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
| Property | Value |
|---|---|
| Brand Name | SUStech |
| Primary Color | #C2121C — Bold Red |
| Background Color | #0B0B0B — Deep Black |
| Market | Bangladesh (BDT currency) |
| Language | English (primary), with support for Bengali labels |
| Target Audience | Non-technical general consumers aged 16–45 |
| Product Category | Tech & 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
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
| KPI | Target | Priority |
|---|---|---|
| Page Load Time | < 3 seconds on 4G | Critical |
| Mobile Responsiveness | 100% responsive (320px+) | Critical |
| Authentication Success Rate | > 98% | Critical |
| Cart Abandonment Rate | < 40% | High |
| Admin Panel Uptime | 99.9% | High |
| Support Ticket Resolution | < 24 hours | Medium |
Technology Stack
Core Technologies
| Layer | Technology | Version | Purpose |
|---|---|---|---|
| Backend Language | PHP | 8.2+ | Server-side logic, APIs, session management |
| Database | MySQL | 8.0+ | Relational data storage (via cPanel phpMyAdmin) |
| Web Server | Apache | 2.4+ | Served via cPanel / .htaccess routing |
| Hosting | cPanel | Latest | File manager, DB, domain, SSL, email |
| Frontend | HTML5 + CSS3 + Vanilla JS | ES2020+ | UI rendering, animations, interactivity |
| CSS Framework | Custom CSS (no Bootstrap) | — | Tailored design system matching brand |
| Authentication | Google OAuth 2.0 | v2 | User login via Google Account |
| Image Storage | cPanel File Manager | — | Product images, category icons stored on server |
| Session | PHP Sessions + MySQL | — | Persistent login state, cart storage |
| Messaging | WhatsApp API (web.whatsapp.com) | — | Per-product WhatsApp share button |
| Animation | CSS Keyframes + JS IntersectionObserver | — | Scroll-triggered animations, hover effects |
Third-Party Integrations
| Service | Purpose | Integration Method |
|---|---|---|
| Google OAuth 2.0 | User authentication | PHP Google Client Library + OAuth callback |
| Google People API | Fetch user name, email, profile picture | REST API after OAuth token exchange |
| Product inquiry sharing | wa.me URL with pre-filled message + product link | |
| PHP Mailer / cPanel Mail | Order confirmation emails | SMTP 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
System Architecture
Application Flow
Request Entry — Apache + .htaccess
All requests route through Apache. .htaccess rewrite rules clean URLs (e.g. /shop → pages/shop.php). Security headers (CSP, X-Frame-Options, HSTS) injected here.
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.
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.
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.
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.
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 Key | Type | Description |
|---|---|---|
user_id | int | DB user ID after Google OAuth |
user_email | string | Google account email |
user_name | string | Google display name |
user_picture | string | Google profile picture URL |
mobile_verified | bool | True after BD mobile entered |
cart | array | Guest cart (product_id → qty map) before DB save |
admin_id | int | Admin session (separate from user) |
oauth_state | string | CSRF token for OAuth flow |
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;
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
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.
Google Authorization Page
User is redirected to Google's consent screen. On approval, Google redirects back to /auth/callback.php?code=XXX&state=YYY.
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.
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.
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.
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
01followed by3–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
| Route | Auth Required | Mobile Required |
|---|---|---|
| /shop, /product/* | No | No |
| /cart (view) | No | No |
| /cart (add), /checkout | Yes | Yes |
| /my-orders, /my-cart | Yes | Yes |
| /support (submit ticket) | Yes | Yes |
| /contact (submit form) | Yes | Yes |
| /edit-profile | Yes | Yes |
| /admin/* | Admin Session | N/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.
Design System
Color Palette
| Token | Hex | Usage |
|---|---|---|
--color-primary | #C2121C | CTAs, highlights, badges, accents |
--color-primary-dark | #9a0e16 | Hover state for primary buttons |
--color-primary-light | #e8363f | Active state, lighter red accents |
--color-bg | #0B0B0B | Page background |
--color-surface | #111111 | Cards, modals |
--color-surface-2 | #1a1a1a | Nested surfaces, table rows |
--color-border | #2a2a2a | Dividers, input borders |
--color-text | #f0f0f0 | Primary text |
--color-text-muted | #888888 | Secondary text, placeholders |
--color-success | #10b981 | Delivered, success states |
--color-warning | #f59e0b | Pending, warning states |
--color-info | #3b82f6 | Confirmed, info states |
Typography
| Element | Font | Size | Weight |
|---|---|---|---|
| Hero Heading | system-ui / Impact fallback | 56–80px | 900 |
| Section Heading (h1) | system-ui | 32–40px | 800 |
| Card Title (h2) | system-ui | 20–24px | 700 |
| Subheading (h3) | system-ui | 16–18px | 600 |
| Body | system-ui | 15–16px | 400 |
| Small / Label | system-ui | 12–13px | 400–500 |
| Price | system-ui | 22–28px | 700 |
| Button | system-ui | 14–16px | 600 |
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
| Variant | Background | Text | Border | Usage |
|---|---|---|---|---|
| Primary | #C2121C | White | None | Buy Now, Place Order, Submit |
| Secondary | Transparent | #C2121C | 1px #C2121C | Add to Cart, View Details |
| #25D366 | White | None | WhatsApp inquiry | |
| Ghost | Transparent | #888 | 1px #2a2a2a | Cancel, secondary actions |
| Danger | #C2121C (10%) | #e8363f | 1px #C2121C | Delete, 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
| Breakpoint | Width | Grid Columns |
|---|---|---|
| xs (mobile) | < 480px | 1 |
| sm | 480–768px | 2 |
| md | 768–1024px | 3 |
| lg (desktop) | 1024px+ | 4 |
Header & Navigation
Header Layout
The header is sticky (position: fixed top), full-width, with a semi-transparent dark background and bottom border. On scroll, a solid black background drops in with a subtle shadow.
Header Elements (Left → Right)
| Element | Desktop | Mobile |
|---|---|---|
| Logo (SVG 1:1) + "SUStech" wordmark | Visible | Visible |
| Nav: Home | Visible | Hamburger menu |
| Nav: Shop | Visible | Hamburger menu |
| Nav: Hot Products | Visible | Hamburger menu |
| Nav: About | Visible | Hamburger menu |
| Nav: Contact | Visible | Hamburger menu |
| Cart Icon (with badge count) | Visible | Visible |
| Login / Account Icon | Visible | Visible |
Account Dropdown (Logged In)
Clicking the account icon opens a dropdown with the user's Google profile picture and name at the top, followed by:
- Dashboard
- My Orders
- My Cart
- Support Tickets
- Edit Profile
- Logout (red, bottom)
Homepage Sections
- Hero Section: Full-screen dark background with animated gradient overlay. Bold headline, sub-text, and two CTAs: "Shop Now" (primary red) and "Hot Products" (secondary outline). Animated floating tech product images on right.
- Category Grid: Main categories displayed as icon cards in a responsive grid with hover animation.
- Hot Products: Horizontally scrollable row of featured product cards.
- Features Banner: 4-column row: Free delivery info, Warranty, Genuine products, Customer support.
- Latest Products: Grid of newest 8 products.
- Testimonials: Static review carousel / grid.
- Newsletter Banner: CTA to contact section.
Shop & Products
Shop Page — Filter Sidebar
| Filter | Type | Behaviour |
|---|---|---|
| Main Category | Accordion list | Filters products by main_category_id. Clicking expands sub-categories. |
| Sub Category | Nested checkbox list | Filters within selected main category. |
| Price Range | Dual-handle slider + number inputs | Filters BETWEEN min and max price in BDT. |
| Sort Order | Select dropdown | Options: 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
| # | Element | Details |
|---|---|---|
| i | Product Image Gallery | Thumbnail on left, large viewer on right. Click thumbnail to switch. Lightbox on click. |
| ii | Product Name | H1, large bold |
| iii | SKU / Category | Small metadata row: SKU code + category breadcrumb |
| iv | Price | Sell price prominent (red), original price struck if discounted. "Save X%" badge. |
| v | Color / Variant Select | If product has multiple stock colors, show color swatches. Selected color updates stock availability. |
| vi | Quantity Selector | Minus [−] | input | Plus [+] buttons. Min 1, max available stock qty. |
| vii | Add to Cart Button | Secondary outline red button. Auth + mobile required. Adds to cart_items, updates cart badge. |
| viii | WhatsApp Button | Same behaviour as card. Pre-fills product name + URL. |
| ix | Buy Now Button | Primary red button. Auth + mobile required. Bypasses cart, goes directly to checkout with this item. |
| x | Warranty Options | Radio buttons if warranties configured. Updates total price display. |
| xi | Features | Bullet list from features JSON. Styled with checkmark icons. |
| xii | Description | Full HTML description rendered safely. Tab: Description / Specs. |
| xiii | Related Products | Same sub-category products grid (4 cards). |
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
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).
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."
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.
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.
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
| Column | Description |
|---|---|
| Order ID | SUS-YYYYMMDD-XXXX format, clickable |
| Customer | User name + email |
| Amount | Total in BDT |
| Status | Colour-coded pill: Pending Confirmed Delivered Cancelled |
| Date | Formatted 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
| Field | Type | Validation |
|---|---|---|
| Product Name | Text | Required, max 200 chars |
| URL Slug | Text (auto-generated) | Required, unique, lowercase-kebab |
| Main Category | Select | Required |
| Sub Category | Select (filtered by main) | Optional |
| Price (BDT) | Number | Required, > 0 |
| Sell Price (BDT) | Number | Optional, must be less than Price |
| Stock (Color + Qty rows) | Dynamic rows | Color optional, qty required per row |
| SKU | Text | Optional |
| Thumbnail Image | File (1 image) | jpg/png/webp, max 2MB |
| Gallery Images | File (up to 5) | jpg/png/webp, max 2MB each |
| Features | Dynamic text rows (add/remove) | Each row is one feature bullet |
| Description | Rich text / Textarea | HTML allowed |
| Featured / Hot Product | Checkbox | Appears in Hot Products section |
| Active / Visible | Toggle | Hidden products won't appear in shop |
| Warranty (month + price rows) | Dynamic rows | Month, 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.
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
| Column | Source |
|---|---|
| Product Name | order_items.product_name (snapshot) |
| Unit Price | order_items.unit_price |
| Quantity | order_items.qty |
| Subtotal | unit_price × qty |
| Shipping | orders.delivery_charge |
| Total | orders.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).
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
| Section | Content |
|---|---|
| Profile Header | Google profile picture, name, Customer ID |
| Account Info | Gmail ID, Mobile Number, Joined Date |
| Account Actions | "Full Deactivate Account" button (sets is_active=0, prevents login) |
| Order History | Table: Order ID | Date | Amount | Status | View Order button |
| Summary | Total 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.
Promo Code Management
New Promo Code Form
| Field | Type | Validation |
|---|---|---|
| Promo Code | Text (uppercase enforced) | Required, unique, alphanumeric + dash only |
| Discount Type | Radio: Percent / Amount | Required |
| Discount Value | Number | Required. If percent, max 100. |
| Start Date | Date picker | Optional. If set, code inactive before this date. |
| Expire Date | Date picker | Optional. If set, code inactive after this date. |
| Min Order (BDT) | Number | Optional. Default 0 = no minimum. |
| Limit per User | Number | Optional. Default 1. |
| Active | Toggle | Inactive 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)
- Code exists and is_active = 1
- Current date is within start_date and expire_date (if set)
- Order subtotal >= min_order
- User usage count < limit_per_user
- If percent: discount = subtotal × (value/100), capped at subtotal
- If amount: discount = min(value, subtotal)
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
| Field | Description |
|---|---|
| Customer Message | Read-only display of original message |
| Order ID | Linked order (if provided), clickable to view order |
| Customer Mobile | Display only |
| Status Update | Dropdown: Open / In Progress / Resolved / Closed |
| Admin Note | Internal note (not visible to customer — for admin reference) |
| Save Changes | Updates ticket status + admin note |
Ticket Status Flow
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_attemptstable 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: XMLHttpRequestheader
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-Tokenheader
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
API Endpoints
All API endpoints are PHP files returning application/json. All state-changing endpoints require POST method and CSRF token validation.
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/cart.php?action=add | POST | User | Add item to cart. Body: product_id, qty, color. |
/api/cart.php?action=update | POST | User | Update cart item qty. Body: cart_item_id, qty. |
/api/cart.php?action=remove | POST | User | Remove item from cart. Body: cart_item_id. |
/api/cart.php?action=count | GET | User | Returns cart item count for badge. |
/api/search.php | GET | None | Query param: q. Returns matching products JSON. |
/api/promo.php | POST | User | Validate promo code. Body: code, order_subtotal. |
/api/order.php | POST | User+Mobile | Place order. Body: shipping details + cart contents + promo. |
/api/ticket.php | POST | User+Mobile | Submit support ticket. Body: subject, message, order_id. |
/api/admin/product.php?action=save | POST | Admin | Create/update product including multipart image upload. |
/api/admin/product.php?action=delete | POST | Admin | Soft-delete product (set is_active=0) or hard delete. |
/api/admin/order-status.php | POST | Admin | Update order status. Body: order_id, status. |
/api/admin/promo.php?action=toggle | POST | Admin | Toggle promo code active state. |
/api/admin/ticket.php | POST | Admin | Update ticket status + admin note. |
/api/admin/settings.php | POST | Admin | Batch update site_settings keys. |
Standard Response Format
{
"success": true | false,
"message": "Human-readable message",
"data": { ... } // Optional payload
}
Deployment Guide
cPanel Setup
Domain & SSL
Point domain to cPanel. Enable Let's Encrypt SSL via cPanel → SSL/TLS Status. Force HTTPS via .htaccess RewriteRule.
MySQL Database Setup
Create database + user in cPanel → MySQL Databases. Grant all privileges. Import SQL schema via phpMyAdmin. Insert default site_settings rows.
File Upload
Upload all project files via cPanel File Manager or FTP to public_html/. Set directory permissions: uploads/ → 755, config/ → 700.
Configure config/db.php
Set DB_HOST (usually localhost), DB_NAME, DB_USER, DB_PASS. Set BASE_URL to production domain.
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.
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
| Setting | Required Value |
|---|---|
| PHP Version | 8.2+ |
| upload_max_filesize | 10MB |
| post_max_size | 12MB |
| max_execution_time | 60 |
| session.cookie_httponly | 1 |
| session.cookie_secure | 1 (on HTTPS) |
| session.use_strict_mode | 1 |
| PDO extension | Enabled |
| GD / Imagick | Enabled (for image resizing) |
| cURL | Enabled (for Google OAuth) |
Development Milestones
| Phase | Deliverables | Duration |
|---|---|---|
| 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