[feat] implement json data for project

This commit is contained in:
Alvalen 2023-09-03 20:26:08 +07:00
parent c6aab9074d
commit b64d7fb30d
19 changed files with 284 additions and 109 deletions

View file

@ -9,6 +9,8 @@ import Link from "next/link";
import Button from "@/components/Button";
import Me from "../../public/img/me.jpg";
import MeAbout from "@/public/img/me2.jpg";
import Setup from "@/public/img/setup.jpg";
import ProjectAll from "@/public/img/projects-all.jpg";
import Hr from "@/components/Hr";
// icons
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -115,18 +117,16 @@ const MyPage = () => {
delay: 0.7,
type: "spring",
}}>
<div className=" rounded-full h-auto w-auto md:px-12">
<div className="h-[300px] w-auto">
<div className="rounded-full h-auto w-auto lg:px-12 grayscale hover:grayscale-0">
<Image
src={Me}
layout="fill"
objectFit="cover"
width={400}
height={550}
placeholder="blur"
className="grayscale hover:grayscale-0"
alt="Alvalens"
className="rounded-full w-full h-full object-cover"
/>
</div>
</div>
</motion.div>
</div>
</div>
@ -134,6 +134,7 @@ const MyPage = () => {
<div className="relative md:h-screen w-screen gap-4 flex justify-center items-center flex-col overflow-hidden">
<div className="z-0 mb-48 md:mb-0 md:absolute top-1/4 md:right-[10%] md:-translate-y-16 ">
<motion.div
className="bg-slate-300 rounded-sm h-[400px] md:h-[600px] w-[80vw] md:w-[30vw] grayscale hover:grayscale-0"
initial={{
x: 300,
opacity: 0,
@ -147,8 +148,7 @@ const MyPage = () => {
transition={{
delay: 0.5,
type: "spring",
}}
className="bg-slate-300 rounded-sm h-[400px] md:h-[600px] w-[80vw] md:w-[30vw] grayscale hover:grayscale-0 ">
}}>
<Image
src={MeAbout}
layout="fill"
@ -160,7 +160,7 @@ const MyPage = () => {
</div>
<div className="z-10 w-full absolute md:w-auto md:left-[10%] top-[60%] md:top-1/3 col-span-2 flex flex-col justify-center items-start md:items-start text-start px-10 py-5">
<motion.h1
className="text-black text-5xl md:text-8xl font-bold"
className="bg-white md:bg-transparent bg-opacity-50 px-3 md-px-0 text-black text-5xl md:text-8xl font-bold"
initial={{ x: -100, opacity: 0 }}
whileInView={{ x: 0, opacity: 1 }}
transition={{
@ -201,7 +201,7 @@ const MyPage = () => {
<div className="relative md:h-screen w-screen gap-4 p-10 flex justify-center items-center flex-col overflow-hidden">
<div className="z-0 mb-48 md:mb-0 md:absolute top-1/4 md:right-[10%] md:-translate-y-16 ">
<motion.div
className="bg-slate-300 rounded-sm h-[400px] md:h-[600px] w-[80vw] md:w-[30vw] "
className="bg-slate-300 rounded-sm h-[400px] md:h-[600px] w-[80vw] md:w-[30vw] grayscale hover:grayscale-0"
initial={{
x: 300,
opacity: 0,
@ -215,11 +215,19 @@ const MyPage = () => {
transition={{
delay: 0.5,
type: "spring",
}}></motion.div>
}}>
<Image
src={ProjectAll}
layout="fill"
className="object-cover"
alt="Alvalens Setup"
placeholder="blur"
/>
</motion.div>
</div>
<div className="z-10 w-full absolute md:w-auto md:left-[10%] top-[60%] md:top-1/3 col-span-2 flex flex-col justify-center items-start md:items-start text-start px-10 py-5">
<motion.h1
className="text-black text-5xl md:text-8xl font-bold"
className="bg-white bg-opacity-50 px-3 md-px-0 text-black md:bg-none text-5xl md:text-8xl font-bold"
initial={{ x: -100, opacity: 0 }}
whileInView={{ x: 0, opacity: 1 }}
transition={{
@ -259,7 +267,15 @@ const MyPage = () => {
<div className="section">
<div className="relative md:h-screen w-screen gap-4 p-10 flex justify-center items-center flex-col">
<div className="z-0 mb-48 md:mb-0 md:absolute top-1/4 md:right-[10%] md:-translate-y-16 ">
<div className="bg-slate-300 rounded-sm h-[400px] md:h-[600px] w-[80vw] md:w-[30vw]"></div>
<div className="bg-slate-300 rounded-sm h-[400px] md:h-[600px] w-[80vw] md:w-[30vw] grayscale hover:grayscale-0">
<Image
src={Setup}
layout="fill"
className="object-cover"
alt="Alvalens Setup"
placeholder="blur"
/>
</div>
</div>
<div className="z-10 w-full absolute md:w-auto md:left-[10%] top-[60%] md:top-1/3 col-span-2 flex flex-col justify-center items-start md:items-start text-start px-10 overflow-hidden">
<motion.h1

15
app/about/layout.js Normal file
View file

@ -0,0 +1,15 @@
// generate layour with footer
import Footer from "@/components/Footer";
export const metadata = {
title: "Alvalens | About",
};
export default function Layout({ children }) {
return (
<>
{children}
<Footer />
</>
);
}

View file

@ -4,13 +4,12 @@ import Link from "next/link";
import { motion } from "framer-motion";
import Button from "@/components/Button";
import Image from "next/legacy/image";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
// images
import Me1 from "@/public/img/me1.jpg";
import Me2 from "@/public/img/me2.jpg";
import Me3 from "@/public/img/me3.jpg";
import Hr from "@/components/Hr";
export default function Page() {
useEffect(() => {
window.scrollTo(0, 0);
@ -35,15 +34,12 @@ export default function Page() {
/>
</motion.div>
</div>
<div className="z-10 w-full absolute md:w-auto md:left-[10%] top-[60%] md:top-1/3 col-span-2 flex flex-col justify-center items-start md:items-start text-start px-10">
<div className="z-10 w-full absolute md:w-auto md:left-[10%] top-[60%] md:top-1/3 col-span-2 flex flex-col justify-center items-start md:items-start text-start px-10 pt-4 backdrop-filter backdrop-blur-sm md:backdrop-blur-none bg-gray-100 bg-opacity-50 md:bg-transparent md:pt-0">
<h1 className="text-5xl md:text-8xl font-bold">
About Me
</h1>
<div className="flex justify-center items-center flex-col my-5 ">
<div className="bg-gray-700 w-20 h-1 rounded-full mb-2"></div>
<div className="bg-gray-700 w-20 h-1 rounded-full translate-x-14"></div>
</div>
<p className="title text-xl mt-4 tracking-wider text-gray-500 leading-[1.7rem] mb-5">
<Hr />
<p className="title text-xl mt-4 tracking-wider text-gray-700 leading-[1.7rem] mb-5 ">
A brief introduction about me and my interest.
</p>
<motion.div
@ -194,13 +190,6 @@ export default function Page() {
</p>
</motion.div>
</div>
{/* <div className="mt-16 flex flex-col justify-start items-center w-full pl-12 md:pl-32">
<div className="flex justify-center items-center flex-col my-5 self-start ">
<div className="bg-gray-700 w-28 h-1 rounded-full mb-3 self-start"></div>
<div className="bg-gray-700 w-28 h-1 rounded-full translate-x-12"></div>
<h1 className="text-3xl font-bold mt-3">Tech Stack</h1>
</div>
</div> */}
<div className=" w-screen mx-auto container gap-4 p-10 grid grid-cols-1 md:grid-cols-2 mt-10 mb-24">
<motion.div
className="flex justify-center items-center flex-col mb-5 "
@ -445,32 +434,6 @@ export default function Page() {
</p>
</motion.div>
</div>
<div className="flex justify-center items-center flex-col mt-5 self-start min-h-[50vh] bg-gray-200">
<Link href="/#contact">
<motion.h1
className="text-5xl font-bold mt-3 tracking-widest hover:underline"
initial={{
opacity: 0,
y: -200,
}}
whileInView={{
opacity: 1,
y: 0,
}}
transition={{
delay: 0.7,
type: "spring",
}}>
Get In Touch{" "}
<FontAwesomeIcon
icon={faArrowRight}
className="text-5xl ml-2"
/>
</motion.h1>
</Link>
</div>
</main>
</>
);

View file

@ -7,7 +7,7 @@ config.autoAddCss = false;
import "./nprogress.css";
export const metadata = {
title: "Create Next App",
title: "Alvalens | Portofolio",
description: "Generated by create next app",
};

106
app/projects/[slug]/page.js Normal file
View file

@ -0,0 +1,106 @@
"use client";
import { useState, useEffect } from "react";
import jsonData from "../../../json/data.json";
import Image from "next/image";
function Page({ params }) {
const [data, setData] = useState(null);
useEffect(() => {
const selectedData = jsonData.Projects.find(
(item) => item.slug === params.slug
);
setData(selectedData);
}, [params.slug]);
if (!data) {
return <p>Loading...</p>;
}
return (
<div className="relative min-h-screen w-full gap-4 p-10 flex justify-center items-center flex-col mb-10 ">
<div className="min-h-screen flex justify-center items-center">
<div className="mx-auto grid grid-cols-1 md:grid-cols-2 ">
<div className="flex justify-center items-start flex-col mb-5 space-y-10">
<div>
<h2 className="uppercase font-normal text-lg tracking-[8px] text-neutral-400">
Project
</h2>
<h1 className="text-4xl font-medium text-neutral-900">
{data.title}
</h1>
</div>
<div>
<h2 className="uppercase font-normal text-lg tracking-[8px] text-neutral-400">
Technology
</h2>
<p className="text-2xl font-normal text-neutral-900">
{data.tech.join(", ")}
</p>
</div>
<div>
<h2 className="uppercase font-normal text-lg tracking-[8px] text-neutral-400">
Year
</h2>
<p className="text-2xl font-normal text-neutral-900">
{data.year}
</p>
</div>
<div>
<h2 className="uppercase font-normal text-lg tracking-[8px] text-neutral-400">
Preview
</h2>
<p className="text-2xl font-normal text-neutral-900">
<a
href={data.preview}
target="_blank"
rel="noopener noreferrer">
{data.preview}
</a>
</p>
</div>
<div>
<h2 className="uppercase font-normal text-lg tracking-[8px] text-neutral-400">
Source Code
</h2>
<p className="text-2xl font-normal text-neutral-900">
<a
href={data.code}
target="_blank"
rel="noopener noreferrer">
{data.code}
</a>
</p>
</div>
</div>
<div className="flex justify-start items-start flex-col mb-5 ">
<h2 className="uppercase font-normal text-lg tracking-[8px] text-neutral-400">
Description
</h2>
{data.desc.map((desc, index) => (
<p
key={index}
className="text-2xl font-normal text-gray-600 mb-5">
{desc}
</p>
))}
</div>
</div>
</div>
{/* images */}
<div className="mx-auto grid grid-cols-1 p-5 md:p-20 w-full h-auto">
<div className="w-full h-auto aspect-video">
{data.images.map((image, index) => (
<img
key={index}
src={image}
alt={`Project Image ${index + 1}`}
className="w-full h-full mb-5"
/>
))}
</div>
</div>
</div>
);
}
export default Page;

View file

@ -1,5 +1,9 @@
// generate layour with footer
import Footer from "@/components/Footer";
export const metadata = {
title: "Alvalens | Projects",
};
export default function Layout({ children }) {
return (
<>

View file

@ -6,12 +6,15 @@ import Button from "@/components/Button";
import Image from "next/legacy/image";
// images
import Me1 from "@/public/img/me1.jpg";
import Me2 from "@/public/img/me2.jpg";
import Me3 from "@/public/img/me3.jpg";
import ReactChat1 from "@/public/projects/react-chat.png";
import ReactChat2 from "@/public/projects/react-chat2.png";
import ReactChat3 from "@/public/projects/react-chat3.png";
import ProjectAll from "@/public/img/projects-all.jpg";
import Hr from "@/components/Hr";
const projects = () => {
[{ title: "React Chat WebApp"}]
[{ title: "React Chat WebApp" }];
};
export default function Page() {
@ -28,16 +31,21 @@ export default function Page() {
initial={{ scale: 1 }}
animate={{ scale: 1.6 }}
transition={{ duration: 1, ease: "circOut" }}
className="bg-slate-300 rounded-sm h-[400px] md:h-[600px] w-[80vw] md:w-[30vw]"></motion.div>
className="bg-slate-300 rounded-sm h-[400px] md:h-[600px] w-[80vw] md:w-[30vw] grayscale hover:grayscale-0">
<Image
src={ProjectAll}
alt="Alvalens"
layout="fill"
objectFit="cover"
placeholder="blur"
/>
</motion.div>
</div>
<div className="z-10 w-full absolute md:w-auto md:left-[10%] top-[60%] md:top-1/3 col-span-2 flex flex-col justify-center items-start md:items-start text-start px-10">
<div className="z-10 w-full absolute md:w-auto md:left-[10%] top-[60%] md:top-1/3 col-span-2 flex flex-col justify-center items-start md:items-start text-start px-10 pt-4 backdrop-filter backdrop-blur-sm md:backdrop-blur-none md:backdrop-filter-none bg-gray-100 bg-opacity-50 md:bg-transparent md:pt-0">
<h1 className="text-5xl md:text-8xl font-bold">
My Projects
</h1>
<div className="flex justify-center items-center flex-col my-5 ">
<div className="bg-gray-700 w-20 h-1 rounded-full mb-2"></div>
<div className="bg-gray-700 w-20 h-1 rounded-full translate-x-14"></div>
</div>
<Hr />
<p className="title text-xl mt-4 tracking-wider text-gray-500 leading-[1.7rem] mb-5">
List of my projects that I have done and currently
working on.
@ -67,7 +75,7 @@ export default function Page() {
<div className="relative w-screen mx-auto container gap-4 px-10 grid grid-cols-1 md:grid-cols-2 mb-10">
<div className="flex justify-center items-start flex-col mb-5 ">
<div className="images relative w-full aspect-square">
<div className="absolute top-28 left-10 w-[50%] aspect-square grayscale hover:grayscale-0 transition-all ease duration-300">
<div className="absolute top-28 left-10 w-[50%] aspect-square grayscale hover:grayscale-0 transition-all ease duration-300 hover:scale-150">
<motion.div
initial={{ opacity: 0, scale: 0.5, x: 100 }}
whileInView={{
@ -75,10 +83,9 @@ export default function Page() {
scale: 1,
x: 0,
}}
transition={{ duration: 1 }}
className="w-full h-full">
className="w-full h-full shadow-lg">
<Image
src={Me1}
src={ReactChat1}
alt="Alvalens"
layout="fill"
objectFit="cover"
@ -86,7 +93,7 @@ export default function Page() {
/>
</motion.div>
</div>
<div className="absolute top-16 right-28 w-[30%] aspect-square grayscale hover:grayscale-0 transition-all ease duration-300">
<div className="absolute top-16 right-28 w-[30%] aspect-square grayscale hover:grayscale-0 transition-all ease duration-300 hover:scale-150">
<motion.div
initial={{
opacity: 0,
@ -98,18 +105,19 @@ export default function Page() {
scale: 1,
x: 0,
}}
transition={{ delay: 0.3, duration: 1 }}
className="w-full h-full">
transition={{ delay: 0.3 }}
className="w-full h-full shadow-lg ">
<Image
src={Me2}
src={ReactChat3}
alt="Alvalens"
layout="fill"
objectFit="cover"
placeholder="blur"
objectPosition="0% 0%"
/>
</motion.div>
</div>
<div className="absolute bottom-16 right-20 w-[40%] aspect-square grayscale hover:grayscale-0 transition-all ease duration-300">
<div className="absolute bottom-16 right-20 w-[40%] aspect-square grayscale hover:grayscale-0 transition-all ease duration-300 hover:scale-150">
<motion.div
initial={{
opacity: 0,
@ -124,9 +132,9 @@ export default function Page() {
transition={{
delay: 0.5,
}}
className="w-full h-full">
className="w-full h-full shadow-lg">
<Image
src={Me3}
src={ReactChat2}
alt="Alvalens"
layout="fill"
objectFit="cover"
@ -167,7 +175,15 @@ export default function Page() {
firebase storage. You can see the source code of
this project on my github account or preview the
project by clicking the button below.
</p>
</p>{" "}
<div className="mt-3">
<Button variation="primary">
<Link href="projects/react-chat ">More</Link>
</Button>
<Button variation="secondary">
<Link href="projects/react-chat">Preview</Link>
</Button>
</div>
</motion.div>
</div>
<div className="mt-16 flex flex-col justify-start items-center w-full pl-10 md:pl-32">

View file

@ -1,7 +1,7 @@
const Button = ({ children, variation, ...props }) => (
<button
{...props}
className={`title rounded-2xl px-8 py-2 shadow-md transition duration-300 ease-in-out ${
className={`title mr-3 rounded-2xl px-8 py-2 shadow-md transition duration-300 ease-in-out ${
variation === "primary"
? "bg-gray-400 hover:bg-slate-500 text-gray-100 hover:text-white"
: "transparent border border-gray-400 hover:border-slate-500 text-gray-400 hover:text-gray-300"

View file

@ -7,10 +7,11 @@ import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
export default function Footer() {
return (
<div className="flex justify-center items-center flex-col mt-5 self-start min-h-[50vh] bg-gray-200">
<div className="flex justify-center items-center flex-col mt-5 self-start ">
<div className="flex justify-center items-center flex-col mt-5 self-center min-h-[50vh] border-b-2 min-w-[80vw] ">
<Link href="/#contact">
<motion.h1
className="text-5xl font-bold mt-3 tracking-widest hover:underline"
className="text-5xl md:text-7xl font-medium mt-3 hover:underline whitespace-nowrap leading-none"
initial={{
opacity: 0,
y: -200,
@ -32,5 +33,12 @@ export default function Footer() {
</motion.h1>
</Link>
</div>
<footer className="flex justify-center items-center flex-col my-5 self-start]">
<p className="text-gray-800 text-sm">
&copy;{new Date().getFullYear()} -{" "}
<span className="text-gray-700 text-lg">Alvalens</span>
</p>
</footer>
</div>
);
}

View file

@ -175,8 +175,8 @@ const Navbar = () => {
<nav
ref={navRef}
className={`navbar px-5 md:px-24 w-screen fixed transition-colors ease duration-500 ${
isNavOpen ? "bg-transparent" : "bg-gray-50"
} inset-0 backdrop-blur-md opacity-50 flex flex-row justify-between items-center h-16 z-50 `}>
isNavOpen ? "bg-transparent" : "backdrop-filter backdrop-blur-xl"
} inset-0 opacity-50 flex flex-row justify-between items-center h-16 z-50 `}>
<div className="">
<h1 className="text-2xl">Alvalens</h1>
</div>

25
json/data.json Normal file
View file

@ -0,0 +1,25 @@
{
"Projects": [
{
"title": "Project 1",
"desc": [
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla euismod, nisl quis ultricies ultricies, nunc nisl ultricies elit, qu",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla euismod, nisl quis ultricies ultricies, nunc nisl ultricies elit, qu"
],
"year": "2015",
"preview": "http://www.google.com",
"code": "http://www.google.com",
"images": [
"/projects/lms.png",
"/projects/lms.png",
"/projects/lms.png"
],
"tech": [
"HTML",
"CSS",
"JavaScript"
],
"slug": "project-1"
}
]
}

View file

@ -24,6 +24,7 @@
"postcss": "8.4.28",
"react": "18.2.0",
"react-dom": "18.2.0",
"swr": "^2.2.2",
"tailwindcss": "3.3.3"
}
}

21
pnpm-lock.yaml generated
View file

@ -50,6 +50,9 @@ dependencies:
react-dom:
specifier: 18.2.0
version: 18.2.0(react@18.2.0)
swr:
specifier: ^2.2.2
version: 2.2.2(react@18.2.0)
tailwindcss:
specifier: 3.3.3
version: 3.3.3
@ -2436,6 +2439,16 @@ packages:
engines: {node: '>= 0.4'}
dev: false
/swr@2.2.2(react@18.2.0):
resolution: {integrity: sha512-CbR41AoMD4TQBQw9ic3GTXspgfM9Y8Mdhb5Ob4uIKXhWqnRLItwA5fpGvB7SmSw3+zEjb0PdhiEumtUvYoQ+bQ==}
peerDependencies:
react: ^16.11.0 || ^17.0.0 || ^18.0.0
dependencies:
client-only: 0.0.1
react: 18.2.0
use-sync-external-store: 1.2.0(react@18.2.0)
dev: false
/tailwindcss@3.3.3:
resolution: {integrity: sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==}
engines: {node: '>=14.0.0'}
@ -2604,6 +2617,14 @@ packages:
punycode: 2.3.0
dev: false
/use-sync-external-store@1.2.0(react@18.2.0):
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies:
react: 18.2.0
dev: false
/util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: false

BIN
public/img/projects-all.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
public/img/setup.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 MiB

BIN
public/projects/lms.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB