├── bun.lockb ├── app ├── favicon.ico ├── page.tsx ├── layout.tsx ├── api │ └── checkout │ │ └── route.ts ├── product │ └── [id] │ │ └── page.tsx └── globals.css ├── postcss.config.mjs ├── public ├── vercel.svg ├── window.svg ├── file.svg ├── globe.svg └── next.svg ├── lib ├── utils.ts └── data.ts ├── components ├── ui │ ├── aspect-ratio.tsx │ ├── skeleton.tsx │ ├── sonner.tsx │ ├── label.tsx │ ├── separator.tsx │ ├── textarea.tsx │ ├── progress.tsx │ ├── collapsible.tsx │ ├── input.tsx │ ├── switch.tsx │ ├── avatar.tsx │ ├── checkbox.tsx │ ├── radio-group.tsx │ ├── hover-card.tsx │ ├── toggle.tsx │ ├── popover.tsx │ ├── badge.tsx │ ├── alert.tsx │ ├── scroll-area.tsx │ ├── tooltip.tsx │ ├── tabs.tsx │ ├── toggle-group.tsx │ ├── resizable.tsx │ ├── slider.tsx │ ├── accordion.tsx │ ├── button.tsx │ ├── card.tsx │ ├── input-otp.tsx │ ├── breadcrumb.tsx │ ├── table.tsx │ ├── calendar.tsx │ ├── pagination.tsx │ ├── dialog.tsx │ ├── form.tsx │ ├── alert-dialog.tsx │ ├── drawer.tsx │ ├── sheet.tsx │ ├── command.tsx │ ├── carousel.tsx │ ├── select.tsx │ ├── navigation-menu.tsx │ ├── context-menu.tsx │ ├── dropdown-menu.tsx │ ├── menubar.tsx │ ├── chart.tsx │ └── sidebar.tsx ├── product │ ├── ProductQuantity.tsx │ └── ProductAction.tsx ├── checkout.tsx └── ProductGrid.tsx ├── hooks ├── use-cart.ts └── use-mobile.ts ├── eslint.config.mjs ├── next.config.ts ├── components.json ├── .gitignore ├── actions └── products.ts ├── tsconfig.json ├── README.md ├── tailwind.config.ts ├── providers └── cart-context.tsx └── package.json /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webprodigies/webprodigies-yeezy/HEAD/bun.lockb -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webprodigies/webprodigies-yeezy/HEAD/app/favicon.ico -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: ["@tailwindcss/postcss"], 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | import { getProducts } from '@/actions/products' 2 | import ProductGrid from '@/components/ProductGrid' 3 | 4 | export default async function Home() { 5 | const products = await getProducts() 6 | return 7 | } 8 | -------------------------------------------------------------------------------- /lib/data.ts: -------------------------------------------------------------------------------- 1 | export const navbarData = [ 2 | { 3 | idx: 1, 4 | title: 'Hoodies', 5 | link: '/hoodies', 6 | }, 7 | { 8 | idx: 2, 9 | title: 'Shoes', 10 | link: '/shoes', 11 | }, 12 | { 13 | idx: 3, 14 | title: 'Shirts', 15 | link: '/shirts', 16 | }, 17 | ] 18 | -------------------------------------------------------------------------------- /components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" 4 | 5 | function AspectRatio({ 6 | ...props 7 | }: React.ComponentProps) { 8 | return 9 | } 10 | 11 | export { AspectRatio } 12 | -------------------------------------------------------------------------------- /components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils" 2 | 3 | function Skeleton({ className, ...props }: React.ComponentProps<"div">) { 4 | return ( 5 |
10 | ) 11 | } 12 | 13 | export { Skeleton } 14 | -------------------------------------------------------------------------------- /hooks/use-cart.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { CartContext } from '@/providers/cart-context' 4 | import { useContext } from 'react' 5 | 6 | export function useCart() { 7 | const context = useContext(CartContext) 8 | if (context === undefined) { 9 | throw new Error('useCart must be used within a CartProvider') 10 | } 11 | return context 12 | } 13 | -------------------------------------------------------------------------------- /public/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from "path"; 2 | import { fileURLToPath } from "url"; 3 | import { FlatCompat } from "@eslint/eslintrc"; 4 | 5 | const __filename = fileURLToPath(import.meta.url); 6 | const __dirname = dirname(__filename); 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }); 11 | 12 | const eslintConfig = [ 13 | ...compat.extends("next/core-web-vitals", "next/typescript"), 14 | ]; 15 | 16 | export default eslintConfig; 17 | -------------------------------------------------------------------------------- /next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from 'next' 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | eslint: { 6 | ignoreDuringBuilds: true, 7 | }, 8 | typescript: { 9 | ignoreBuildErrors: true, 10 | }, 11 | images: { 12 | unoptimized: true, 13 | }, 14 | experimental: { 15 | webpackBuildWorker: true, 16 | parallelServerBuildTraces: true, 17 | parallelServerCompiles: true, 18 | }, 19 | } 20 | 21 | export default nextConfig 22 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } 22 | -------------------------------------------------------------------------------- /hooks/use-mobile.ts: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /actions/products.ts: -------------------------------------------------------------------------------- 1 | 'use server' 2 | import WooCommerceRestApi from 'woocommerce-rest-ts-api' 3 | 4 | const WooCommerce = new WooCommerceRestApi({ 5 | url: 'https://testingwebprodigies.ue1.rapydapps.cloud/', 6 | consumerKey: process.env.WC_CONSUMER_KEY as string, 7 | consumerSecret: process.env.WC_CONSUMER_SECRET as string, 8 | version: 'wc/v3', 9 | }) 10 | 11 | export const getProducts = async () => { 12 | const products = await WooCommerce.get('products') 13 | return products.data 14 | } 15 | 16 | export const getProduct = async (id: string) => { 17 | const product = await WooCommerce.get(`products`, { 18 | id: parseInt(id), 19 | }) 20 | return product.data 21 | } 22 | -------------------------------------------------------------------------------- /components/ui/sonner.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { useTheme } from "next-themes" 4 | import { Toaster as Sonner, ToasterProps } from "sonner" 5 | 6 | const Toaster = ({ ...props }: ToasterProps) => { 7 | const { theme = "system" } = useTheme() 8 | 9 | return ( 10 | 22 | ) 23 | } 24 | 25 | export { Toaster } 26 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as LabelPrimitive from "@radix-ui/react-label" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | function Label({ 9 | className, 10 | ...props 11 | }: React.ComponentProps) { 12 | return ( 13 | 21 | ) 22 | } 23 | 24 | export { Label } 25 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next' 2 | import { DM_Mono } from 'next/font/google' 3 | import './globals.css' 4 | import CartProvider from '@/providers/cart-context' 5 | 6 | const dmmono = DM_Mono({ 7 | weight: '400', 8 | subsets: ['latin'], 9 | }) 10 | 11 | export const metadata: Metadata = { 12 | title: 'Yeezy Clone', 13 | description: 'Fake yeezy website. This is just for learning purpose.', 14 | } 15 | 16 | export default function RootLayout({ 17 | children, 18 | }: Readonly<{ 19 | children: React.ReactNode 20 | }>) { 21 | return ( 22 | 26 | 27 | {children} 28 | 29 | 30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /components/ui/separator.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as SeparatorPrimitive from "@radix-ui/react-separator" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | function Separator({ 9 | className, 10 | orientation = "horizontal", 11 | decorative = true, 12 | ...props 13 | }: React.ComponentProps) { 14 | return ( 15 | 25 | ) 26 | } 27 | 28 | export { Separator } 29 | -------------------------------------------------------------------------------- /components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { 6 | return ( 7 |