added project list page
This commit is contained in:
parent
f1c7948d0a
commit
27b05c2904
@ -31,7 +31,7 @@
|
||||
"eslint": "8.41.0",
|
||||
"eslint-config-next": "13.4.4",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"postcss": "^8.4.24",
|
||||
"postcss": "^8.4.31",
|
||||
"postcss-preset-mantine": "1.8.0",
|
||||
"postcss-simple-vars": "^7.0.1",
|
||||
"prettier": "3.0.3",
|
||||
|
@ -50,7 +50,7 @@ devDependencies:
|
||||
specifier: ^9.0.0
|
||||
version: 9.0.0(eslint@8.41.0)
|
||||
postcss:
|
||||
specifier: ^8.4.24
|
||||
specifier: ^8.4.31
|
||||
version: 8.4.31
|
||||
postcss-preset-mantine:
|
||||
specifier: 1.8.0
|
||||
@ -362,8 +362,8 @@ packages:
|
||||
resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==}
|
||||
dev: true
|
||||
|
||||
/@types/prop-types@15.7.8:
|
||||
resolution: {integrity: sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ==}
|
||||
/@types/prop-types@15.7.9:
|
||||
resolution: {integrity: sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==}
|
||||
|
||||
/@types/react-dom@18.2.4:
|
||||
resolution: {integrity: sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw==}
|
||||
@ -374,12 +374,12 @@ packages:
|
||||
/@types/react@18.2.7:
|
||||
resolution: {integrity: sha512-ojrXpSH2XFCmHm7Jy3q44nXDyN54+EYKP2lBhJ2bqfyPj6cIUW/FZW/Csdia34NQgq7KYcAlHi5184m4X88+yw==}
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.8
|
||||
'@types/scheduler': 0.16.4
|
||||
'@types/prop-types': 15.7.9
|
||||
'@types/scheduler': 0.16.5
|
||||
csstype: 3.1.2
|
||||
|
||||
/@types/scheduler@0.16.4:
|
||||
resolution: {integrity: sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==}
|
||||
/@types/scheduler@0.16.5:
|
||||
resolution: {integrity: sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==}
|
||||
|
||||
/@typescript-eslint/parser@5.62.0(eslint@8.41.0)(typescript@5.0.4):
|
||||
resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==}
|
||||
@ -640,8 +640,8 @@ packages:
|
||||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/caniuse-lite@1.0.30001547:
|
||||
resolution: {integrity: sha512-W7CrtIModMAxobGhz8iXmDfuJiiKg1WADMO/9x7/CLNin5cpSbuBjooyoIUVB5eyCc36QuTVlkVa1iB2S5+/eA==}
|
||||
/caniuse-lite@1.0.30001551:
|
||||
resolution: {integrity: sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==}
|
||||
dev: false
|
||||
|
||||
/chalk@4.1.2:
|
||||
@ -813,7 +813,7 @@ packages:
|
||||
is-string: 1.0.7
|
||||
is-typed-array: 1.1.12
|
||||
is-weakref: 1.0.2
|
||||
object-inspect: 1.12.3
|
||||
object-inspect: 1.13.0
|
||||
object-keys: 1.1.1
|
||||
object.assign: 4.1.4
|
||||
regexp.prototype.flags: 1.5.1
|
||||
@ -1778,7 +1778,7 @@ packages:
|
||||
'@next/env': 13.4.4
|
||||
'@swc/helpers': 0.5.1
|
||||
busboy: 1.6.0
|
||||
caniuse-lite: 1.0.30001547
|
||||
caniuse-lite: 1.0.30001551
|
||||
postcss: 8.4.14
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
@ -1803,8 +1803,8 @@ packages:
|
||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
/object-inspect@1.12.3:
|
||||
resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
|
||||
/object-inspect@1.13.0:
|
||||
resolution: {integrity: sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==}
|
||||
dev: true
|
||||
|
||||
/object-keys@1.1.1:
|
||||
@ -2278,7 +2278,7 @@ packages:
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
get-intrinsic: 1.2.1
|
||||
object-inspect: 1.12.3
|
||||
object-inspect: 1.13.0
|
||||
dev: true
|
||||
|
||||
/slash@3.0.0:
|
||||
|
BIN
public/assets/project-1.png
Normal file
BIN
public/assets/project-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 710 KiB |
BIN
public/assets/project-2.png
Normal file
BIN
public/assets/project-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 84 KiB |
BIN
public/assets/project-3.png
Normal file
BIN
public/assets/project-3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
@ -12,7 +12,10 @@ export const metadata: Metadata = {
|
||||
url: 'https://github.com/Refansa',
|
||||
},
|
||||
],
|
||||
title: 'Refansa - Software Developer',
|
||||
title: {
|
||||
template: 'Refansa - Software Developer | %s',
|
||||
default: 'Refansa - Software Developer',
|
||||
},
|
||||
description: "Refansa's portfolio website",
|
||||
viewport: 'width=device-width, initial-scale=1',
|
||||
colorScheme: 'dark',
|
||||
|
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { AppShell, Container, Stack, rem } from '@mantine/core'
|
||||
import { AppShell, Container, Stack } from '@mantine/core'
|
||||
import Introduction from '../partials/Introduction'
|
||||
import About from '../partials/About'
|
||||
import Navbar from '../components/Navbar'
|
||||
@ -19,7 +19,7 @@ export default function HomePage() {
|
||||
</AppShell.Header>
|
||||
<AppShell.Main>
|
||||
<Container
|
||||
size={rem(1920)}
|
||||
size={1920}
|
||||
px={{ base: '0rem', lg: '4rem', xl: '8rem' }}>
|
||||
<Stack>
|
||||
<Introduction />
|
||||
|
45
src/app/projects/page.tsx
Normal file
45
src/app/projects/page.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { Metadata } from 'next'
|
||||
import Project from './project'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Projects',
|
||||
}
|
||||
|
||||
const projectLists = [
|
||||
{
|
||||
title: 'AmanaTax',
|
||||
description: 'A video course website to learn about taxes.',
|
||||
imgSrc: '/assets/project-1.png',
|
||||
alt: 'AmanaTax Homepage',
|
||||
tags: ['internship project', 'laravel', 'completed'],
|
||||
},
|
||||
{
|
||||
title: 'Koperasi',
|
||||
description: 'Cooperatives website that accept online transactions.',
|
||||
codeSrc: 'https://github.com/Refansa/koperasi',
|
||||
imgSrc: '/assets/project-2.png',
|
||||
alt: 'Koperasi Homepage',
|
||||
tags: ['school project', 'vue.js', 'completed'],
|
||||
},
|
||||
{
|
||||
title: 'RMBG',
|
||||
description:
|
||||
'Easily remove background from an image with one simple click.',
|
||||
codeSrc: 'https://github.com/Refansa/rmbg',
|
||||
imgSrc: '/assets/project-3.png',
|
||||
alt: 'RMBG Website',
|
||||
tags: ['personal project', 'react.js', 'completed'],
|
||||
},
|
||||
{
|
||||
title: 'This Portfolio',
|
||||
description: 'My own portfolio!',
|
||||
codeSrc: 'https://github.com/Refansa/portfolio',
|
||||
imgSrc: '/assets/project-4.png',
|
||||
alt: 'Portfolio Homepage',
|
||||
tags: ['personal project', 'react', 'in progress'],
|
||||
},
|
||||
]
|
||||
|
||||
export default function ProjectLists() {
|
||||
return <Project projectLists={projectLists} />
|
||||
}
|
34
src/app/projects/project.tsx
Normal file
34
src/app/projects/project.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
'use client'
|
||||
|
||||
import { AppShell, Container, Stack } from '@mantine/core'
|
||||
import Footer from '../../components/Footer'
|
||||
import Navbar from '../../components/Navbar'
|
||||
import Projects, { ProjectItemProps } from '../../partials/Projects'
|
||||
|
||||
export default function Project({
|
||||
projectLists,
|
||||
}: {
|
||||
projectLists: ProjectItemProps[]
|
||||
}) {
|
||||
return (
|
||||
<AppShell
|
||||
withBorder={false}
|
||||
padding={'xl'}
|
||||
header={{ height: 72 }}
|
||||
className={'shell-root'}>
|
||||
<AppShell.Header>
|
||||
<Navbar />
|
||||
</AppShell.Header>
|
||||
<AppShell.Main>
|
||||
<Container
|
||||
size={1920}
|
||||
px={{ base: '0rem', lg: '4rem', xl: '8rem' }}>
|
||||
<Stack>
|
||||
<Projects projectLists={projectLists} />
|
||||
<Footer />
|
||||
</Stack>
|
||||
</Container>
|
||||
</AppShell.Main>
|
||||
</AppShell>
|
||||
)
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import { Button } from '@mantine/core'
|
||||
import Link from 'next/link'
|
||||
import { MouseEventHandler } from 'react'
|
||||
|
||||
interface NavLinkProps {
|
||||
@ -10,7 +11,7 @@ interface NavLinkProps {
|
||||
function NavLink({ content, href, onClick }: NavLinkProps) {
|
||||
return (
|
||||
<Button
|
||||
component={'a'}
|
||||
component={Link}
|
||||
variant='subtle'
|
||||
size='md'
|
||||
onClick={onClick}
|
||||
|
@ -21,7 +21,7 @@ export default function NavMobile() {
|
||||
/>
|
||||
<NavLink
|
||||
content='Projects'
|
||||
href='https://github.com/Refansa?tab=repositories'
|
||||
href='/projects'
|
||||
/>
|
||||
</Stack>
|
||||
</Drawer>
|
||||
|
@ -14,11 +14,11 @@ function Navbar() {
|
||||
<Group visibleFrom='sm'>
|
||||
<NavLink
|
||||
content='About'
|
||||
href='/#about'
|
||||
href='/'
|
||||
/>
|
||||
<NavLink
|
||||
content='Projects'
|
||||
href='https://github.com/Refansa?tab=repositories'
|
||||
href='/projects'
|
||||
/>
|
||||
</Group>
|
||||
<NavMobile />
|
||||
|
@ -1,3 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import { motion, useAnimation } from 'framer-motion'
|
||||
import { useEffect } from 'react'
|
||||
import { useInView } from 'react-intersection-observer'
|
||||
|
@ -1,12 +1,3 @@
|
||||
.grayscale {
|
||||
filter: grayscale(1);
|
||||
}
|
||||
|
||||
/* Offset the anchor hashtag link
|
||||
*/
|
||||
.anchor:target::before {
|
||||
content: '';
|
||||
display: block;
|
||||
height: 160px;
|
||||
margin-top: -160px;
|
||||
}
|
||||
|
@ -14,10 +14,7 @@ import SlideUpWhenVisible from '../hooks/slideUpWhenVisible'
|
||||
function About() {
|
||||
return (
|
||||
<SlideUpWhenVisible>
|
||||
<Box
|
||||
id='about'
|
||||
className={classes.anchor}
|
||||
my='xl'>
|
||||
<Box my='xl'>
|
||||
<SimpleGrid
|
||||
cols={{ base: 1, sm: 2 }}
|
||||
spacing={{ base: 'sm', md: 'md', lg: 'lg' }}>
|
||||
|
@ -24,7 +24,7 @@ interface ItemGridProps {
|
||||
text: string
|
||||
}
|
||||
|
||||
const ItemGrid = ({ icon, text }: ItemGridProps) => {
|
||||
const Item = ({ icon, text }: ItemGridProps) => {
|
||||
return (
|
||||
<Paper
|
||||
w={100}
|
||||
@ -64,67 +64,67 @@ export default function Experiences() {
|
||||
mt='xl'
|
||||
w={{ base: 240, sm: 480, md: 720, lg: 960 }}
|
||||
cols={{ base: 2, sm: 4, md: 6, lg: 8 }}>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandHtml5 />}
|
||||
text='HTML'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandCss3 />}
|
||||
text='CSS'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandJavascript />}
|
||||
text='Javascript'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandPhp />}
|
||||
text='PHP'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandPython />}
|
||||
text='Python'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandMysql />}
|
||||
text='MySQL'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandLaravel />}
|
||||
text='Laravel'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandNodejs />}
|
||||
text='NodeJS'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandReact />}
|
||||
text='React'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandVue />}
|
||||
text='Vue'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandTailwind />}
|
||||
text='Tailwind'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandSass />}
|
||||
text='Sass'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandMantine />}
|
||||
text='Mantine'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandNextjs />}
|
||||
text='NextJS'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandPrisma />}
|
||||
text='Prisma'
|
||||
/>
|
||||
<ItemGrid
|
||||
<Item
|
||||
icon={<IconBrandSupabase />}
|
||||
text='Supabase'
|
||||
/>
|
||||
|
119
src/partials/Projects.tsx
Normal file
119
src/partials/Projects.tsx
Normal file
@ -0,0 +1,119 @@
|
||||
import {
|
||||
AspectRatio,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Group,
|
||||
Image,
|
||||
SimpleGrid,
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
} from '@mantine/core'
|
||||
import { IconSourceCode } from '@tabler/icons-react'
|
||||
import SlideUpWhenVisible from '../hooks/slideUpWhenVisible'
|
||||
|
||||
export interface ProjectItemProps {
|
||||
alt?: string
|
||||
codeSrc?: any
|
||||
description: string
|
||||
imgSrc?: any
|
||||
tags?: string[]
|
||||
title: string
|
||||
}
|
||||
|
||||
const ProjectItem = ({
|
||||
alt,
|
||||
codeSrc,
|
||||
description,
|
||||
imgSrc,
|
||||
tags,
|
||||
title,
|
||||
}: ProjectItemProps) => {
|
||||
return (
|
||||
<Card
|
||||
shadow='sm'
|
||||
padding='lg'>
|
||||
<Card.Section>
|
||||
<AspectRatio
|
||||
ratio={1366 / 609}
|
||||
mah={160}
|
||||
my='auto'>
|
||||
<Image
|
||||
src={imgSrc}
|
||||
alt={alt}
|
||||
/>
|
||||
</AspectRatio>
|
||||
</Card.Section>
|
||||
|
||||
<Text
|
||||
fw='bold'
|
||||
size='lg'
|
||||
mt='md'>
|
||||
{title}
|
||||
</Text>
|
||||
{tags ? (
|
||||
<Group
|
||||
gap='xs'
|
||||
my='md'>
|
||||
{tags.map((tag) => {
|
||||
return (
|
||||
<Badge
|
||||
key={title}
|
||||
radius='xs'
|
||||
variant='outline'>
|
||||
{tag}
|
||||
</Badge>
|
||||
)
|
||||
})}
|
||||
</Group>
|
||||
) : null}
|
||||
<Text
|
||||
size='sm'
|
||||
c='dimmed'
|
||||
mb='md'>
|
||||
{description}
|
||||
</Text>
|
||||
{codeSrc ? (
|
||||
<Button
|
||||
mt='auto'
|
||||
component='a'
|
||||
href={codeSrc}
|
||||
target='_blank'
|
||||
leftSection={<IconSourceCode />}
|
||||
variant='light'>
|
||||
Source Code
|
||||
</Button>
|
||||
) : null}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Projects({
|
||||
projectLists,
|
||||
}: {
|
||||
projectLists: ProjectItemProps[]
|
||||
}) {
|
||||
return (
|
||||
<SlideUpWhenVisible>
|
||||
<Box my='xl'>
|
||||
<Stack align='center'>
|
||||
<Title ta='center'>My Projects</Title>
|
||||
<SimpleGrid
|
||||
mt='xl'
|
||||
cols={{ base: 1, sm: 2, md: 3 }}>
|
||||
{projectLists.map((project) => {
|
||||
return (
|
||||
<ProjectItem
|
||||
key={project.title}
|
||||
{...project}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
</Box>
|
||||
</SlideUpWhenVisible>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user