Product Requirements Document · v1.0
E-Commerce Tech Shop
Full PRD
1.0.0
PHP · MySQL · cPanel
Google OAuth 2.0
Section 01

Project Overview

SUStech is a modern e-commerce platform specialising in technology products for the Bangladeshi market. Built on PHP and MySQL with cPanel hosting, it delivers a frictionless shopping experience for non-technical users while providing a powerful admin panel for complete store management.

Brand Identity

PropertyValue
Brand NameSUStech
Primary Color#C2121C — Bold Red
Background Color#0B0B0B — Deep Black
MarketBangladesh (BDT currency)
LanguageEnglish (primary), with support for Bengali labels
Target AudienceNon-technical general consumers aged 16–45
Product CategoryTech & Electronics (mobiles, laptops, accessories, gadgets)

Scope

This PRD covers the complete SUStech web platform including:

  • Customer-facing storefront with full e-commerce functionality
  • Google OAuth 2.0 authentication with mandatory Bangladeshi mobile number verification
  • Multi-step product ordering, cart, and checkout with delivery configuration
  • WhatsApp integration per product for direct seller contact
  • Full-featured admin panel with dashboard analytics, product/order/customer management
  • Promo code engine, support ticket system, and configurable legal pages
  • cPanel + MySQL deployment with secure file storage
Section 02

Objectives & Goals

Primary Objectives

🎯 Business Goal

Launch a fully operational, revenue-generating e-commerce tech store in Bangladesh with complete product lifecycle management from listing to delivery.

👤 User Goal

Allow non-technical Bangladeshi users to discover, compare, and purchase tech products with minimal friction using their Google account and mobile number.

🔐 Trust Goal

Build customer confidence through verified identity (Google + BD mobile), transparent order tracking, and responsive support tickets.

⚙️ Operations Goal

Give admins complete control over every aspect of the store — products, orders, customers, promotions — through a clean, powerful dashboard.

Key Performance Indicators

KPITargetPriority
Page Load Time< 3 seconds on 4GCritical
Mobile Responsiveness100% responsive (320px+)Critical
Authentication Success Rate> 98%Critical
Cart Abandonment Rate< 40%High
Admin Panel Uptime99.9%High
Support Ticket Resolution< 24 hoursMedium
Section 03

Technology Stack

Core Technologies

LayerTechnologyVersionPurpose
Backend LanguagePHP8.2+Server-side logic, APIs, session management
DatabaseMySQL8.0+Relational data storage (via cPanel phpMyAdmin)
Web ServerApache2.4+Served via cPanel / .htaccess routing
HostingcPanelLatestFile manager, DB, domain, SSL, email
FrontendHTML5 + CSS3 + Vanilla JSES2020+UI rendering, animations, interactivity
CSS FrameworkCustom CSS (no Bootstrap)Tailored design system matching brand
AuthenticationGoogle OAuth 2.0v2User login via Google Account
Image StoragecPanel File ManagerProduct images, category icons stored on server
SessionPHP Sessions + MySQLPersistent login state, cart storage
MessagingWhatsApp API (web.whatsapp.com)Per-product WhatsApp share button
AnimationCSS Keyframes + JS IntersectionObserverScroll-triggered animations, hover effects

Third-Party Integrations

ServicePurposeIntegration Method
Google OAuth 2.0User authenticationPHP Google Client Library + OAuth callback
Google People APIFetch user name, email, profile pictureREST API after OAuth token exchange
WhatsAppProduct inquiry sharingwa.me URL with pre-filled message + product link
PHP Mailer / cPanel MailOrder confirmation emailsSMTP via cPanel email account

File Structure

sustech/
├── index.php                  ← Homepage / Hero
├── .htaccess                  ← URL rewriting + security headers
├── config/
│   ├── db.php                 ← MySQL PDO connection
│   ├── google-oauth.php       ← OAuth credentials + flow
│   └── constants.php          ← Site-wide constants (colors, WhatsApp no.)
├── auth/
│   ├── login.php              ← Google OAuth redirect
│   ├── callback.php           ← OAuth callback handler
│   ├── mobile-verify.php      ← BD mobile number entry page
│   └── logout.php             ← Session destroy + redirect
├── pages/
│   ├── shop.php               ← Product listing + filters
│   ├── product.php            ← Single product detail
│   ├── cart.php               ← Shopping cart
│   ├── checkout.php           ← Checkout form + order placement
│   ├── order-success.php      ← Post-order confirmation
│   ├── my-orders.php          ← User order history
│   ├── my-cart.php            ← Saved cart
│   ├── support.php            ← Support ticket form + list
│   ├── edit-profile.php       ← Update name, mobile
│   ├── hot-products.php       ← Featured/hot products page
│   ├── about.php              ← About SUStech
│   └── contact.php            ← Contact form
├── admin/
│   ├── index.php              ← Admin dashboard
│   ├── login.php              ← Admin login (separate credentials)
│   ├── products.php           ← Product management + upload
│   ├── categories.php         ← Main + sub-category management
│   ├── orders.php             ← Order management
│   ├── customers.php          ← Customer list + profiles
│   ├── promo-codes.php        ← Promo code CRUD
│   ├── support-tickets.php    ← Ticket management
│   ├── legal-pages.php        ← Privacy + Terms editor
│   ├── footer-settings.php    ← Footer content editor
│   ├── delivery-charges.php   ← Delivery rate settings
│   └── logout.php             ← Admin logout
├── api/
│   ├── cart.php               ← Cart CRUD (AJAX)
│   ├── order.php              ← Place order (AJAX)
│   ├── search.php             ← Product search (AJAX)
│   ├── ticket.php             ← Support ticket submit (AJAX)
│   └── admin/
│       ├── product.php        ← Product CRUD
│       ├── order-status.php   ← Update order status
│       └── promo.php          ← Promo code validation
├── includes/
│   ├── header.php             ← Site header partial
│   ├── footer.php             ← Site footer partial
│   ├── auth-guard.php         ← Redirect if not logged in
│   ├── mobile-guard.php       ← Redirect if mobile not set
│   └── admin-guard.php        ← Admin auth check
├── assets/
│   ├── css/
│   │   ├── main.css           ← Global styles + design tokens
│   │   ├── animations.css     ← Keyframes + scroll-reveal
│   │   └── admin.css          ← Admin panel styles
│   ├── js/
│   │   ├── app.js             ← Global JS (nav, toast, scroll)
│   │   ├── shop.js            ← Filter, sort, search
│   │   ├── product.js         ← Gallery, qty, cart actions
│   │   ├── cart.js            ← Cart AJAX operations
│   │   └── admin.js           ← Admin panel interactions
│   └── images/
│       ├── logo.svg
│       ├── logo-white.svg
│       ├── favicon.ico
│       ├── products/          ← Uploaded product images
│       └── categories/        ← Category icons
└── uploads/
    ├── products/              ← Thumbnail + gallery images
    └── categories/            ← Category images
Section 04

System Architecture

Application Flow

1

Request Entry — Apache + .htaccess

All requests route through Apache. .htaccess rewrite rules clean URLs (e.g. /shoppages/shop.php). Security headers (CSP, X-Frame-Options, HSTS) injected here.

2

Auth Middleware — includes/auth-guard.php

All protected pages include auth-guard.php which checks $_SESSION['user_id']. If missing, redirect to /auth/login. After Google login, mobile-guard.php checks if mobile number is set.

3

Controller Logic — PHP page files

Each page file handles its own business logic: fetch data from MySQL via PDO, validate input, compute state, then output HTML. No MVC framework; logic is cleanly separated from presentation via include partials.

4

Database Layer — MySQL via PDO

All database access uses PHP PDO with prepared statements. Connection pooling is handled by cPanel MySQL. Sensitive queries (auth, orders) use transactions.

5

AJAX APIs — api/ directory

Dynamic operations (add to cart, search, update order status) hit JSON endpoints in /api/. All return application/json. Admin APIs additionally verify admin session.

6

File Upload — cPanel File Manager

Product images uploaded via admin panel are moved to /uploads/products/ and /uploads/categories/. PHP validates file type (jpg/png/webp), max size 2MB, generates unique filename with timestamp.

Session Architecture

Session KeyTypeDescription
user_idintDB user ID after Google OAuth
user_emailstringGoogle account email
user_namestringGoogle display name
user_picturestringGoogle profile picture URL
mobile_verifiedboolTrue after BD mobile entered
cartarrayGuest cart (product_id → qty map) before DB save
admin_idintAdmin session (separate from user)
oauth_statestringCSRF token for OAuth flow
Section 05

Database Schema

All tables use InnoDB engine with UTF8MB4 charset. Foreign keys enforce referential integrity.

users

CREATE TABLE users (
  id            INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  google_id     VARCHAR(50)  UNIQUE NOT NULL,
  email         VARCHAR(150) UNIQUE NOT NULL,
  name          VARCHAR(100) NOT NULL,
  picture       VARCHAR(500),
  mobile        VARCHAR(14)  NULL,          -- BD format: +8801XXXXXXXXX
  is_active     TINYINT(1)   DEFAULT 1,
  created_at    TIMESTAMP    DEFAULT CURRENT_TIMESTAMP,
  updated_at    TIMESTAMP    DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

main_categories

CREATE TABLE main_categories (
  id        INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name      VARCHAR(100) NOT NULL,
  slug      VARCHAR(120) UNIQUE NOT NULL,
  image     VARCHAR(300),
  sort_order INT DEFAULT 0,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

sub_categories

CREATE TABLE sub_categories (
  id               INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  main_category_id INT UNSIGNED NOT NULL,
  name             VARCHAR(100) NOT NULL,
  slug             VARCHAR(120) UNIQUE NOT NULL,
  image            VARCHAR(300),
  sort_order       INT DEFAULT 0,
  created_at       TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (main_category_id) REFERENCES main_categories(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

products

CREATE TABLE products (
  id               INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name             VARCHAR(200) NOT NULL,
  slug             VARCHAR(220) UNIQUE NOT NULL,
  main_category_id INT UNSIGNED,
  sub_category_id  INT UNSIGNED,
  price            DECIMAL(12,2) NOT NULL,
  sell_price       DECIMAL(12,2),
  sku              VARCHAR(100),
  thumbnail        VARCHAR(300),
  features         TEXT,                    -- JSON array of feature strings
  description      LONGTEXT,
  is_featured      TINYINT(1) DEFAULT 0,    -- Hot Product flag
  is_active        TINYINT(1) DEFAULT 1,
  warranty_data    TEXT,                    -- JSON [{months, is_free, price}]
  created_at       TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at       TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (main_category_id) REFERENCES main_categories(id) ON DELETE SET NULL,
  FOREIGN KEY (sub_category_id)  REFERENCES sub_categories(id)  ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

product_images

CREATE TABLE product_images (
  id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  product_id INT UNSIGNED NOT NULL,
  image_path VARCHAR(300) NOT NULL,
  sort_order INT DEFAULT 0,
  FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

product_stock

CREATE TABLE product_stock (
  id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  product_id INT UNSIGNED NOT NULL,
  color      VARCHAR(50),
  qty        INT UNSIGNED DEFAULT 0,
  FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

orders

CREATE TABLE orders (
  id              INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  order_number    VARCHAR(20) UNIQUE NOT NULL,   -- e.g. SUS-20240512-0001
  user_id         INT UNSIGNED NOT NULL,
  status          ENUM('pending','confirmed','shipped','delivered','cancelled') DEFAULT 'pending',
  subtotal        DECIMAL(12,2) NOT NULL,
  delivery_charge DECIMAL(10,2) NOT NULL,
  discount        DECIMAL(10,2) DEFAULT 0,
  total           DECIMAL(12,2) NOT NULL,
  promo_code      VARCHAR(30),
  customer_note   TEXT,
  shipping_name   VARCHAR(100) NOT NULL,
  shipping_mobile VARCHAR(14)  NOT NULL,
  shipping_address TEXT        NOT NULL,
  shipping_city   VARCHAR(100) NOT NULL,
  created_at      TIMESTAMP   DEFAULT CURRENT_TIMESTAMP,
  updated_at      TIMESTAMP   DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

order_items

CREATE TABLE order_items (
  id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  order_id    INT UNSIGNED NOT NULL,
  product_id  INT UNSIGNED,
  product_name VARCHAR(200) NOT NULL,     -- snapshot at time of order
  unit_price  DECIMAL(12,2) NOT NULL,
  qty         INT UNSIGNED NOT NULL,
  color       VARCHAR(50),
  subtotal    DECIMAL(12,2) NOT NULL,
  FOREIGN KEY (order_id)   REFERENCES orders(id)   ON DELETE CASCADE,
  FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

cart_items

CREATE TABLE cart_items (
  id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  user_id    INT UNSIGNED NOT NULL,
  product_id INT UNSIGNED NOT NULL,
  color      VARCHAR(50),
  qty        INT UNSIGNED DEFAULT 1,
  added_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uq_cart (user_id, product_id, color),
  FOREIGN KEY (user_id)    REFERENCES users(id)    ON DELETE CASCADE,
  FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

promo_codes

CREATE TABLE promo_codes (
  id             INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  code           VARCHAR(30) UNIQUE NOT NULL,
  discount_type  ENUM('percent','amount') NOT NULL,
  discount_value DECIMAL(10,2) NOT NULL,
  min_order      DECIMAL(10,2) DEFAULT 0,
  limit_per_user INT UNSIGNED DEFAULT 1,
  start_date     DATE,
  expire_date    DATE,
  is_active      TINYINT(1) DEFAULT 1,
  created_at     TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

promo_code_usage

CREATE TABLE promo_code_usage (
  id        INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  promo_id  INT UNSIGNED NOT NULL,
  user_id   INT UNSIGNED NOT NULL,
  order_id  INT UNSIGNED NOT NULL,
  used_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (promo_id) REFERENCES promo_codes(id),
  FOREIGN KEY (user_id)  REFERENCES users(id),
  FOREIGN KEY (order_id) REFERENCES orders(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

support_tickets

CREATE TABLE support_tickets (
  id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  user_id    INT UNSIGNED NOT NULL,
  order_id   INT UNSIGNED,
  subject    VARCHAR(200) NOT NULL,
  message    TEXT NOT NULL,
  mobile     VARCHAR(14),
  status     ENUM('open','in_progress','resolved','closed') DEFAULT 'open',
  admin_note TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id)  REFERENCES users(id),
  FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

site_settings

CREATE TABLE site_settings (
  setting_key   VARCHAR(100) PRIMARY KEY,
  setting_value TEXT,
  updated_at    TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Default rows:
INSERT INTO site_settings VALUES
('whatsapp_number',  '+8801XXXXXXXXX', NOW()),
('delivery_inside_dhaka',  '60', NOW()),
('delivery_outside_dhaka', '120', NOW()),
('footer_description', 'SUStech — Your trusted tech shop in Bangladesh.', NOW()),
('footer_address',  'Dhaka, Bangladesh', NOW()),
('footer_phone',    '+8801XXXXXXXXX', NOW()),
('footer_email',    'info@sustech.com.bd', NOW()),
('footer_facebook', '', NOW()),
('footer_instagram','', NOW()),
('footer_tiktok',   '', NOW()),
('footer_copyright','© 2024 SUStech. All rights reserved.', NOW()),
('privacy_content', '', NOW()),
('terms_content',   '', NOW());

admin_users

CREATE TABLE admin_users (
  id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  username   VARCHAR(50) UNIQUE NOT NULL,
  password   VARCHAR(255) NOT NULL,   -- bcrypt hashed
  email      VARCHAR(150),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Section 06

Authentication Flow

All customer authentication uses Google OAuth 2.0. No password is ever stored. After OAuth, new users must enter a valid Bangladeshi mobile number before accessing protected actions.

Google OAuth 2.0 Flow

1

User Clicks "Login with Google"

Front-end redirects to /auth/login.php. Server generates a random CSRF state token stored in $_SESSION['oauth_state'], then builds the Google authorization URL with scopes openid email profile.

2

Google Authorization Page

User is redirected to Google's consent screen. On approval, Google redirects back to /auth/callback.php?code=XXX&state=YYY.

3

Callback Processing (callback.php)

Server verifies state matches session to prevent CSRF. Exchanges authorization code for access token via POST to https://oauth2.googleapis.com/token. Fetches user info from https://www.googleapis.com/oauth2/v3/userinfo.

4

User Record Upsert

If google_id exists in users table → update name and picture. If new user → INSERT record. Set session: user_id, user_email, user_name, user_picture.

5

Mobile Number Gate

If users.mobile is NULL → redirect to /auth/mobile-verify.php. User enters a Bangladeshi mobile in the format 01XXXXXXXXX (11 digits, starts with 01). Stored as +880XXXXXXXXXX after validation via regex. Set $_SESSION['mobile_verified'] = true.

6

Redirect to Intended Page

After successful login + mobile verification, redirect to the originally requested URL (stored in $_SESSION['redirect_after_login']) or homepage.

Mobile Number Validation Rules

Regex: /^01[3-9]\d{8}$/ — accepts 11-digit Bangladeshi numbers starting with 013–019. Stored in DB as +880 + 10 remaining digits.

  • Must be exactly 11 digits
  • Must begin with 01 followed by 3–9
  • No duplicate mobile numbers allowed across accounts
  • User can update mobile from Edit Profile (re-validation required)
  • Admin can view but not modify mobile from Customer Management

Protected Routes

RouteAuth RequiredMobile Required
/shop, /product/*NoNo
/cart (view)NoNo
/cart (add), /checkoutYesYes
/my-orders, /my-cartYesYes
/support (submit ticket)YesYes
/contact (submit form)YesYes
/edit-profileYesYes
/admin/*Admin SessionN/A

Admin Authentication

Admin login is completely separate from Google OAuth. Admins log in at /admin/login.php with a username and bcrypt-hashed password stored in the admin_users table. Admin sessions use a separate key (admin_id) so customer sessions cannot grant admin access.

Section 07

Design System

Color Palette

TokenHexUsage
--color-primary#C2121CCTAs, highlights, badges, accents
--color-primary-dark#9a0e16Hover state for primary buttons
--color-primary-light#e8363fActive state, lighter red accents
--color-bg#0B0B0BPage background
--color-surface#111111Cards, modals
--color-surface-2#1a1a1aNested surfaces, table rows
--color-border#2a2a2aDividers, input borders
--color-text#f0f0f0Primary text
--color-text-muted#888888Secondary text, placeholders
--color-success#10b981Delivered, success states
--color-warning#f59e0bPending, warning states
--color-info#3b82f6Confirmed, info states

Typography

ElementFontSizeWeight
Hero Headingsystem-ui / Impact fallback56–80px900
Section Heading (h1)system-ui32–40px800
Card Title (h2)system-ui20–24px700
Subheading (h3)system-ui16–18px600
Bodysystem-ui15–16px400
Small / Labelsystem-ui12–13px400–500
Pricesystem-ui22–28px700
Buttonsystem-ui14–16px600

Animation Principles

  • Scroll-reveal: Elements fade + slide up (translateY 30px → 0, opacity 0 → 1) when entering viewport via IntersectionObserver. Duration 500ms, ease-out.
  • Hero entrance: Staggered animation — logo first (200ms), tagline (400ms), CTA button (600ms).
  • Product card hover: Scale 1 → 1.03, box-shadow deepens, "View Details" button slides up from bottom.
  • Button hover: Background shift + subtle scale 0.98 on active.
  • Page transitions: Soft opacity fade-in on load (opacity 0 → 1, 300ms).
  • Toast notifications: Slide in from right (translateX 120% → 0), auto-dismiss after 3.5s with fade-out.
  • Cart icon: Bounce animation on item add (+1 badge pulse).
  • Skeleton loading: Shimmer effect on product cards while AJAX loading.

Component Specs

Buttons

VariantBackgroundTextBorderUsage
Primary#C2121CWhiteNoneBuy Now, Place Order, Submit
SecondaryTransparent#C2121C1px #C2121CAdd to Cart, View Details
WhatsApp#25D366WhiteNoneWhatsApp inquiry
GhostTransparent#8881px #2a2a2aCancel, secondary actions
Danger#C2121C (10%)#e8363f1px #C2121CDelete, Cancel order

Product Card

  • Width: fluid (min 240px, max 320px)
  • Border radius: 12px
  • Background: --color-surface
  • Border: 1px solid --color-border
  • Thumbnail: 16:9 ratio, object-fit: cover
  • Price: red, bold, 22px
  • Original price: struck through if sell_price present
  • Hover: card lifts (box-shadow), action buttons slide in from bottom

Mobile-First Breakpoints

BreakpointWidthGrid Columns
xs (mobile)< 480px1
sm480–768px2
md768–1024px3
lg (desktop)1024px+4
Section 09

Shop & Products

Shop Page — Filter Sidebar

FilterTypeBehaviour
Main CategoryAccordion listFilters products by main_category_id. Clicking expands sub-categories.
Sub CategoryNested checkbox listFilters within selected main category.
Price RangeDual-handle slider + number inputsFilters BETWEEN min and max price in BDT.
Sort OrderSelect dropdownOptions: Default, Price Low→High, Price High→Low, Newest First

Behaviour

  • Filters update URL query params (?cat=&sub=&min=&max=&sort=) for shareable URLs
  • AJAX fetch re-renders product grid without full page reload
  • Mobile: filter sidebar collapses into a bottom sheet / modal overlay
  • Result count displayed: "Showing 24 of 156 products"
  • Pagination: 24 products per page, numbered + previous/next
  • Search bar at top: live AJAX search with debounce (300ms)

Product Card

Product Card Elements

  • Thumbnail image (16:9, lazy loaded)
  • "Hot" badge if is_featured = 1
  • Product Name (2 line clamp)
  • Price (sell_price if set, else price)
  • Original price struck through if discounted
  • "View Details" button → product page
  • WhatsApp button (green)
  • "Buy" button (red primary)

WhatsApp Button Behaviour

Clicking WhatsApp opens: https://wa.me/{whatsapp_number}?text=I'm interested to buy this: {product_name} — {product_url}. The WhatsApp number is fetched from site_settings and is editable by Admin. No login required to use WhatsApp button.

Product Detail Page

#ElementDetails
iProduct Image GalleryThumbnail on left, large viewer on right. Click thumbnail to switch. Lightbox on click.
iiProduct NameH1, large bold
iiiSKU / CategorySmall metadata row: SKU code + category breadcrumb
ivPriceSell price prominent (red), original price struck if discounted. "Save X%" badge.
vColor / Variant SelectIf product has multiple stock colors, show color swatches. Selected color updates stock availability.
viQuantity SelectorMinus [−] | input | Plus [+] buttons. Min 1, max available stock qty.
viiAdd to Cart ButtonSecondary outline red button. Auth + mobile required. Adds to cart_items, updates cart badge.
viiiWhatsApp ButtonSame behaviour as card. Pre-fills product name + URL.
ixBuy Now ButtonPrimary red button. Auth + mobile required. Bypasses cart, goes directly to checkout with this item.
xWarranty OptionsRadio buttons if warranties configured. Updates total price display.
xiFeaturesBullet list from features JSON. Styled with checkmark icons.
xiiDescriptionFull HTML description rendered safely. Tab: Description / Specs.
xiiiRelated ProductsSame sub-category products grid (4 cards).
Section 10

Cart & Checkout

Cart Page

Displays all items in cart_items for the logged-in user. Each row shows: thumbnail, product name, color, unit price, quantity (editable), subtotal. Qty changes trigger AJAX update. Remove button (×) removes item. Cart totals section on right: subtotal, delivery charge (based on city), discount (if promo applied), total.

Promo Code

Text input + "Apply" button. AJAX POST to /api/promo.php. Server validates: code exists, is active, within date range, min order met, user hasn't exceeded limit. Returns discount amount. Displayed in cart summary. Error toast if invalid.

Checkout Flow

1

Shipping Details Form

Fields: Full Name (pre-filled from profile), Mobile Number (pre-filled), Division/District/City dropdown, Full Address (textarea), Customer Note (optional). City selection auto-updates delivery charge (Inside Dhaka / Outside Dhaka).

2

Order Review

Full order summary: all items with qty and price, delivery charge, promo discount, final total in BDT. "Edit Cart" link. Confirmation checkbox: "I confirm my order details are correct."

3

Place Order

POST to /api/order.php. Validates: user auth, stock availability, promo recheck. Generates order number (SUS-YYYYMMDD-XXXX). Creates orders + order_items rows in transaction. Clears cart. Sends confirmation email.

4

Order Success Page

Shows order number, estimated delivery, order summary. Green success animation. Buttons: "Continue Shopping" and "Track My Order" (→ my-orders page).

Delivery Charge Logic

If shipping_city is "Dhaka" → apply delivery_inside_dhaka setting. Otherwise → apply delivery_outside_dhaka setting. Both values are set by admin in Delivery Charge Settings and stored in site_settings.

My Orders Page

Lists all orders for the logged-in user in reverse chronological order. Each row: Order Number, Date, Total (BDT), Status pill, "View Details" button. Clicking View Details expands an accordion showing all order items, shipping address, and timeline of status changes.

Section 11

Admin Panel

The admin panel (/admin/) is a separate PHP application with its own authentication, layout, and styles. It is inaccessible to any user without a valid admin session.

Admin Sidebar Navigation

  • Dashboard
  • Products
  • Categories
  • Orders
  • Customers
  • Promo Codes
  • Support Tickets
  • Legal Pages
  • Footer
  • Delivery Charges
  • Logout

Dashboard

Stats Cards (Top Row)

Total Products

COUNT(products)

Total Orders

COUNT(orders)

Pending Orders

COUNT WHERE status=pending

Total Revenue

SUM(orders.total) WHERE delivered

Total Customers

COUNT(users)

Recent Orders Table

ColumnDescription
Order IDSUS-YYYYMMDD-XXXX format, clickable
CustomerUser name + email
AmountTotal in BDT
StatusColour-coded pill: Pending Confirmed Delivered Cancelled
DateFormatted date
Actions"Manage" button → Order detail modal

Product Management

Product List Table Columns

Search bar (live filter by name/SKU), then table: ID | Thumbnail | Product Name | Category | Price | Stock | Status (Active/Hidden badge) | Actions (Edit / Delete).

Add / Edit Product Form

FieldTypeValidation
Product NameTextRequired, max 200 chars
URL SlugText (auto-generated)Required, unique, lowercase-kebab
Main CategorySelectRequired
Sub CategorySelect (filtered by main)Optional
Price (BDT)NumberRequired, > 0
Sell Price (BDT)NumberOptional, must be less than Price
Stock (Color + Qty rows)Dynamic rowsColor optional, qty required per row
SKUTextOptional
Thumbnail ImageFile (1 image)jpg/png/webp, max 2MB
Gallery ImagesFile (up to 5)jpg/png/webp, max 2MB each
FeaturesDynamic text rows (add/remove)Each row is one feature bullet
DescriptionRich text / TextareaHTML allowed
Featured / Hot ProductCheckboxAppears in Hot Products section
Active / VisibleToggleHidden products won't appear in shop
Warranty (month + price rows)Dynamic rowsMonth, is_free toggle, price (if not free)

Category Management

Main Category

Form: Name, URL Slug (auto), Icon/Image (1:1, 1 file). Table: Image | Name | Slug | Sub-category count | Edit / Delete.

Sub-Category

Form: Main Category select, Sub-name, URL Slug, Image (1:1, 1 file). Table: Image | Main Category | Sub-category | Slug | Edit / Delete.

Warning: Deleting a main category cascades to sub-categories. Products are set to NULL category. Admin is warned via JS confirmation dialog before delete.

Section 12

Order Management

Order List

Filter tabs at top: All | Pending | Confirmed | Shipped | Delivered | Cancelled. Each shows count badge. Table columns: Order ID | Customer | City | Shipping (BDT) | Amount | Status | Date | Actions.

Manage Order Modal / Page

Update Fulfillment Status

Dropdown: Pending → Confirmed → Shipped → Delivered → Cancelled. "Update Status" button. Status changes are logged. Customer gets email notification on status update.

Ordered Items Table

ColumnSource
Product Nameorder_items.product_name (snapshot)
Unit Priceorder_items.unit_price
Quantityorder_items.qty
Subtotalunit_price × qty
Shippingorders.delivery_charge
Totalorders.total

Additional Order Info Sections

  • Customer Profile: Name, email, mobile, link to full customer profile and order history.
  • Shipping Details: Recipient name, mobile, full address, city.
  • Customer Note: Any note the customer left at checkout.
  • Promo Code: Code used and discount amount (if any).
Section 13

Customer Management

Customer List

Search bar (by name, email, mobile). Table: Avatar + Name | Contact Info (email + mobile) | Joined Date | Orders count | Total Spent (BDT) | Status (Active/Deactivated) | Actions (View Profile).

Customer Profile View

SectionContent
Profile HeaderGoogle profile picture, name, Customer ID
Account InfoGmail ID, Mobile Number, Joined Date
Account Actions"Full Deactivate Account" button (sets is_active=0, prevents login)
Order HistoryTable: Order ID | Date | Amount | Status | View Order button
SummaryTotal Spent (BDT), Total Order count

Deactivation: When admin deactivates an account, the user's Google login will be rejected at callback.php (is_active check). User sees a "Your account has been suspended" message. Admin can reactivate from the same profile page.

Section 14

Promo Code Management

New Promo Code Form

FieldTypeValidation
Promo CodeText (uppercase enforced)Required, unique, alphanumeric + dash only
Discount TypeRadio: Percent / AmountRequired
Discount ValueNumberRequired. If percent, max 100.
Start DateDate pickerOptional. If set, code inactive before this date.
Expire DateDate pickerOptional. If set, code inactive after this date.
Min Order (BDT)NumberOptional. Default 0 = no minimum.
Limit per UserNumberOptional. Default 1.
ActiveToggleInactive codes cannot be applied at checkout.

Promo Code List Table

Columns: Code | Discount | Validity (start–expire dates) | Limit per user | Usage count | Status | Actions (Edit / Delete / Toggle Active).

Validation Logic (checkout)

  1. Code exists and is_active = 1
  2. Current date is within start_date and expire_date (if set)
  3. Order subtotal >= min_order
  4. User usage count < limit_per_user
  5. If percent: discount = subtotal × (value/100), capped at subtotal
  6. If amount: discount = min(value, subtotal)
Section 15

Support Tickets

Customer Support Page

Auth + mobile required. Customer fills out: Subject (dropdown presets + custom), Order ID (optional, with order picker), Message (textarea), Pre-filled mobile. Submit creates a ticket. Customer sees their open tickets below the form with current status.

Admin — Ticket List

Columns: Ticket # | User (name + email) | Subject | Status pill | Date | Actions (Process / Delete).

Process Ticket Panel

FieldDescription
Customer MessageRead-only display of original message
Order IDLinked order (if provided), clickable to view order
Customer MobileDisplay only
Status UpdateDropdown: Open / In Progress / Resolved / Closed
Admin NoteInternal note (not visible to customer — for admin reference)
Save ChangesUpdates ticket status + admin note

Ticket Status Flow

Open In Progress Resolved Closed
Section 17

Security Requirements

Authentication Security

  • All OAuth state tokens are random 32-byte hex values (CSRF protection)
  • Google access tokens are never stored in DB; only user profile data
  • Admin passwords are bcrypt-hashed (cost factor 12)
  • Admin login rate-limited: max 5 failed attempts per 15 minutes (stored in login_attempts table or APCu)
  • Sessions regenerated after login (session_regenerate_id(true))
  • Session cookie: HttpOnly, Secure, SameSite=Strict

Input Validation & SQL Injection Prevention

  • All DB queries use PDO prepared statements — no string interpolation
  • All user input sanitized with htmlspecialchars() before output
  • File uploads: validate MIME type via finfo_file(), not just extension; regenerate filenames; store outside webroot if possible
  • Integer IDs validated with filter_var($id, FILTER_VALIDATE_INT)
  • AJAX endpoints verify X-Requested-With: XMLHttpRequest header

CSRF Protection

  • All state-changing forms include a hidden CSRF token generated per session
  • Token validated server-side on every POST
  • AJAX requests include CSRF token in X-CSRF-Token header

HTTP Security Headers (.htaccess)

Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# HSTS (enable after SSL confirmed)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

Data Privacy (PDPA Compliance Basics)

  • Only data necessary for order fulfilment is collected (name, email, mobile, address)
  • Google profile picture URL stored (not the image itself)
  • Privacy Policy page clearly lists what data is collected and why
  • Admin cannot view or modify user Google tokens
  • Account deactivation (not deletion) available via admin; full deletion policy described in Privacy Policy
Section 18

API Endpoints

All API endpoints are PHP files returning application/json. All state-changing endpoints require POST method and CSRF token validation.

EndpointMethodAuthDescription
/api/cart.php?action=addPOSTUserAdd item to cart. Body: product_id, qty, color.
/api/cart.php?action=updatePOSTUserUpdate cart item qty. Body: cart_item_id, qty.
/api/cart.php?action=removePOSTUserRemove item from cart. Body: cart_item_id.
/api/cart.php?action=countGETUserReturns cart item count for badge.
/api/search.phpGETNoneQuery param: q. Returns matching products JSON.
/api/promo.phpPOSTUserValidate promo code. Body: code, order_subtotal.
/api/order.phpPOSTUser+MobilePlace order. Body: shipping details + cart contents + promo.
/api/ticket.phpPOSTUser+MobileSubmit support ticket. Body: subject, message, order_id.
/api/admin/product.php?action=savePOSTAdminCreate/update product including multipart image upload.
/api/admin/product.php?action=deletePOSTAdminSoft-delete product (set is_active=0) or hard delete.
/api/admin/order-status.phpPOSTAdminUpdate order status. Body: order_id, status.
/api/admin/promo.php?action=togglePOSTAdminToggle promo code active state.
/api/admin/ticket.phpPOSTAdminUpdate ticket status + admin note.
/api/admin/settings.phpPOSTAdminBatch update site_settings keys.

Standard Response Format

{
  "success": true | false,
  "message": "Human-readable message",
  "data": { ... }   // Optional payload
}
Section 19

Deployment Guide

cPanel Setup

1

Domain & SSL

Point domain to cPanel. Enable Let's Encrypt SSL via cPanel → SSL/TLS Status. Force HTTPS via .htaccess RewriteRule.

2

MySQL Database Setup

Create database + user in cPanel → MySQL Databases. Grant all privileges. Import SQL schema via phpMyAdmin. Insert default site_settings rows.

3

File Upload

Upload all project files via cPanel File Manager or FTP to public_html/. Set directory permissions: uploads/ → 755, config/ → 700.

4

Configure config/db.php

Set DB_HOST (usually localhost), DB_NAME, DB_USER, DB_PASS. Set BASE_URL to production domain.

5

Google OAuth Setup

Create OAuth 2.0 credentials in Google Cloud Console. Authorized redirect URI: https://sustech.com.bd/auth/callback.php. Add CLIENT_ID and CLIENT_SECRET to config/google-oauth.php.

6

Test All Flows

Test: Google login → mobile entry → add to cart → checkout → order placed. Test admin login → add product → update order status. Verify emails sent via cPanel SMTP.

PHP Configuration Requirements

SettingRequired Value
PHP Version8.2+
upload_max_filesize10MB
post_max_size12MB
max_execution_time60
session.cookie_httponly1
session.cookie_secure1 (on HTTPS)
session.use_strict_mode1
PDO extensionEnabled
GD / ImagickEnabled (for image resizing)
cURLEnabled (for Google OAuth)
Section 20

Development Milestones

PhaseDeliverablesDuration
Phase 1 — Foundation Project setup, DB schema, cPanel config, Google OAuth, mobile verification, header/footer partials, CSS design system, animation framework 1.5 weeks
Phase 2 — Shop Core Homepage, Shop page with filters, Product detail page, Cart (add/update/remove), Search 2 weeks
Phase 3 — Checkout & Orders Checkout flow, Order placement API, Order success page, My Orders page, Promo code engine 1.5 weeks
Phase 4 — Admin Panel Admin auth, Dashboard, Product CRUD + image upload, Category management, Order management 2 weeks
Phase 5 — Admin Advanced Customer management, Promo codes, Support tickets, Footer/legal editor, Delivery charges, WhatsApp number setting 1.5 weeks
Phase 6 — Polish & Testing Mobile responsive QA, security hardening, performance optimisation, cross-browser testing, email templates, UAT 1 week
Phase 7 — Launch Production deployment, SSL, DNS, admin onboarding, first products seeded, go-live 0.5 week

SUStech PRD v1.0 — Confidential & Proprietary — All rights reserved