diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..3211301 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,25 @@ +## Description +Describe the purpose of this PR and the problem it solves. + +## Changes +- Added ... +- Implemented ... +- Refactored ... +- Fixed ... + +## Screenshots +(if applicable) + +## Testing +Describe how this was tested. + +## Checklist +- [ ] Tested locally +- [ ] No ESLint errors +- [ ] No console errors +- [ ] Responsive (obligatory after the Phase 5 is reached, see [README.md](https://github.com/Abviol/scent/blob/dev/README.md)) +- [ ] No new accessibility violations +- [ ] Types are correct +- [ ] Documentation/comments updated +- [ ] UI matches design +- [ ] Animations work correctly diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..70cd3de --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,245 @@ +# Contributing to Scent + +This document outlines the development workflow and rules to keep the codebase consistent and maintainable. + +--- + +## Navigation + +1. [Project Setup](#project-setup) +2. [Development Flow](#development-flow) +3. [Branch Naming](#branch-naming) +4. [Branch Strategy](#branch-strategy) +5. [Commit Convention](#commit-convention) +6. [Pull Requests](#pull-requests) +7. [What Should Not Be Committed](#what-should-not-be-committed) +8. [Code Style](#code-style) +9. [Definition of Done](#definition-of-done) +10. [Notes](#notes) +--- + +## Project Setup + +### Clone the repository + +```bash +git clone https://github.com/Abviol/scent.git +``` + +### Copy variables from .env.example to .env + +```bash +cp .env.example .env +``` + +### Install dependencies + +```bash +pnpm install +``` + +### Start development server + +```bash +pnpm dev +``` + +### Build project +```bash +pnpm build +``` + +### Lint code +```bash +pnpm lint +``` + +--- + +## Development Flow + +1. Create branch from `dev` +2. Implement changes +3. Run `pnpm lint` + `pnpm build` +4. Open PR targeting `dev` +5. Merge after review/checks + +--- + +## Branch Naming + +Use the following convention: + +``` +type/short-description +``` + +### Branch types: +- `feat`: new feature +- `fix`: bug fix +- `refactor`: code change without behavior change +- `docs`: documentation only +- `style`: formatting (no logic changes) +- `test`: adding/updating tests +- `chore`: maintenance (build tools, deps, etc.) + +### Examples: +- feat/cart-drawer +- fix/hydration-issue +- refactor/navbar-state +- docs/readme-update + +--- + +## Branch Strategy + +- main → production +- dev → active development + +PRs target dev; dev is merged into main only for releases. + +--- + +## Commit Convention + +We use Conventional Commits: + +``` +type(scope): subject + +Body: explanation of what changed and why (optional) + +Footer: links / breaking changes (optional) +``` + +### 1. Type (required) +- `feat`: new feature +- `fix`: bug fix +- `refactor`: code change without behavior change +- `docs`: documentation only +- `style`: formatting (no logic changes) +- `test`: adding/updating tests +- `chore`: maintenance (build tools, deps, etc.) + +### 2. Scope (optional) +What part of the app is affected. + +Examples: +- `cart` +- `navbar` +- `auth` +- `checkout` +- `api` + +### 3. Subject (required) +Short description of the change + +**Rules**: + +- imperative mood (“add”, not “added”) +- lowercase +- no period at the end +- ideally ≤ 50–72 characters + + +Example: +``` +feat(cart): add drawer animation +``` + +### 4. Body (optional) +Why and what in detail. + +```markdown +Implemented smooth slide-in animation using Framer Motion. +Improves UX consistency with design system. +``` + +### 5. Footer (optional) +Used for metadata like: +- breaking changes +- issue references + +```markdown +fix(auth): prevent login crash on empty input + +Closes #42 +``` +or +```markdown +feat(api): change response format + +BREAKING CHANGE: response now returns `userData` instead of `user` +``` + +### Full commit example + +```markdown +feat(cart): add drawer animation + +Implemented slide-in cart drawer with focus trap and escape handling. +Improves accessibility and aligns with design specs. + +Closes #18 +``` + +## Pull Requests + +Before opening a PR: + +- Ensure the branch is up to date with `dev` +- Run `pnpm build` +- Run `pnpm lint` +- Test changes locally + +### PR Naming Convention + +PR titles use the same format as commit messages: +```markdown +type(scope): short description +``` + +### PR requirements: +- Clear description +- Screenshots (if UI changes) +- All (applicable) checklist items completed + +See [/.github/pull_request_template.md](./.github/pull_request_template.md) + +--- + +## What should NOT be committed + +- console.log left in code +- commented-out code +- unused imports +- debug flags + +--- + +## Code Style + +See [Code Conventions](./docs/code_conventions.md) for the full coding +standards applied across the codebase. + +--- + +## Definition of Done + +A task is considered complete when: + +- [ ] Feature works as expected +- [ ] No ESLint errors +- [ ] No console errors +- [ ] Fully responsive (obligatory after the Phase 5 is reached, see [README.md](./README.md)) +- [ ] Accessible (keyboard + ARIA where needed) +- [ ] Types are correct +- [ ] UI matches design +- [ ] Code is reviewed and clean + +--- + +## Notes + +This project is designed as a portfolio-level production simulation. +Quality, consistency, and clarity matter more than speed. \ No newline at end of file diff --git a/README.md b/README.md index e215bc4..806287c 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,322 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# Scent + +Modern fragrance-focused e-commerce experience built with Next.js, TypeScript, and Tailwind CSS. + +![Next.js](https://img.shields.io/badge/next.js-v16-gray?style=for-the-badge&logo=next.js&logoColor=white&labelColor=black) +![React](https://img.shields.io/badge/react-v19-gray?style=for-the-badge&logo=react&logoColor=61DAFB&labelColor=20232a) +![TypeScript](https://img.shields.io/badge/typescript-v5-gray.svg?style=for-the-badge&logo=typescript&logoColor=white&labelColor=007ACC) +![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-v4-gray?style=for-the-badge&logo=tailwindcss&logoColor=white&labelColor=38bdf8) +![Prisma](https://img.shields.io/badge/prisma-v__-gray?style=for-the-badge&logo=prisma&logoColor=white&labelColor=131826) +[![Vercel](https://img.shields.io/badge/vercel-black?style=for-the-badge&logo=vercel&logoColor=white)](https://scent-nine.vercel.app/) +![License](https://img.shields.io/badge/license-MIT-gray?style=for-the-badge&labelColor=green) + +--- + +## Navigation +1. [Overview](#overview) +2. [Features](#features) +3. [Performance & Scalability Goals](#performance--scalability-goals) +4. [Roadmap](#roadmap) +5. [Tech Stack](#tech-stack) +6. [Project Structure](#project-structure) +7. [Getting Started](#getting-started) +8. [Available Scripts](#available-scripts) +9. [Screenshots](#screenshots) +10. [Deployment](#deployment) +11. [Contributing](#contributing) +12. [License](#license) + +--- + +## Overview + +Scent is a full-stack fragrance-focused e-commerce application developed collaboratively by a full-stack engineer and a UX/UI designer. + +The project was created as a production-oriented portfolio application focused on delivering a modern shopping experience while following real-world frontend engineering practices. + +Key areas of focus include: +- scalable architecture +- strict TypeScript usage +- reusable component design +- responsive layouts +- collaborative Git workflow +- performance optimization +- accessibility and user experience + +--- + +## Features + +- Fully responsive modern interface +- Accessible UI components +- Optimized Next.js App Router architecture +- Type-safe development with TypeScript +- Reusable component-based architecture +- Tailwind CSS design system +- Conventional Commits and structured PR workflow +- Production-oriented frontend workflow + +--- + +## Performance & Scalability Goals + +The application is designed with a production-oriented mindset, focusing on perceived performance, scalability, and resilience under real-world constraints such as high latency and increased user load. + +The current performance objectives include: + +- Optimized user experience under high-latency and unstable network conditions +- Efficient rendering strategy with minimal unnecessary client-side JavaScript +- Scalable architecture designed to support high traffic workloads (100k+ concurrent users) under appropriate horizontal scaling conditions. +- Reduced Time to First Byte (TTFB) and optimized server response times via caching strategies +- Optimized asset delivery (image optimization, lazy loading, and CDN usage) +- Stable UI performance under heavy interaction load (animations, cart updates, navigation transitions) + +Additional engineering targets for production readiness: + +- Effective caching strategy (server-side + edge where applicable) +- Database query optimization and avoidance of N+1 patterns +- Stateless backend design to support horizontal scaling +- Graceful degradation under partial service failure +- Monitoring-ready architecture (logs, metrics, and error tracking integration) +- Core Web Vitals optimization (LCP, CLS, INP within “good” thresholds) + +--- + +## Roadmap + +### Design +- [x] Website structure +- [x] Branding (color scheme, fonts, spacing) +- [x] Breakpoints definition +- [x] Desktop design — all pages and component states +- [ ] Tablet and mobile adaptive design +- [ ] Design polish and organization + +--- + +### Phase 0 — Preparation +- [x] Complete official Next.js course +- [x] Learn Prisma, PostgreSQL, and relational databases +- [x] Learn NextAuth basics +- [x] Initialize Next.js + TypeScript + Tailwind CSS + +### Phase 1 — Frontend +- [x] Integrate Shadcn UI +- [x] UI kit (custom colors, fonts, buttons, tags, breadcrumbs) +- [x] Reusable components (header, footer, product card, search, comments) +- [ ] All client-side pages +- [ ] Metadata (title, description, favicon) + +### Phase 2 — Backend: Core +- [ ] Set up Prisma + PostgreSQL +- [ ] Design database schema +- [ ] Seed database with initial data +- [ ] Configure NextAuth +- [ ] Configure localization +- [ ] React Server Components +- [ ] Authentication +- [ ] User profile +- [ ] Shop (filters, sorting, search, gender/brand views) +- [ ] Product interactions (wishlist, cart, comments) + +### Phase 3 — Backend: Integrations +- [ ] Newsletter subscription +- [ ] Stripe payment integration (test mode) +- [ ] Order storage +- [ ] React Server Components optimization + +### Phase 4 — Admin Dashboard +- [ ] Authentication +- [ ] Dashboard home +- [ ] Products CRUD +- [ ] Orders management +- [ ] Users management + +### Phase 5 — Polishing +- [ ] Tablet and mobile responsiveness +- [ ] SEO optimization +- [ ] PageSpeed Insights audit +- [ ] Unit and integration testing +- [ ] Production readiness review +- [ ] Secrets and environment variables audit + +### Phase 6 — Deployment +- [ ] Configure Vercel environment variables +- [ ] Deploy to Vercel +- [ ] Custom domain setup + +### Phase 7 — Showcase +- [ ] Finalize README +- [ ] Set repository public +- [ ] Post on LinkedIn and Dev.to + +--- + +## Tech Stack + +### Frontend + +- React v19 +- Next.js v16 +- TypeScript v5 +- Tailwind CSS v4 + +### UI & Component Libraries + +- Shadcn/ui +- Radix UI +- Lucide React +- Swiper + +### Backend & Infrastructure + +- Prisma (ORM) +- PostgreSQL (database) +- Vercel (hosting & deployment) + + +### Tooling & Developer Experience + +- pnpm (package manager) +- ESLint (linting) +- Prettier (code formatting) +--- + +## Project Structure + +```txt +src/ +├── app/ +│ ├── account/ # Account related pages +│ │ ├── cart/ +│ │ ├── orders/ +│ │ ├── profile/ +│ │ ├── wishlist/ +│ │ └── layout.tsx +│ ├── shop/ # Shop related pages +│ │ ├── [[...slug]]/ +│ │ ├── brands/ +│ │ ├── product/ +│ │ └── layout.tsx +│ ├── globals.css # Global styles, themes, and utilities +│ ├── layout.tsx # Root layout +│ └── page.tsx # Homepage +│ +├── assets/ # Fonts, images, icons +│ ├── images/ +│ └── fonts.ts +├── components/ # Reusable components +│ ├── ui/ # UI primitives +│ ├── icons/ # Custom icons +│ ├── layout/ # Layout-related components +│ │ ├── footer.tsx +│ │ ├── header.tsx +│ │ └── nav.tsx +│ └── pages/ # Page-specific components +├── hooks/ # Custom React hooks +└── lib/ # Shared data, utilities and types + ├── data.ts + ├── types.ts + └── utils.ts +``` + +--- ## Getting Started -First, run the development server: +### Clone the repository + +```bash +git clone https://github.com/Abviol/scent.git +``` + +### Copy variables from .env.example to .env + +```bash +cp .env.example .env +``` + +### Install dependencies + +```bash +pnpm install +``` + +### Start development server + +```bash +pnpm dev +``` + +Open: + +```txt +http://localhost:3000 +``` + +--- + +## Available Scripts + +### Development ```bash -npm run dev -# or -yarn dev -# or pnpm dev -# or -bun dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +### Production build + +```bash +pnpm build +``` + +### Start production server + +```bash +pnpm start +``` + +### Lint code + +```bash +pnpm lint +``` + +--- + +## Screenshots + +### Home Page + +![Homepage](./docs/images/home.png) + +### Shop Page + +![Shop page](./docs/images/shop.png) + +### Cart Page + +![Cart page](./docs/images/cart.png) + + +### Wishlist Page +![Wishlist page](./docs/images/wishlist.png) -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +--- -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +## Deployment -## Learn More +The application is deployed on Vercel automatically on push to `dev`. -To learn more about Next.js, take a look at the following resources: +--- -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +## Contributing -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +Please read [Contributing](./CONTRIBUTING.md) +before creating branches, commits, or pull requests. -## Deploy on Vercel +--- -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +## License -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +MIT License. \ No newline at end of file diff --git a/components/filterDropdown.tsx b/components/filterDropdown.tsx index 1d18afd..0c4d329 100644 --- a/components/filterDropdown.tsx +++ b/components/filterDropdown.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useEffect } from "react"; +import { useState } from "react"; import { Minus, Plus } from "lucide-react"; import { Slider } from "@/components/ui/slider"; import { Checkbox } from "@/components/ui/checkbox"; diff --git a/docs/code_conventions.md b/docs/code_conventions.md new file mode 100644 index 0000000..420044a --- /dev/null +++ b/docs/code_conventions.md @@ -0,0 +1,483 @@ +# Code Conventions + +This document defines the coding conventions applied across the `Next.js`, `React`, `TypeScript`, and `Tailwind CSS` codebase. + +--- + +## Navigation + +1. [React / Next.js](#react--nextjs) + - [Components](#components) + - [Custom Hooks](#custom-hooks) + - [Exports](#exports) + - [Folder Colocation](#folder-colocation) +2. [TypeScript](#typescript) + - [Variables](#variables) + - [Constants](#constants) + - [Functions](#functions) + - [Interfaces](#interfaces) + - [Types](#types) + - [Interface vs Type](#interface-vs-type) + - [Enum vs Const](#enum-vs-const) + - [Explicit Return Types](#explicit-return-types-on-functions) + - [null vs undefined](#null-vs-undefined) +3. [Imports](#imports) + - [Import Ordering](#import-ordering) + - [Absolute vs Relative Imports](#absolute-vs-relative-imports) +4. [Styling](#styling) +5. [General](#general) + - [Comment Conventions](#comment-conventions) + - [console.log Policy](#consolelog-policy) + +--- + +## React / Next.js + +### Components + +#### File Architecture + +Each reusable component must reside in a dedicated `.tsx` file named in `kebab-case`: + +```txt +../ +├── product-card.tsx +├── search-result-item.tsx +└── ... +``` + +If a component's styling is extracted into a dedicated `styles.css` file in accordance with the [styling conventions](#styling), the component must follow this structure: + +```txt +../ +└── my-component/ + ├── index.tsx # Component definition + └── styles.css # Component styles +``` + +#### Declaration + +Components must be named using `PascalCase`, matching the name of the file or directory they reside in: + +```tsx +// my-component.tsx +// or +// ../my-component/index.tsx + +function MyComponent() { + return (<>); +} +``` + +#### `'use client'` Usage + +Use `'use client'` only when a component requires one of the following: + +- React state (`useState`, `useReducer`) +- React lifecycle effects (`useEffect`) +- Browser APIs (`window`, `localStorage`, etc.) +- Event handlers (`onClick`, `onChange`, etc.) + +If none of the above apply, leave it as a Server Component — no directive is needed. + +The key design principle is: push `'use client'` as deep into the component tree as possible, so the maximum amount of UI stays server-rendered. + +```tsx +async function MyServerComponent() { + return ( + + ); +} +``` + +```tsx +'use client' + +import { useState } from "react"; + +function MyClientComponent() { + const [number, setNumber] = useState(0); + const handleClick = () => setNumber(prev => prev + 1); + + return ( + + ); +} +``` + +#### Props Destructuring + +Use inline destructuring for component props: + +```tsx +function MyComponent({ title, description }: MyComponentProps) { + return
{title}
; +} +``` + +--- + +### Custom Hooks + +#### File Naming + +Custom hook files must be named in `kebab-case`, prefixed with `use-`: + +```txt +hooks/ +└── use-my-hook.ts +``` + +#### Declaration + +Custom hooks must be declared using a regular function declaration and named in `camelCase`, prefixed with `use`: + +```ts +function useMyHook() {} +``` + +--- + +### Exports + +Use `export default` for components and page files: + +```tsx +// ./my-page.tsx +export default function MyPage() {} +``` + +```tsx +// ./my-component.tsx +export default function MyComponent() {} +``` + +Use named exports for utilities, hooks, types, and constants: + +```ts +export function myUtility() {} +export function useMyHook() {} +export type MyType = number; +export const MY_CONST = "my_const_value"; +``` + +--- + +### Folder Colocation + +Component-specific utilities, types, and constants that are **not shared across the codebase** must be placed inside the component's file: + +```tsx +// my-component.tsx + +function myComponentUtility() {} +interface MyComponentProps {} +const MY_COMPONENT_CONST = "my_component_const_value"; + +function MyComponent() {} +``` + +If the component already has a folder structure, those may live in dedicated files within that folder: + +```txt +my-component/ +├── index.tsx +├── styles.css +├── types.ts # Component-specific types +└── utils.ts # Component-specific utilities +``` + +Shared utilities, types, and constants must be placed in the corresponding files inside the `lib/` directory: + +```ts +// lib/types.ts +export type MyType = number; + +// lib/utils.ts +export function myUtility() {} + +// lib/data.ts +export const MY_CONST = "my_const_value"; +``` + +--- + +## TypeScript + +### Variables + +Variables must be named in `camelCase`: + +```ts +let myVariable; +``` + +### Constants + +Primitive constants and configuration values must be named in `UPPER_SNAKE_CASE`: + +```ts +const MAX_ITEMS = 10; +const API_BASE_URL = "https://api.example.com"; +``` + +### Functions + +Functions must be named in `camelCase`: + +```ts +function myFunction() {} +``` + +```ts +const myArrowFunction = () => {}; +``` + +#### Regular vs Arrow Function Declarations + +Regular function declarations must be used for utility functions: + +```ts +// ./lib/utils.ts +function myUtilityFunction() {} +``` + +Arrow function declarations must be used for event handlers inside React components. Event handlers must be named using the `handle` prefix followed by the action name, in accordance with the [function naming convention](#functions): + +```tsx +function MyComponent() { + const handleClick = () => {}; + const handleSubmit = () => {}; + + return ( +