Глава 53. Финальный проект: собираем крутое приложение

Зачем эта глава

Здесь мы соберём большой проект, который объединяет всё, что ты изучил. Это будет полноценное приложение, которое можно показать в портфолио и заказчикам.

Проект: «ProShop» (мини‑маркетплейс)

Идея: каталог товаров + корзина + профиль пользователя + поиск и фильтры.

Функциональные требования

  • Главная страница с карточками товаров.
  • Страница товара с описанием.
  • Корзина с добавлением и удалением.
  • Поиск, фильтр, пагинация.
  • Форма логина (можно фейковую).
  • Избранное (state или API).

Стек (все из курса)

  • Next.js (App Router)
  • Tailwind CSS
  • TypeScript
  • TanStack Query
  • Zustand или Redux Toolkit
  • React Hook Form + Zod

Структура проекта

Папки
app/
  layout.tsx
  page.tsx
  product/[id]/page.tsx
  cart/page.tsx
  profile/page.tsx

components/
  ProductCard.tsx
  Header.tsx
  SearchBar.tsx

store/
  cart.ts

lib/
  api.ts
  validators.ts

Шаг 1. Создай проект

Bash
npx create-next-app@latest proshop --ts
cd proshop
npm install

Подсказка: сразу включай Tailwind и App Router при создании.

Шаг 2. Настрой провайдеры

TSX
// app/layout.tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const client = new QueryClient();

export default function RootLayout({ children }) {
  return (
    
      
        
          {children}
        
      
    
  );
}

Шаг 3. Карточка товара

TSX
type Product = {
  id: number;
  title: string;
  price: number;
};

export function ProductCard({ title, price }: Product) {
  return (
    

{title}

{price} ₽

); }

Шаг 4. Запрос к API

TSX
import { useQuery } from "@tanstack/react-query";

export function ProductsList() {
  const { data, isLoading } = useQuery({
    queryKey: ["products"],
    queryFn: () => fetch("/api/products").then(r => r.json())
  });

  if (isLoading) return 

Загрузка...

; return data.map(p => ); }

Шаг 5. Корзина (state)

TS
import { create } from "zustand";

export const useCart = create((set) => ({
  items: [],
  add: (item) => set((state) => ({ items: [...state.items, item] })),
  remove: (id) => set((state) => ({ items: state.items.filter(i => i.id !== id) }))
}));

Шаг 6. Форма логина

TSX
import { useForm } from "react-hook-form";

export function LoginForm() {
  const { register, handleSubmit } = useForm();
  return (
    
); }

Шаг 7. Финальные штрихи

  • Добавь адаптив.
  • Проверь доступность (a11y).
  • Сделай 2–3 теста на основные компоненты.

Проверка себя

  • Есть каталог, карточки, корзина и профиль.
  • Запросы к API работают и показывают ошибки.
  • Формы валидируются.
  • Проект задеплоен (Vercel / GitLab Pages).
Финальный совет: этот проект можно использовать как основу для реальных заказов. Главное — довести его до аккуратного вида.

Критерий готовности

Цель: показать проект клиенту.

Требования: рабочий каталог, корзина, поиск, форма логина, деплой.

Критерий готовности: проект выглядит профессионально и готов для портфолио.