added footer and navbar, still working on copyright text

This commit is contained in:
Jacob Delgado 2024-10-28 22:48:22 -07:00
parent 67c2eabd1a
commit 7bc254ad03
13 changed files with 322 additions and 6 deletions

Binary file not shown.

View File

@ -16,15 +16,18 @@
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"dotenv": "^16.4.5",
"framer-motion": "^11.11.10",
"lucide-react": "^0.427.0",
"next": "14.1.4",
"nodemailer": "^6.9.14",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"resend": "^3.5.0",
"sharp": "^0.33.5",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7"
"tailwindcss-animate": "^1.0.7",
"usehooks-ts": "^3.1.0"
},
"devDependencies": {
"@types/node": "^20.16.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -1,12 +1,15 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import Navbar from "@/components/Navbar/Navbar";
import Footer from "@/components/Footer/Footer";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Kevos Attire",
description: "Clothing for people with needs",
description: "Clothing for the next generation.",
};
export default function RootLayout({
@ -16,7 +19,11 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body className={`${inter.className} bg-slate-700`}>{children}</body>
<body className={`${inter.className} bg-slate-700`}>
<Navbar />
{children}
<Footer />
</body>
</html>
);
}

View File

@ -13,6 +13,7 @@ import { sendEmails } from "@/lib/mail.utils";
const Popp = Poppins({ weight: "400", subsets: ["latin"] });
// improve to drag & drop side cart for more fun
export default function Home() {
@ -24,6 +25,10 @@ export default function Home() {
orders: "",
});
function newItem(){
}
async function newOrder(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
@ -73,9 +78,9 @@ export default function Home() {
<main className="flex min-h-screen flex-col px-20">
{/* Title */}
<div className="text-4xl w-full justify-center text-center items-center flex flex-col gap-9 py-12 font-medium text-orange-600">
<h1 className={`${Popp.className} text-white text-5xl`}>
{/* <h1 className={`${Popp.className} text-white text-5xl`}>
Kevo&#39;s Attire
</h1>
</h1> */}
<div
className={`${Popp.className} text-orange-600 text-center flex flex-col gap-5`}
>

View File

@ -0,0 +1,38 @@
"use client";
import Image from "next/image";
const CartModal = () => {
const cartItems = true;
return (
<div>
<div className="absolute p-4 rounded-md shadow-[0_3px_10px_rgb(0,0,0,0,2)] bg-white top-12 right-0 flex flex-col gap-6 z-20">
{!cartItems ? <div>Cart is Empty</div> :
<div className="">
<Image
src="batch1/Mockup 134.png"
alt=""
width={72}
height={96}
className="object-contain rounded-md"
/>
<div className="">
{/* TOP */}
<div>
{/* TITLE */}
<div className="">
<h3>Product Name</h3>
<div className="">$49</div>
</div>
{/* DESCRIPTION */}
<div className="">
available
</div>
</div>
{/* BOTTOM */}
</div>
</div>}
</div>
</div>
);
};

View File

@ -0,0 +1,11 @@
"use client";
import React from 'react'
const CartTab = () => {
const cartItems = false;
return (
<div className='absolute p-4 rounded-md shadow-[0_3px_10px_rgb(0,0,0,0,2)] bg-white top-12 right-0 flex flex-col gap-6 z-20'>{!cartItems ? (<div>Cart is Empty</div>) : (<div></div>)}</div>
)
}
export default CartTab

View File

@ -0,0 +1,40 @@
import React from 'react'
import { FaFacebookF } from "react-icons/fa";
import { FaInstagram } from "react-icons/fa";
import { FaTiktok } from "react-icons/fa";
const Footer = () => {
return (
<div className='footer text-white flex flex-col gap-8 px-24 pb-2'>
<div className='top'>
<div className='item'>
<h1>Categories</h1>
<span>Women</span>
<span>Men</span>
<span>Shoes</span>
<span>Accessories</span>
<span>New Arrivals</span>
</div>
<div className='item'>
<h1>Links</h1>
<span>FAQ</span>
<span>Pages</span>
<span>Stores</span>
<span>Compare</span>
<span>Cookies</span>
</div>
<div className='item'></div>
<div className='item'></div>
</div>
<div className='Socials flex gap-4 text-xl'>
<FaFacebookF />
<FaInstagram />
<FaTiktok />
</div>
<div className='bottom text-xs'><span>© 2024 - Kevos Attire LLC. All rights reserved. All items are made with the assumption that they are 100% original ideas as we do not </span></div>
</div>
)
}
export default Footer

View File

@ -0,0 +1,140 @@
"use client";
import { motion } from "framer-motion";
import { useState } from "react";
import { useMediaQuery } from "@/util/useMediaQuery";
import { FiShoppingCart } from "react-icons/fi";
import Image from "next/image";
const navMotion = {
visible: {
opacity: 1,
transition: {
when: "beforeChildren",
staggerChildren: 0.15,
},
},
hidden: {
opacity: 0,
},
};
const itemMotion = {
visible: { opacity: 1, x: 0 },
hidden: { opacity: 0, x: -100 },
};
export default function Nav() {
const [toggled, setToggled] = useState(false);
const matches = useMediaQuery("(min-width: 1280px)");
// console.log(matches);
return (
<nav className="relative mx-8 mb-10 flex justify-between items-center pt-12 font-medium md:mx-16 lg:mx-32 text-white">
<svg
className="absolute bottom-0 left-1/2 -translate-x-1/2"
width="250"
height={4}
viewBox="0 0 250 4"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M2 2L428 2" stroke="#EEEEEE" strokeLinecap="round" />
</svg>
<div>
<Image
src="/white_logo.png"
width={64}
height={64}
className="rounded-full md:hidden"
alt="Profile picture"
/>
<Image
src="/white_logo.png"
width={80}
height={80}
className="rounded-full md:block hidden xl:hidden"
alt="Profile picture"
/>
<Image
src="/white_logo.png"
width={90}
height={90}
className="rounded-full hidden xl:block"
alt="Profile picture"
/>
</div>
{/* Title */}
<h1 className="text-lg font-bold absolute text-center w-full ">
<a href="/">Kevos Attire</a>
</h1>
{/* Check if mobile device */}
{matches && (
<div className="flex gap-8 relative">
<a href="/">Home</a>
<a href="/products">Shirts</a>
<a href="/about">About</a>
{/* <a href="/contact">Contact</a> */}
<a className="flex relative items-center justify-center" href="/cart">
<FiShoppingCart className="text-lg lg:text-xl" />
<span className="absolute text-white text-xs w-5 h-5 rounded-[50%] bg-slate-400 -top-2.5 -right-2.5 flex items-center justify-center">0</span>
</a>
</div>
)}
{!matches && (
<div
onClick={() => setToggled(!toggled)}
className="space-y-1.5 cursor-pointer z-50"
>
<motion.span
animate={{ rotateZ: toggled ? 45 : 0, y: toggled ? 8 : 0 }}
className="block h-0.5 w-8 bg-[#EEEEEE]"
></motion.span>
<motion.span
animate={{ width: toggled ? 0 : 24 }}
className="block h-0.5 w-6 bg-[#EEEEEE]"
></motion.span>
<motion.span
animate={{
rotateZ: toggled ? -45 : 0,
y: toggled ? -8 : 0,
width: toggled ? 32 : 16,
}}
className="block h-0.5 w-4 bg-[#EEEEEE]"
></motion.span>
</div>
)}
{toggled && !matches && (
<motion.div
animate={{ opacity: 1, x: 0 }}
initial={{ opacity: 0, x: 25 }}
className="fixed flex bg-slate-700 bottom-0 right-0 w-full h-screen items-center justify-center z-40"
>
<motion.div
variants={navMotion}
animate="visible"
initial="hidden"
className="flex flex-col gap-24 text-lg"
>
<motion.a variants={itemMotion} href="/">
Home
</motion.a>
<motion.a variants={itemMotion} href="/products">
Products
</motion.a>
<motion.a variants={itemMotion} href="/about">
About
</motion.a>
<motion.a variants={itemMotion} href="/cart">
Cart
</motion.a>
{/* <motion.a variants={itemMotion} href="/contact">
Contact
</motion.a> */}
</motion.div>
</motion.div>
)}
</nav>
);
}

View File

@ -0,0 +1,11 @@
import Link from 'next/link';
import React from 'react'
const ProductCart = (props: any) => {
const {id, name, price, image, size} = props.data;
return (
<div className='bg-[#EEEEEE] p-5 rounded-xl shadow-sm'><Link href=""></Link></div>
)
}
export default ProductCart

View File

@ -26,7 +26,7 @@ const MenuCard = ({ Menu }: any) => {
return (
<Card
key={menu_item.id}
className="flex-1 flex-col max-w-[325px] h-[400px] relative overflow-hidden bg-white/10 border-none hover:scale-150 transition hover:z-50 backdrop-blur-xl"
className="flex-1 flex-col max-w-[325px] h-[400px] relative overflow-hidden bg-white/10 border-none transition hover:z-50 backdrop-blur-xl"
>
<div className="w-full h-[75%]">
<div className="h-full relative w-full">

View File

@ -0,0 +1,61 @@
import { useState } from 'react'
import { useIsomorphicLayoutEffect } from 'usehooks-ts'
type UseMediaQueryOptions = {
defaultValue?: boolean
initializeWithValue?: boolean
}
const IS_SERVER = typeof window === 'undefined'
export function useMediaQuery(
query: string,
{
defaultValue = false,
initializeWithValue = true,
}: UseMediaQueryOptions = {},
): boolean {
const getMatches = (query: string): boolean => {
if (IS_SERVER) {
return defaultValue
}
return window.matchMedia(query).matches
}
const [matches, setMatches] = useState<boolean>(() => {
if (initializeWithValue) {
return getMatches(query)
}
return defaultValue
})
// Handles the change event of the media query.
function handleChange() {
setMatches(getMatches(query))
}
useIsomorphicLayoutEffect(() => {
const matchMedia = window.matchMedia(query)
// Triggered at the first client-side load and if query changes
handleChange()
// Use deprecated `addListener` and `removeListener` to support Safari < 14 (#135)
if (matchMedia.addListener) {
matchMedia.addListener(handleChange)
} else {
matchMedia.addEventListener('change', handleChange)
}
return () => {
if (matchMedia.removeListener) {
matchMedia.removeListener(handleChange)
} else {
matchMedia.removeEventListener('change', handleChange)
}
}
}, [query])
return matches
}