├── .eslintrc.cjs
├── .gitignore
├── README.md
├── index.html
├── note.md
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
└── icon.png
├── src
├── App.jsx
├── assets
│ ├── amikom-kantin.png
│ ├── profile-photo.png
│ ├── react-openai.png
│ └── snake-amazon.png
├── components
│ ├── About
│ │ ├── AboutContent.jsx
│ │ ├── AboutMe.jsx
│ │ ├── Card.jsx
│ │ └── SkillsContent.jsx
│ ├── Footer
│ │ ├── Copyright.jsx
│ │ ├── Footer.jsx
│ │ └── SocialIcon.jsx
│ ├── Header
│ │ ├── Header.jsx
│ │ ├── NavList.jsx
│ │ └── ThemeToggle.jsx
│ ├── Hero
│ │ └── Hero.jsx
│ ├── Projects
│ │ ├── MyProjects.jsx
│ │ ├── OpenLink.jsx
│ │ ├── ProjectDetails.jsx
│ │ ├── ProjectList.jsx
│ │ └── Thumbnail.jsx
│ └── Services
│ │ ├── Services.jsx
│ │ └── ServicesList.jsx
├── index.css
├── main.jsx
└── pages
│ ├── AboutPage.jsx
│ ├── HomePage.jsx
│ ├── NotFoundPage.jsx
│ └── ProjectPage.jsx
├── tailwind.config.js
├── vercel.json
└── vite.config.js
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:react/recommended',
7 | 'plugin:react/jsx-runtime',
8 | 'plugin:react-hooks/recommended',
9 | ],
10 | ignorePatterns: ['dist', '.eslintrc.cjs'],
11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
12 | settings: { react: { version: '18.2' } },
13 | plugins: ['react-refresh'],
14 | rules: {
15 | 'react-refresh/only-export-components': [
16 | 'warn',
17 | { allowConstantExport: true },
18 | ],
19 | },
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Personal Website
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/note.md:
--------------------------------------------------------------------------------
1 | 1. Create new project Vite
2 |
3 | ```
4 | pnpm create vite@latest .
5 | or
6 | pnpm create vite@latest project-name
7 | ```
8 |
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "portfolio",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0",
15 | "react-ga4": "^2.1.0",
16 | "react-router-dom": "^6.21.1",
17 | "react-simple-typewriter": "^5.0.1",
18 | "tailwind-hamburgers": "^1.3.5"
19 | },
20 | "devDependencies": {
21 | "@types/react": "^18.2.43",
22 | "@types/react-dom": "^18.2.17",
23 | "@vitejs/plugin-react": "^4.2.1",
24 | "autoprefixer": "^10.4.16",
25 | "eslint": "^8.55.0",
26 | "eslint-plugin-react": "^7.33.2",
27 | "eslint-plugin-react-hooks": "^4.6.0",
28 | "eslint-plugin-react-refresh": "^0.4.5",
29 | "postcss": "^8.4.33",
30 | "tailwindcss": "^3.4.0",
31 | "vite": "^5.0.8"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hamdanzull/Personal-Website/a9abce9c5a50be8b802517844b01a8ccc3b904d6/public/icon.png
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react"
2 | import { BrowserRouter as Router, Routes, Route } from "react-router-dom"
3 | import HomePage from "./pages/HomePage"
4 | import ProjectPage from "./pages/ProjectPage"
5 | import NotFoundPage from "./pages/NotFoundPage"
6 | import AboutPage from "./pages/AboutPage"
7 | import ReactGA from "react-ga4";
8 |
9 | const trackingId = "G-ETW3F6K6VY"
10 | ReactGA.initialize(trackingId);
11 |
12 | export default function App() {
13 |
14 | useEffect(() => {
15 | ReactGA.send({ hitType: "pageview", page: "/" });
16 | }, [])
17 |
18 | return (
19 | <>
20 |
21 |
22 | } />
23 | } />
24 | } />
25 | } />
26 |
27 |
28 | >
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/src/assets/amikom-kantin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hamdanzull/Personal-Website/a9abce9c5a50be8b802517844b01a8ccc3b904d6/src/assets/amikom-kantin.png
--------------------------------------------------------------------------------
/src/assets/profile-photo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hamdanzull/Personal-Website/a9abce9c5a50be8b802517844b01a8ccc3b904d6/src/assets/profile-photo.png
--------------------------------------------------------------------------------
/src/assets/react-openai.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hamdanzull/Personal-Website/a9abce9c5a50be8b802517844b01a8ccc3b904d6/src/assets/react-openai.png
--------------------------------------------------------------------------------
/src/assets/snake-amazon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hamdanzull/Personal-Website/a9abce9c5a50be8b802517844b01a8ccc3b904d6/src/assets/snake-amazon.png
--------------------------------------------------------------------------------
/src/components/About/AboutContent.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react-refresh/only-export-components */
2 | /* eslint-disable react/prop-types */
3 | import { useTypewriter, Cursor } from 'react-simple-typewriter'
4 |
5 | export const text = [`Hi everyone 👋\nI'm Muhammad Hamdan Zulfa, a 20-year-old Software Engineer and a student at AMIKOM University based in Yogyakarta, Indonesia. Every day, I'm immersed in writing lines of code. Bugs and errors seem to be my constant companions.`, `I'm always curious to learn something new, especially in web technology and design. I fall in love with JavaScript and TypeScript. Not just coding, I also took care of what I wrote. Writing clean code and make me comfortable.`]
6 |
7 | export function AboutContent({ aboutToggle }) {
8 | const [typing] = useTypewriter({
9 | words: text,
10 | loop: 0,
11 | typeSpeed: 20,
12 | deleteSpeed: 20,
13 | delaySpeed: 3000
14 | })
15 | return (
16 | <>
17 | hamdanzull@Host:~$ node aboutMe.js
18 |
19 | {aboutToggle ? typing : 'See you 👋'}
20 |
21 |
22 | >
23 | )
24 | }
--------------------------------------------------------------------------------
/src/components/About/AboutMe.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | import { AboutContent } from './AboutContent';
3 | import Card from './Card';
4 | import SkillsContent from './SkillsContent';
5 |
6 | export default function AboutMe({ aboutToggle }) {
7 | return (
8 |
9 |
10 |
11 | About Me
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | )
25 | }
--------------------------------------------------------------------------------
/src/components/About/Card.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | export default function Card({ children, title }) {
3 | return (
4 |
5 |
13 |
14 | {children}
15 |
16 |
17 | )
18 | }
--------------------------------------------------------------------------------
/src/components/About/SkillsContent.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | const skills = [
3 | { component: HtmlIcon, size: 32, label: "01.png" },
4 | { component: CssIcon, size: 32, label: "02.png" },
5 | { component: JsIcon, size: 32, label: "03.png" },
6 | { component: BootstrapIcon, size: 32, label: "04.png" },
7 | { component: TailwindIcon, size: 32, label: "05.png" },
8 | { component: NodeIcon, size: 32, label: "06.png" },
9 | { component: ReactIcon, size: 32, label: "07.png" },
10 | { component: ExpressIcon, size: 32, label: "08.png" },
11 | { component: NextIcon, size: 32, label: "09.png" },
12 | { component: ViteIcon, size: 32, label: "10.png" },
13 | { component: MySqlIcon, size: 32, label: "11.png" },
14 | { component: PostgresqlIcon, size: 32, label: "12.png" },
15 | ];
16 |
17 | export default function SkillsContent() {
18 | return (
19 | <>
20 | hamdanzull@Host:~$ ls skills/*.png
21 |
22 | {skills.map((skill, index) => (
23 |
24 |
25 | {skill.label}
26 |
27 | ))}
28 |
29 | >
30 | )
31 | }
32 |
33 | function HtmlIcon({ size }) {
34 | return (
35 |
36 |
37 |
38 | )
39 | }
40 |
41 | function CssIcon({ size }) {
42 | return (
43 |
44 |
45 |
46 | )
47 | }
48 |
49 | function JsIcon({ size }) {
50 | return (
51 |
52 |
53 |
54 | )
55 | }
56 |
57 | function TailwindIcon({ size }) {
58 | return (
59 |
60 |
61 |
62 | )
63 | }
64 |
65 | function BootstrapIcon({ size }) {
66 | return (
67 |
68 |
69 |
70 | )
71 | }
72 |
73 | function NodeIcon({ size }) {
74 | return (
75 |
76 |
77 |
78 | )
79 | }
80 |
81 | function ReactIcon({ size }) {
82 | return (
83 |
84 |
85 |
86 | )
87 | }
88 |
89 | function ExpressIcon({ size }) {
90 | return (
91 |
92 |
93 |
94 | )
95 | }
96 |
97 | function ViteIcon({ size }) {
98 | return (
99 |
100 |
101 |
102 | )
103 | }
104 |
105 | function NextIcon({ size }) {
106 | return (
107 |
108 |
109 |
110 | )
111 | }
112 |
113 | function MySqlIcon({ size }) {
114 | return (
115 |
116 |
117 |
118 | )
119 | }
120 |
121 | function PostgresqlIcon({ size }) {
122 | return (
123 |
124 |
125 |
126 | )
127 | }
128 |
--------------------------------------------------------------------------------
/src/components/Footer/Copyright.jsx:
--------------------------------------------------------------------------------
1 | export default function Copyright() {
2 |
3 | return (
4 | <>
5 | © 2023-2024 hamdanzull - All Rights Reserved.
6 | >
7 | )
8 | }
--------------------------------------------------------------------------------
/src/components/Footer/Footer.jsx:
--------------------------------------------------------------------------------
1 | import SocialIcon from './SocialIcon'
2 | import Copyright from './Copyright'
3 |
4 | export default function Footer() {
5 | return (
6 |
12 | )
13 | }
--------------------------------------------------------------------------------
/src/components/Footer/SocialIcon.jsx:
--------------------------------------------------------------------------------
1 | const socials = [
2 | { icon: LinkedinIcon, url: 'https://linkedin.com/in/hamdanzull' },
3 | { icon: GithubIcon, url: 'https://www.instagram.com/hamdanzull' },
4 | { icon: InstagramIcon, url: 'https://www.instagram.com/hamdanzull' },
5 | { icon: FacebookIcon, url: 'https://www.facebook.com/hamdanzull' },
6 | ];
7 |
8 | export default function SocialIcon() {
9 | return (
10 |
11 |
Connect with me
12 |
13 | {socials.map((social, idx) => (
14 |
15 |
16 |
17 |
18 |
19 | ))}
20 |
21 |
22 | )
23 | }
24 |
25 | function LinkedinIcon() {
26 | return (
27 |
28 |
29 |
30 | )
31 | }
32 |
33 | function GithubIcon() {
34 | return (
35 |
36 |
37 |
38 | )
39 | }
40 |
41 | function InstagramIcon() {
42 | return (
43 |
44 |
45 |
46 | )
47 | }
48 |
49 | function FacebookIcon() {
50 | return (
51 |
52 |
53 |
54 | )
55 | }
--------------------------------------------------------------------------------
/src/components/Header/Header.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import ThemeToggle from './ThemeToggle';
3 | import NavList from './NavList';
4 |
5 | export default function Header() {
6 | const [menuToggle, setMenuToggle] = useState(false);
7 | const handleMenu = () => setMenuToggle(!menuToggle);
8 |
9 | return (
10 |
35 | )
36 | }
--------------------------------------------------------------------------------
/src/components/Header/NavList.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | import { NavLink } from 'react-router-dom';
3 |
4 |
5 | const navLinks = [
6 | { to: '/', text: 'Home' },
7 | { to: '/about', text: 'About' },
8 | { to: '/projects', text: 'Projects' },
9 | { to: '/services', text: 'Services' },
10 | ];
11 |
12 | export default function NavList({ menuToggle }) {
13 | return (
14 |
15 |
16 | {navLinks.map((link, index) => (
17 |
18 | `block cursor-pointer text-center w-screen md:w-auto py-3 md:py-0 transition-colors duration-300 ${isActive ? 'text-red-500 dark:text-sky-500 bg-[#d6d9de] dark:bg-[#121c2a] md:bg-transparent dark:md:bg-transparent' : 'hover:text-gray-700 dark:hover:text-gray-300'}`
20 | }>{link.text}
21 |
22 | ))}
23 |
24 |
25 | )
26 | }
--------------------------------------------------------------------------------
/src/components/Header/ThemeToggle.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | /* eslint-disable no-unused-vars */
3 | import { useEffect, useState } from "react";
4 |
5 | export default function ThemeToggle() {
6 | const [theme, setTheme] = useState(() => {
7 | return localStorage.getItem('theme') || 'light';
8 | });
9 |
10 | const handleSetTheme = () => {
11 | setTheme((prevTheme) => (
12 | prevTheme === 'light' ? 'dark' : 'light'
13 | ));
14 | };
15 |
16 | useEffect(() => {
17 | localStorage.setItem('theme', theme);
18 | document.documentElement.className = theme;
19 | }, [theme]);
20 |
21 | return (
22 | handleSetTheme()}
23 | className="h-[40px] w-[40px] active:bg-gray-300 dark:active:bg-gray-700 rounded-full relative">
24 |
25 |
26 |
27 |
28 |
29 |
30 | )
31 | }
--------------------------------------------------------------------------------
/src/components/Hero/Hero.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/no-unescaped-entities */
2 | /* eslint-disable react/prop-types */
3 | import profile from '../../assets/profile-photo.png'
4 |
5 | export default function Hero({ aboutToggle, handleAbout }) {
6 | return (
7 |
8 |
9 |
10 |
13 |
14 |
15 |
Haloo! I'm
16 |
17 | Muh. Hamdan Zulfa
18 |
19 |
20 |
21 |
A beginner enthusiast exploring modern tech, especially in software development.
22 |
24 | {aboutToggle ? 'Show less' : 'Learn more'}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | )
33 | }
--------------------------------------------------------------------------------
/src/components/Projects/MyProjects.jsx:
--------------------------------------------------------------------------------
1 | import { useNavigate } from 'react-router-dom'
2 | import OpenLink from './OpenLink'
3 | import ProjectDetails from './ProjectDetails'
4 | import ProjectList from './ProjectList'
5 | import Thumbnail from './Thumbnail'
6 | // project image:
7 | import snakeAmazon from '../../assets/snake-amazon.png'
8 | import reactOpenai from '../../assets/react-openai.png'
9 |
10 | const projects = [
11 | {
12 | id: 1,
13 | title: 'Snake Amazon',
14 | image: snakeAmazon,
15 | stacks: 'Pure HTML, CSS and Vanilla JS',
16 | description: 'A classic arcade-style game where you guide a snake through a grid, eating apples to grow longer while avoiding collisions. Simple and challenging, it revives the timeless joy of classic games.',
17 | link: 'https://wdp-12.github.io/Finalproject1_Kelompok1/',
18 | },
19 | {
20 | id: 3,
21 | title: 'React OpenAI',
22 | image: reactOpenai,
23 | stacks: 'React & Tailwind CSS',
24 | description: "This project marks my introduction to React as I develop a chatbot application to interact with OpenAI. It represents my first step in mastering React and enhancing my programming skills.",
25 | link: 'https://openai.hamdanzull.my.id'
26 | }
27 | ]
28 |
29 | export default function MyProjects() {
30 | const direct = useNavigate();
31 | return (
32 |
33 |
34 |
My Projects
35 |
36 | {projects.map(project => (
37 |
38 |
42 |
43 |
44 |
45 |
46 | ))}
47 |
48 |
direct('/projects')} className='mt-5 relative left-1/2 -translate-x-1/2 font-semibold flex items-center gap-1.5 text-red-500 dark:text-sky-500 border-b-2 border-transparent hover:border-red-400 hover:dark:border-sky-500 transition'>
49 | View more projects
50 |
51 |
52 |
53 |
54 | )
55 | }
--------------------------------------------------------------------------------
/src/components/Projects/OpenLink.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | export default function OpenLink({ link }) {
3 | return (
4 |
6 | Demo App
7 |
8 |
9 | )
10 | }
--------------------------------------------------------------------------------
/src/components/Projects/ProjectDetails.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | export default function ProjectDetails({ project, children }) {
3 | return (
4 |
5 |
{project.title}
6 |
Stacks: {project.stacks}
7 |
{project.description}
8 | {children}
9 |
10 | )
11 | }
--------------------------------------------------------------------------------
/src/components/Projects/ProjectList.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | export default function ProjectList({ children }) {
3 | return (
4 | <>
5 |
6 | {children}
7 |
8 | >
9 | )
10 | }
--------------------------------------------------------------------------------
/src/components/Projects/Thumbnail.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/prop-types */
2 | export default function Thumbnail({ image, title }) {
3 | return (
4 |
5 |
7 |
8 | )
9 | }
--------------------------------------------------------------------------------
/src/components/Services/Services.jsx:
--------------------------------------------------------------------------------
1 | import ServicesList from "./ServicesList"
2 |
3 |
4 | export default function Services() {
5 | return (
6 |
7 |
8 |
9 | Services
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | )
18 | }
--------------------------------------------------------------------------------
/src/components/Services/ServicesList.jsx:
--------------------------------------------------------------------------------
1 | const services = [
2 | { icon: InstallationIcon, name: 'Installation', desc: 'Offering hardware and software installation (Operating Systems), applications, games, and network infrastructure.' },
3 | { icon: WebDevIcon, name: 'Web Development', desc: 'Crafting personalized portfolio websites, institutional sites, online stores (E-commerce), academic projects, and more.' },
4 | { icon: DesignIcon, name: 'Design', desc: 'Creating website or app designs & prototypes, brand logos, product designs, mockups, advertisements and more.' },
5 | { icon: AutomationIcon, name: 'Automation', desc: 'Providing Telegram & WhatsApp BOT services to enhance online business services, scraping data, and more.' },
6 | ]
7 |
8 | export default function ServicesList() {
9 | return (
10 | services.map((service, idx) => (
11 |
12 |
13 |
14 |
15 |
16 |
{service.name}
17 |
{service.desc}
18 |
19 |
20 | ))
21 | )
22 | }
23 |
24 | function InstallationIcon() {
25 | return (
26 |
27 |
28 |
29 |
30 | )
31 | }
32 |
33 | function WebDevIcon() {
34 | return (
35 |
36 |
37 |
38 | )
39 | }
40 |
41 | function DesignIcon() {
42 | return (
43 |
44 |
45 |
46 | )
47 | }
48 |
49 | function AutomationIcon() {
50 | return (
51 |
52 |
53 |
54 | )
55 | }
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&family=Montserrat:wght@100;200;300;400;500;600;700;800;900&family=Pacifico&family=Ubuntu&display=swap');
2 |
3 | @tailwind base;
4 | @tailwind components;
5 | @tailwind utilities;
--------------------------------------------------------------------------------
/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App.jsx'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')).render(
7 |
8 |
9 | ,
10 | )
11 |
--------------------------------------------------------------------------------
/src/pages/AboutPage.jsx:
--------------------------------------------------------------------------------
1 | import { text } from "../components/About/AboutContent"
2 | import Card from "../components/About/Card"
3 | import SkillsContent from "../components/About/SkillsContent"
4 | import Header from "../components/Header/Header"
5 | import Footer from "../components/Footer/Footer"
6 |
7 | export default function AboutPage() {
8 | return (
9 | <>
10 |
11 |
12 |
13 |
About Me
14 | {text.map((paragraph, index) => (
15 |
16 | {paragraph}
17 |
18 | ))}
19 |
20 |
21 |
22 |
23 |
24 |
Lorem
25 |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatum voluptate maxime amet modi optio tempora dolorem quibusdam earum? Modi error quae culpa dignissimos dicta tenetur maiores dolores minus impedit voluptatibus voluptatum dolor officia, ab sequi? Fugiat impedit voluptatum quis consequatur molestias tempora, provident ad possimus accusamus recusandae assumenda! Tenetur, doloremque!
26 |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Eveniet tempora molestiae praesentium delectus illum sint id et laborum ipsum quasi, ad possimus consequuntur architecto aperiam dignissimos perspiciatis quas facilis ipsam ex nostrum voluptate! Sint itaque molestiae facilis quae placeat fuga distinctio, neque illo labore nesciunt doloremque eaque, sed fugiat illum optio nemo amet maiores! Quae amet pariatur explicabo voluptatem? Quas laborum error at unde in, enim aut earum praesentium dolor, dignissimos quo a architecto eum.
27 |
28 |
29 |
30 | >
31 | )
32 | }
--------------------------------------------------------------------------------
/src/pages/HomePage.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import MyProjects from '../components/Projects/MyProjects';
3 | import AboutMe from '../components/About/AboutMe';
4 | import Services from '../components/Services/Services';
5 | import Header from '../components/Header/Header';
6 | import Hero from '../components/Hero/Hero';
7 | import Footer from '../components/Footer/Footer';
8 |
9 | export default function HomePage() {
10 | const [aboutToggle, setAboutToggle] = useState(false);
11 | const handleAbout = () => setAboutToggle(!aboutToggle);
12 | return (
13 | <>
14 |
15 |
19 |
20 |
21 |
22 |
23 | >
24 | )
25 | }
--------------------------------------------------------------------------------
/src/pages/NotFoundPage.jsx:
--------------------------------------------------------------------------------
1 | import { useNavigate } from "react-router-dom";
2 | import ThemeToggle from "../components/Header/ThemeToggle";
3 |
4 | export default function NotFoundPage() {
5 | const direct = useNavigate();
6 | return (
7 |
8 |
9 |
10 |
11 |
404
12 |
Page Not Found
13 |
direct('/')} className="font-semibold flex items-center gap-1 text-red-500 dark:text-sky-500 px-4 py-1.5 rounded-full border-[2.5px] border-red-500 dark:border-sky-500 ring-red-300 dark:ring-sky-800 active:ring-4">
14 |
15 | Back To Home
16 |
17 |
18 | )
19 | }
20 |
21 | function HomeIcon() {
22 | return (
23 |
24 |
25 |
26 | )
27 | }
--------------------------------------------------------------------------------
/src/pages/ProjectPage.jsx:
--------------------------------------------------------------------------------
1 | import Footer from "../components/Footer/Footer";
2 | import Header from "../components/Header/Header";
3 | import ProjectList from "../components/Projects/ProjectList";
4 | import Thumbnail from "../components/Projects/Thumbnail";
5 | import ProjectDetails from "../components/Projects/ProjectDetails";
6 | import OpenLink from "../components/Projects/OpenLink";
7 | // project image:
8 | import snakeAmazon from '../assets/snake-amazon.png'
9 | import amikomKantin from '../assets/amikom-kantin.png'
10 | import reactOpenai from '../assets/react-openai.png'
11 |
12 | const projects = [
13 | {
14 | id: 1,
15 | title: 'Snake Amazon',
16 | image: snakeAmazon,
17 | stacks: 'Pure HTML, CSS and Vanilla JS',
18 | description: 'A classic arcade-style game where you guide a snake through a grid, eating apples to grow longer while avoiding collisions. Simple and challenging, it revives the timeless joy of classic games.',
19 | link: 'https://wdp-12.github.io/Finalproject1_Kelompok1/',
20 | },
21 | {
22 | id: 2,
23 | title: 'Amikom Kantin',
24 | image: amikomKantin,
25 | stacks: 'PHP, CSS, JavaScript & MySQL',
26 | description: "Amikom Kantin represents the culmination of my semester's final project—a user-friendly web app streamlining cafeteria interactions, from menu exploration to online ordering and payments.",
27 | link: '/'
28 | },
29 | {
30 | id: 3,
31 | title: 'React OpenAI',
32 | image: reactOpenai,
33 | stacks: 'React & Tailwind CSS',
34 | description: "This project marks my introduction to React as I develop a chatbot application to interact with OpenAI. It represents my first step in mastering React and enhancing my programming skills.",
35 | link: 'https://openai.hamdanzull.my.id'
36 | }
37 | ]
38 |
39 | export default function ProjectPage() {
40 | return (
41 | <>
42 |
43 |
44 |
45 |
My Projects
46 |
47 | My projects reflect my journey in exploring various technologies and problem-solving. From web development to experimenting with data, each project is a step in my learning process. I enjoy creating user-friendly solutions that make a positive impact.
48 |
49 |
50 | {projects.map(project => (
51 |
52 |
56 |
57 |
58 |
59 |
60 | ))}
61 |
62 |
63 |
64 | >
65 | )
66 | }
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | /** @type {import('tailwindcss').Config} */
3 | export default {
4 | content: [
5 | "./index.html",
6 | "./src/**/*.{js,ts,jsx,tsx}",
7 | ],
8 | darkMode: "class",
9 | theme: {
10 | extend: {},
11 | },
12 | plugins: [require('tailwind-hamburgers')],
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "rewrites": [
3 | {
4 | "source": "/(.*)",
5 | "destination": "/"
6 | }
7 | ]
8 | }
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------