Admin Panel for the Online Store 'Korobki-optom'

Password-protected admin panel for managing products, orders, reviews, and content of the online store.

Admin Panel for the Online Store 'Korobki-optom' — фото 1
click to view full size

Slide 1 of 6

DESCRIPTION

A fully functional admin panel built on top of an existing cardboard packaging online store (Next.js 16 / React 19 / PostgreSQL). This is the second phase of the project: a closed management interface has been added to the public site, transforming the store into a fully self-administered product — the owner manages the catalog, orders, reviews, and all site content without developer involvement and without direct access to the database.

Authentication and access control

The entire `/admin` section is secured by server middleware (proxy): each request to the admin panel checks an httpOnly cookie with a token; in the absence of or mismatch — a redirect to the login page. Authentication is password-based (compared to the environment variable ADMIN_PASSWORD), the session lasts 7 days in a secure cookie with httpOnly and sameSite=lax flags (protection against XSS and CSRF). All admin pages are marked as force-dynamic — data is always up-to-date, without static caching.

Interface and dashboard

The interface is built as a classic CRUD dashboard using server components of the App Router with adaptive sidebar navigation (fixed sidebar on desktop, off-canvas menu on mobile). The main dashboard page concurrently (Promise.all) aggregates summaries across all sections — the number of products, orders, reviews — and displays cards with live counters. Next to the 'Orders' and 'Reviews' items in the sidebar, unread badges are shown: the number of new orders and reviews awaiting moderation.

Product management

Product management — full CRUD with URL-slug generation through automatic transliteration from Cyrillic to Latin. Prices are entered in rubles and stored in kopecks (integer). Advanced image gallery management is implemented: uploading multiple files at once with preliminary compression in the browser (canvas, resize, and re-encoding to JPEG before sending), server-side normalization via sharp (support for Apple HEIC/HEIF format through heic-convert, auto-rotation based on EXIF, mozjpeg) and storage in the database as BYTEA. Images can be managed directly in the form — deleting, reordering with arrows, and designating a main image. The request body limit has been raised to 50 MB for uploading heavy photos.

Orders section

The orders section provides a feed with server-side sorting (by date, status, amount) and expandable cards. Unread orders are visually highlighted; 'unread' is calculated on the database side with a complex SQL condition — an order is considered unread if the admin has not opened it yet OR if the customer has sent a new message after the last view. When the card is expanded, the order is automatically marked as read. Inside — order composition, recipient contacts, lifecycle status switch (new → processing → shipped → delivered / canceled) and an embedded chat with the customer with message polling every 4 seconds; the admin's reply simultaneously marks the order as read.

Review moderation

Review moderation — a separate queue: unapproved reviews are raised to the top and highlighted, with actions 'approve', 'hide', and 'delete' available for each, instantly invalidating public product pages.

Site content management

A separate layer — managing site content without code changes. Through admin panel forms, the main page (hero headers), 'About Us' page (text, dynamic blocks of statistics, principles, and contacts in JSON), FAQ list (with adding, deleting, and reordering questions), and general settings (title, description, color theme selection from ready-made presets) are edited. All this data is stored in a key-value settings table and is immediately reflected on the public site.

Server Actions and database

Technically, all data writing is implemented on Server Actions (without a separate REST API): forms use typed state useActionState (React 19), select fields are automatically submitted on change via requestSubmit, and after each mutation, there is targeted cache invalidation of affected routes via revalidatePath, so changes immediately appear both in the admin panel and on the storefront. Each server action re-checks administrator rights. Database access is through the same connection pool with parameterized queries (protection against SQL injection) in the isolated schema `corobki`.

TOOLS USED

  • Next.js 16 (App Router)
  • React 19
  • React Server Components
  • Server Actions
  • Middleware (proxy)
  • useActionState
  • TypeScript
  • PostgreSQL
  • pg (node-postgres)
  • SQL
  • httpOnly-cookies
  • Tailwind CSS v4
  • Radix UI
  • shadcn/ui
  • lucide-react
  • sharp
  • heic-convert
  • Canvas API
  • FormData API
  • Bun
  • Biome
  • Husky
  • Git

RESULT

  • A closed management interface has been added to the existing online store — the owner fully administers the store independently, without a developer and without direct access to the database.
  • The /admin section is secured by server middleware: password authentication and httpOnly token verification for each request, with a 7-day session with sameSite/httpOnly flags (protection against XSS and CSRF).
  • Full CRUD for products implemented with auto-transliteration from Cyrillic to URL-slug and prices in integer kopecks.
  • Image gallery management built: multi-upload, browser compression (Canvas), server normalization via sharp + heic-convert, deletion, reordering, and designation of the main photo.
  • A dashboard with summary metrics across all sections, collected concurrently (Promise.all), has been created.
  • An unread badge system has been implemented in the sidebar — new orders and reviews awaiting moderation are counted on the database side.
  • An order feed with server-side sorting, highlighting of unread orders, and auto-marking as read upon opening has been implemented.
  • The logic of 'unread order' has been moved to an SQL condition that considers new messages from the customer after the last admin view.
  • Lifecycle status management for orders and an embedded chat with the customer (polling every 4 seconds) have been added.
  • A review moderation queue with actions to approve / hide / delete and instant invalidation of public pages has been created.
  • Editing all site content from the admin panel (main, 'About Us', FAQ, theme, contacts) via a key-value settings store without code changes has been implemented.
  • All mutations are built on type-safe Server Actions with rights checking and targeted cache invalidation via revalidatePath.
  • The interface is adaptive: fixed sidebar on desktop and an off-canvas menu on mobile.

AI-ASSISTANT

Ask a question about this project