Merge branch 'beta'
This commit is contained in:
commit
37c2acb724
13 changed files with 4123 additions and 263 deletions
49
.forgejo/workflows/ci-cd-beta.yml
Normal file
49
.forgejo/workflows/ci-cd-beta.yml
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
name: Beta CI/CD Pipeline
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- beta
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: npm run test
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Upload Build Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: dist
|
||||||
|
path: dist/
|
||||||
|
|
||||||
|
deploy-beta:
|
||||||
|
needs: build-and-test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Download Build Artifact
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: dist
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
- name: Deploy to Beta via FTP
|
||||||
|
env:
|
||||||
|
FTP_USERNAME: ${{ secrets.BETA_FTP_USERNAME }}
|
||||||
|
FTP_PASSWORD: ${{ secrets.BETA_FTP_PASSWORD }}
|
||||||
|
FTP_HOST: ${{ secrets.FTP_HOST }}
|
||||||
|
run: |
|
||||||
|
lftp -d -u "$FTP_USERNAME","$FTP_PASSWORD" -e "set ssl:verify-certificate no; set ftp:ssl-allow yes; set ftp:ssl-force true; set ftp:ssl-protect-data true; set ftp:passive-mode true; mirror -R dist/ ./; quit" $FTP_HOST
|
||||||
51
.forgejo/workflows/ci-cd-main.yml
Normal file
51
.forgejo/workflows/ci-cd-main.yml
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
name: Production CI/CD Pipeline
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: npm run test
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Upload Build Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: dist
|
||||||
|
path: dist/
|
||||||
|
|
||||||
|
deploy-prod:
|
||||||
|
needs: build-and-test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment:
|
||||||
|
name: production
|
||||||
|
steps:
|
||||||
|
- name: Download Build Artifact
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: dist
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
- name: Deploy to Production via FTP
|
||||||
|
env:
|
||||||
|
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
|
||||||
|
FTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
|
||||||
|
FTP_HOST: ${{ secrets.FTP_HOST }}
|
||||||
|
run: |
|
||||||
|
lftp -d -u "$FTP_USERNAME","$FTP_PASSWORD" -e "set ssl:verify-certificate no; set ftp:ssl-allow yes; set ftp:ssl-force true; set ftp:ssl-protect-data true; set ftp:passive-mode true; mirror -R dist/ ./; quit" $FTP_HOST
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
when:
|
|
||||||
- event: [push, pull_request, deployment]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: install
|
|
||||||
image: node:20-alpine
|
|
||||||
commands:
|
|
||||||
- npm ci
|
|
||||||
|
|
||||||
- name: lint
|
|
||||||
image: node:20-alpine
|
|
||||||
commands:
|
|
||||||
- npm run lint
|
|
||||||
|
|
||||||
- name: test
|
|
||||||
image: node:20-alpine
|
|
||||||
commands:
|
|
||||||
- npm run test
|
|
||||||
|
|
||||||
- name: build
|
|
||||||
image: node:20-alpine
|
|
||||||
commands:
|
|
||||||
- npm run build
|
|
||||||
|
|
||||||
- name: deploy-prod
|
|
||||||
image: alpine:3.18
|
|
||||||
environment:
|
|
||||||
FTP_USERNAME:
|
|
||||||
from_secret: ftp_username
|
|
||||||
FTP_PASSWORD:
|
|
||||||
from_secret: ftp_password
|
|
||||||
FTP_HOST:
|
|
||||||
from_secret: ftp_host
|
|
||||||
commands:
|
|
||||||
- apk add --no-cache lftp
|
|
||||||
- lftp -d -u "$FTP_USERNAME","$FTP_PASSWORD" -e "set ssl:verify-certificate no; set ftp:ssl-allow yes; set ftp:ssl-force true; set ftp:ssl-protect-data true; set ftp:passive-mode true; mirror -R dist/ ./; quit" $FTP_HOST
|
|
||||||
when:
|
|
||||||
- branch: main
|
|
||||||
event: push
|
|
||||||
- event: deployment
|
|
||||||
environment: production
|
|
||||||
|
|
||||||
- name: deploy-beta
|
|
||||||
image: alpine:3.18
|
|
||||||
environment:
|
|
||||||
FTP_USERNAME:
|
|
||||||
from_secret: beta_ftp_username
|
|
||||||
FTP_PASSWORD:
|
|
||||||
from_secret: beta_ftp_password
|
|
||||||
FTP_HOST:
|
|
||||||
from_secret: ftp_host
|
|
||||||
commands:
|
|
||||||
- apk add --no-cache lftp
|
|
||||||
- lftp -d -u "$FTP_USERNAME","$FTP_PASSWORD" -e "set ssl:verify-certificate no; set ftp:ssl-allow yes; set ftp:ssl-force true; set ftp:ssl-protect-data true; set ftp:passive-mode true; mirror -R dist/ ./; quit" $FTP_HOST
|
|
||||||
when:
|
|
||||||
- branch: beta
|
|
||||||
event: push
|
|
||||||
- event: deployment
|
|
||||||
environment: beta
|
|
||||||
108
architecture_diagram.md
Normal file
108
architecture_diagram.md
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
# Supplier Portal Architecture & Module Design
|
||||||
|
|
||||||
|
This document outlines the proposed module structure, page flows, and visual architecture for the E-Commerce Supplier Portal.
|
||||||
|
|
||||||
|
## 1. System Architecture & Modules
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
%% Styling
|
||||||
|
classDef primary fill:#1A2B45,stroke:#1A2B45,color:#fff;
|
||||||
|
classDef accent fill:#E9C46A,stroke:#E9C46A,color:#1A2B45;
|
||||||
|
classDef container fill:#FFFFFF,stroke:#1A2B45,color:#1A2B45;
|
||||||
|
classDef bg fill:#F5F0EA,stroke:#1A2B45,color:#1A2B45;
|
||||||
|
|
||||||
|
%% Modules
|
||||||
|
AuthModule["Authentication Module"]:::primary
|
||||||
|
ProfileModule["Onboarding & Profile Module"]:::primary
|
||||||
|
ProductModule["Product Management"]:::primary
|
||||||
|
DashboardModule["Analytics & Dashboard"]:::primary
|
||||||
|
FulfillmentModule["Order & Fulfillment Tracking"]:::primary
|
||||||
|
WalletModule["Payout & Wallet"]:::primary
|
||||||
|
NotificationModule["Notification System"]:::primary
|
||||||
|
|
||||||
|
%% Components
|
||||||
|
Signup["Signup Page<br/>(Email, Phone, GSTIN Init)"]:::container
|
||||||
|
Login["Login Page<br/>(OTP / Password)"]:::container
|
||||||
|
ProfileComplete["Profile Completion Page<br/>(Store Info, Pickup Address, GSTIN Verify)"]:::container
|
||||||
|
ProdUpload["Single Upload / Modify Page"]:::container
|
||||||
|
BulkUpload["Bulk Excel/CSV Upload Page"]:::container
|
||||||
|
AnalyticsDash["Sales & Earnings Analytics<br/>(Yearly, Weekly, Daily, Custom Date Filters)"]:::container
|
||||||
|
StockReports["Stock & Inventory Tracking"]:::container
|
||||||
|
ReturnsDashboard["Customer Returns Center<br/>(Requests, Tracking & Quality Checks)"]:::container
|
||||||
|
PayoutCenter["Payout / Wallet Dashboard<br/>(Outstanding Balance, Withdrawal Request)"]:::container
|
||||||
|
ItemTracking["Item Tracking Dashboard<br/>(Individual Item Status, SKUs, Serials)"]:::container
|
||||||
|
TransitTracking["Transit Tracking Dashboard<br/>(Courier Status, Carrier Integration)"]:::container
|
||||||
|
|
||||||
|
%% Relations
|
||||||
|
AuthModule --> Signup
|
||||||
|
AuthModule --> Login
|
||||||
|
Signup --> ProfileComplete
|
||||||
|
ProfileComplete --> ProfileModule
|
||||||
|
|
||||||
|
ProductModule --> ProdUpload
|
||||||
|
ProductModule --> BulkUpload
|
||||||
|
|
||||||
|
DashboardModule --> AnalyticsDash
|
||||||
|
DashboardModule --> StockReports
|
||||||
|
|
||||||
|
FulfillmentModule --> ItemTracking
|
||||||
|
FulfillmentModule --> TransitTracking
|
||||||
|
FulfillmentModule --> ReturnsDashboard
|
||||||
|
|
||||||
|
WalletModule --> PayoutCenter
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Detailed Page & Module Breakdown
|
||||||
|
|
||||||
|
### A. Authentication & Onboarding Module
|
||||||
|
1. **Signup Page**
|
||||||
|
- Business Email, Password, and Mobile Number validation.
|
||||||
|
- Initial GSTIN input (for verification).
|
||||||
|
2. **Login Page**
|
||||||
|
- Credentials or OTP-based secure login.
|
||||||
|
3. **Account Profile Completion Page (Onboarding Step 2)**
|
||||||
|
- **Store Details**: Upload Store Logo/Profile Image, Store Display Name.
|
||||||
|
- **Pickup & Shipping**: Pickup Address, contact person details.
|
||||||
|
- **Regulatory Info**: Verified GSTIN, Bank Account details (for payouts).
|
||||||
|
|
||||||
|
### B. Product & Inventory Management Module
|
||||||
|
1. **Single Product Upload & Modification**
|
||||||
|
- Form-based creation (Images, Title, Description, SKU, Category, Price, Stock count).
|
||||||
|
- Real-time preview of the product card matching our theme.
|
||||||
|
2. **Bulk Product Upload & Modify**
|
||||||
|
- Excel/CSV upload template download.
|
||||||
|
- Status log showing validation warnings (e.g., missing images, pricing errors).
|
||||||
|
|
||||||
|
### C. Analytical Dashboard Module
|
||||||
|
Provides comprehensive reporting with dynamic period filters (**Yearly, Weekly, Daily, and Custom Date Range**):
|
||||||
|
1. **Sales & Earnings Reports**
|
||||||
|
- Interactive charts showing Total Sales (Gross volume) vs. Total Earned (Net margin after commissions).
|
||||||
|
2. **Stock & Inventory Status**
|
||||||
|
- Low-stock alerts, active listings count, and inactive listings.
|
||||||
|
|
||||||
|
### D. Order & Fulfillment Tracking Module
|
||||||
|
1. **Item Tracking**
|
||||||
|
- Track individual items per order (SKU details, quantity, individual packaging status).
|
||||||
|
- Flag items: *Ready to Ship*, *Shipped*, *Delivered*, *Cancelled*.
|
||||||
|
2. **Transit Tracking**
|
||||||
|
- Real-time logistic carrier updates (e.g., DHL, FedEx, Local Post tracking number integration).
|
||||||
|
- Expected Delivery Date and transit milestones display.
|
||||||
|
3. **Return Tracking & Return Requests**
|
||||||
|
- **Items Requested for Return**: Lists customer return requests, reason for return, and custom images uploaded by the customer (e.g., defective product, wrong size). Action to *Approve* or *Reject* return.
|
||||||
|
- **In-Transit Return Tracking**: Real-time logistic progress of returning items from the customer back to the supplier hub.
|
||||||
|
|
||||||
|
### E. Wallet & Financials (Payout) Module
|
||||||
|
1. **Current Outstanding Balance**
|
||||||
|
- Live ready-to-withdraw funds display.
|
||||||
|
2. **Withdrawal Interface**
|
||||||
|
- Payout history list with status tracking (Pending, Approved, Transferred).
|
||||||
|
- "Withdraw Funds" action trigger.
|
||||||
|
|
||||||
|
### F. Notifications & Account Settings
|
||||||
|
1. **Header Notification Drawer**
|
||||||
|
- Real-time notices for new orders, low inventory, return requests, and completed payouts.
|
||||||
|
2. **Profile / Account Settings Page**
|
||||||
|
- Modify existing Store Profile Image, Pickup Location details, and GSTIN certificates.
|
||||||
86
guide.md
Normal file
86
guide.md
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
# Supplier Portal - View & Navigation Guide
|
||||||
|
|
||||||
|
This guide explains how to start the development server, navigate the screens, and view the onboarding flows and simulated dashboard preview.
|
||||||
|
|
||||||
|
## 1. Running the Portal Locally
|
||||||
|
|
||||||
|
To start the Vite development server, run the following command in the project root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, the server runs at **[http://localhost:5173/](http://localhost:5173/)** (or the port specified in your console).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Page Routing & State Mapping
|
||||||
|
|
||||||
|
The portal uses a client-side state router mapping component views to logical routes:
|
||||||
|
|
||||||
|
| Route State | Component/View Description | Navigable Via |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `home` | **Landing Page**: Brand value proposition, hero banner, primary action CTAs. | Logo click, "Platform" header link. |
|
||||||
|
| `about` | **About Us**: Organization mission details and team profiles. | "Success Stories" header link. |
|
||||||
|
| `contact` | **Contact Support**: "Get in Touch" inquiry form and help desk coordinates. | "Support" header link. |
|
||||||
|
| `login` | **Supplier Login**: Account login via password credentials or OTP mock. | "Login" header button. |
|
||||||
|
| `signup` | **Supplier Registration**: Fields for business email, password, and GSTIN. | "Get Started" header button. |
|
||||||
|
| `profile-completion` | **Profile Wizard (Step 2)**: Logo picker, bio, and interactive GSTIN validation. | Auto-redirect on Signup form submit. |
|
||||||
|
| `confirmation` | **Dashboard Preview (Step 3)**: Payout status notifications and mock graphs. | Auto-redirect on Profile Completion save. |
|
||||||
|
| `dashboard` | **Seller Dashboard & Tools**: Overview performance metrics, single/bulk product uploads, orders tracking log, returns approvals, wallet payouts, and settings configuration. | Click "Go to Dashboard" button in confirmation, or submit Login form. |
|
||||||
|
|
||||||
|
--- te
|
||||||
|
|
||||||
|
## 3. Navigating the Phase 1 Onboarding Flow )
|
||||||
|
|
||||||
|
You can step through the interactive onboarding flow sequentially to experience the full walkthrough:
|
||||||
|
|
||||||
|
### Step A: The Landing Page
|
||||||
|
- Open the application. You will see the **Global Artisans Hub** landing page with the primary theme (Deep Navy Blue headers/footers, Amber Gold accents, and Warm Cream backgrounds).
|
||||||
|
- Click **Platform**, **Success Stories** (About Us), or **Support** (Contact Us) in the header navigation to view the respective information layouts.
|
||||||
|
|
||||||
|
### Step B: Account Registration
|
||||||
|
1. Click **Get Started** in the header.
|
||||||
|
2. The view will switch to the **Register** tab.
|
||||||
|
3. Fill in the required fields:
|
||||||
|
- **Business Email**
|
||||||
|
- **Mobile Number**
|
||||||
|
- **Create Password**
|
||||||
|
- **GSTIN / Tax ID**
|
||||||
|
4. Click **Register Business**.
|
||||||
|
|
||||||
|
### Step C: Profile Completion (Step 2 of 3)
|
||||||
|
1. You will be taken to the **Complete Your Supplier Profile** wizard.
|
||||||
|
2. Enter a **Store Display Name**.
|
||||||
|
3. (Optional) Choose an image file to upload. It will immediately show an avatar logo preview.
|
||||||
|
4. Enter an **About Your Craft / Business** description.
|
||||||
|
5. Fill in the **Business Address for Pickup** fields (Street Address, City, State, Pincode).
|
||||||
|
6. Enter a GSTIN, and click **Verify GSTIN**. The button will show a loading spinner, then update to **Verified ✓** status.
|
||||||
|
7. Click **Save & Continue**.
|
||||||
|
|
||||||
|
### Step D: Onboarding Confirmation (Step 3 of 3)
|
||||||
|
- You will arrive at the **Welcome to Global Artisans Hub!** confirmation view.
|
||||||
|
- Click **Go to Dashboard (Preview Only)** to go to the live seller portal dashboard page.
|
||||||
|
- Alternatively, you can directly access the dashboard page by going to **Login** -> enter credentials -> click **Secure Login**.
|
||||||
|
|
||||||
|
### Step E: Navigating the Seller Dashboard & Tools
|
||||||
|
Once inside the active dashboard (`/dashboard`), use the left sidebar menu to navigate the tools:
|
||||||
|
1. **Overview & Analytics**: View Sales, net margins, stock, and returns. Toggle the date filters (Year, Week, Day, Custom Date) to see the metrics update dynamically.
|
||||||
|
2. **Manage Products**:
|
||||||
|
- View your active inventory listing.
|
||||||
|
- Fill out the **Upload Product** form on the right to add a product or click **Edit** on a row to modify it.
|
||||||
|
- Click the bulk upload zone to simulate importing products via CSV files.
|
||||||
|
3. **Orders & Transit**: Track active orders, status (Ready to Ship, Shipped, Delivered), carriers, and tracking coordinates.
|
||||||
|
4. **Returns Management**: View buyer return requests. Click **Approve** or **Reject** to update their logistics status in the warehouse transit log.
|
||||||
|
5. **Wallet & Payouts**: Enter an amount to process a withdrawal from your outstanding ready balance.
|
||||||
|
6. **Store Settings**: Update your store name, logo file, bio, and pickup coordinates.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Run Automated Component Tests
|
||||||
|
|
||||||
|
To run the Vitest unit tests verifying these navigation flows and tools, execute:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run test
|
||||||
|
```
|
||||||
1198
package-lock.json
generated
1198
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -7,7 +7,7 @@
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "oxlint",
|
"lint": "oxlint",
|
||||||
"test": "echo 'No tests specified' && exit 0",
|
"test": "vitest run",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -15,12 +15,17 @@
|
||||||
"react-dom": "^19.2.8"
|
"react-dom": "^19.2.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@testing-library/dom": "^10.4.1",
|
||||||
|
"@testing-library/jest-dom": "^7.0.0",
|
||||||
|
"@testing-library/react": "^16.3.2",
|
||||||
"@types/node": "^24.13.3",
|
"@types/node": "^24.13.3",
|
||||||
"@types/react": "^19.2.17",
|
"@types/react": "^19.2.17",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@vitejs/plugin-react": "^6.0.4",
|
"@vitejs/plugin-react": "^6.0.4",
|
||||||
|
"jsdom": "^30.0.1",
|
||||||
"oxlint": "^1.75.0",
|
"oxlint": "^1.75.0",
|
||||||
"typescript": "~6.0.2",
|
"typescript": "~6.0.2",
|
||||||
"vite": "^8.2.0"
|
"vite": "^8.2.0",
|
||||||
|
"vitest": "^4.1.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
133
src/App.test.tsx
Normal file
133
src/App.test.tsx
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
import { render, screen, fireEvent } from '@testing-library/react'
|
||||||
|
import { describe, it, expect, vi, beforeAll } from 'vitest'
|
||||||
|
import App from './App'
|
||||||
|
|
||||||
|
// Mock window.scrollTo since jsdom does not implement it
|
||||||
|
beforeAll(() => {
|
||||||
|
window.scrollTo = vi.fn()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Supplier Portal Onboarding & Active Dashboard Tests', () => {
|
||||||
|
it('renders landing page with correct primary titles', () => {
|
||||||
|
render(<App />)
|
||||||
|
|
||||||
|
expect(screen.getByText(/Sell Globally\./i)).toBeInTheDocument()
|
||||||
|
expect(screen.getByText(/Celebrate Craft\./i)).toBeInTheDocument()
|
||||||
|
|
||||||
|
expect(screen.getByRole('heading', { name: /^Expand Your Reach$/i })).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('navigates to Support page and handles contact form submission', () => {
|
||||||
|
render(<App />)
|
||||||
|
|
||||||
|
const supportBtn = screen.getByText('Support')
|
||||||
|
fireEvent.click(supportBtn)
|
||||||
|
|
||||||
|
const nameInput = screen.getByLabelText(/Full Name \*/i)
|
||||||
|
const emailInput = screen.getByLabelText(/Email Address \*/i)
|
||||||
|
const msgInput = screen.getByLabelText(/Message \*/i)
|
||||||
|
|
||||||
|
fireEvent.change(nameInput, { target: { value: 'John Doe' } })
|
||||||
|
fireEvent.change(emailInput, { target: { value: 'john@example.com' } })
|
||||||
|
fireEvent.change(msgInput, { target: { value: 'Hello support!' } })
|
||||||
|
|
||||||
|
const alertMock = vi.spyOn(window, 'alert').mockImplementation(() => {})
|
||||||
|
|
||||||
|
const submitBtn = screen.getByText('Submit Inquiry')
|
||||||
|
fireEvent.click(submitBtn)
|
||||||
|
|
||||||
|
expect(alertMock).toHaveBeenCalled()
|
||||||
|
alertMock.mockRestore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('signs up successfully and completes profile to active dashboard', async () => {
|
||||||
|
render(<App />)
|
||||||
|
|
||||||
|
const getStartedBtn = screen.getByRole('button', { name: /^Get Started$/i })
|
||||||
|
fireEvent.click(getStartedBtn)
|
||||||
|
|
||||||
|
const emailInput = screen.getByLabelText(/Business Email \*/i)
|
||||||
|
const phoneInput = screen.getByLabelText(/Mobile Number \*/i)
|
||||||
|
const passInput = screen.getByLabelText(/Create Password \*/i)
|
||||||
|
const taxInput = screen.getByLabelText(/GSTIN \/ Tax ID \*/i)
|
||||||
|
|
||||||
|
fireEvent.change(emailInput, { target: { value: 'seller@example.com' } })
|
||||||
|
fireEvent.change(phoneInput, { target: { value: '9876543210' } })
|
||||||
|
fireEvent.change(passInput, { target: { value: 'password123' } })
|
||||||
|
fireEvent.change(taxInput, { target: { value: '29AAAAA1111A1Z1' } })
|
||||||
|
|
||||||
|
const registerBtn = screen.getByRole('button', { name: /Register Business/i })
|
||||||
|
fireEvent.click(registerBtn)
|
||||||
|
|
||||||
|
expect(screen.getByText('Step 2 of 3: Business Details')).toBeInTheDocument()
|
||||||
|
|
||||||
|
const storeNameInput = screen.getByLabelText(/Store Display Name \*/i)
|
||||||
|
fireEvent.change(storeNameInput, { target: { value: 'Crafty Store' } })
|
||||||
|
|
||||||
|
const bioText = screen.getByLabelText(/About Your Craft \/ Business \*/i)
|
||||||
|
fireEvent.change(bioText, { target: { value: 'Handmade pottery.' } })
|
||||||
|
|
||||||
|
const streetInput = screen.getByPlaceholderText('Street Address')
|
||||||
|
const cityInput = screen.getByPlaceholderText('City')
|
||||||
|
const stateInput = screen.getByPlaceholderText('State')
|
||||||
|
const pincodeInput = screen.getByPlaceholderText('Pincode')
|
||||||
|
|
||||||
|
fireEvent.change(streetInput, { target: { value: '123 Loom Lane' } })
|
||||||
|
fireEvent.change(cityInput, { target: { value: 'Handloom City' } })
|
||||||
|
fireEvent.change(stateInput, { target: { value: 'Karnataka' } })
|
||||||
|
fireEvent.change(pincodeInput, { target: { value: '560001' } })
|
||||||
|
|
||||||
|
const saveBtn = screen.getByRole('button', { name: /Save & Continue/i })
|
||||||
|
fireEvent.click(saveBtn)
|
||||||
|
|
||||||
|
// Redirects directly to Dashboard Page
|
||||||
|
expect(screen.getByText('Performance Analytics')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText(/Total Sales Volume/i)).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('logs in successfully and navigates dashboard tools', () => {
|
||||||
|
render(<App />)
|
||||||
|
|
||||||
|
const loginBtn = screen.getByRole('button', { name: /^Login$/i })
|
||||||
|
fireEvent.click(loginBtn)
|
||||||
|
|
||||||
|
const emailInput = screen.getByLabelText(/Business Email/i)
|
||||||
|
const passInput = screen.getByLabelText(/Password/i)
|
||||||
|
|
||||||
|
fireEvent.change(emailInput, { target: { value: 'seller@example.com' } })
|
||||||
|
fireEvent.change(passInput, { target: { value: 'password123' } })
|
||||||
|
|
||||||
|
const submitBtn = screen.getByRole('button', { name: /Secure Login/i })
|
||||||
|
fireEvent.click(submitBtn)
|
||||||
|
|
||||||
|
// Check dashboard rendering
|
||||||
|
expect(screen.getByText('Performance Analytics')).toBeInTheDocument()
|
||||||
|
|
||||||
|
// Check Sidebar Tab click: Manage Products
|
||||||
|
const productsTabBtn = screen.getByText(/Manage Products/i)
|
||||||
|
fireEvent.click(productsTabBtn)
|
||||||
|
|
||||||
|
expect(screen.getByText(/Active Inventory/i)).toBeInTheDocument()
|
||||||
|
expect(screen.getByText(/Upload New Product/i)).toBeInTheDocument()
|
||||||
|
|
||||||
|
// Check Sidebar Tab click: Orders & Transit
|
||||||
|
const ordersTabBtn = screen.getByText(/Orders & Transit/i)
|
||||||
|
fireEvent.click(ordersTabBtn)
|
||||||
|
|
||||||
|
expect(screen.getByText(/Active Orders & Payout status/i)).toBeInTheDocument()
|
||||||
|
|
||||||
|
// Check Sidebar Tab click: Returns Management
|
||||||
|
const returnsTabBtn = screen.getByText(/Returns Management/i)
|
||||||
|
fireEvent.click(returnsTabBtn)
|
||||||
|
|
||||||
|
expect(screen.getByText(/Returns & Quality Assurance Center/i)).toBeInTheDocument()
|
||||||
|
expect(screen.getByText(/Items Requested for Return/i)).toBeInTheDocument()
|
||||||
|
|
||||||
|
// Check Sidebar Tab click: Wallet & Payouts
|
||||||
|
const walletTabBtn = screen.getByText(/Wallet & Payouts/i)
|
||||||
|
fireEvent.click(walletTabBtn)
|
||||||
|
|
||||||
|
expect(screen.getByText(/Wallet & Payout Portal/i)).toBeInTheDocument()
|
||||||
|
expect(screen.getByText(/Outstanding Ready Balance/i)).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
1449
src/App.tsx
1449
src/App.tsx
File diff suppressed because it is too large
Load diff
116
src/config.ts
Normal file
116
src/config.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
export const CONFIG = {
|
||||||
|
companyName: 'Global Artisans Hub',
|
||||||
|
logoLetter: 'A',
|
||||||
|
supportEmail: 'support@globalartisanshub.com',
|
||||||
|
supportPhone: '+1 (800) 555-0199',
|
||||||
|
address: '1775 Artisan Ridge Rd, Craftsville, CA 90210',
|
||||||
|
|
||||||
|
hero: {
|
||||||
|
title: 'Sell Globally. Celebrate Craft.',
|
||||||
|
subtitle: 'Join the premier marketplace for artisans and reach millions of conscious customers worldwide.',
|
||||||
|
image: 'https://images.unsplash.com/photo-1513519245088-0e12902e5a38?auto=format&fit=crop&q=80&w=800'
|
||||||
|
},
|
||||||
|
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
icon: '🌍',
|
||||||
|
title: 'Expand Your Reach',
|
||||||
|
description: 'Globalize your marketplace for artisans and reach millions of conscious customers.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: '🛠️',
|
||||||
|
title: 'Easy Inventory Tools',
|
||||||
|
description: 'Dashboard marketplace to manage and update listings with ease.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: '🛡️',
|
||||||
|
title: 'Secure Payments',
|
||||||
|
description: 'Secure payments and reliable payout processing directly to your bank account.'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
featuredArtisan: {
|
||||||
|
name: 'Naomi K.',
|
||||||
|
role: 'Master Weaver',
|
||||||
|
quote: '"Joining the Global Artisans Hub has transformed our community. We went from selling at local weekend fairs to serving buyers worldwide, preserving our traditional craft."',
|
||||||
|
avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?auto=format&fit=crop&q=80&w=300'
|
||||||
|
},
|
||||||
|
|
||||||
|
about: {
|
||||||
|
missionTitle: 'Our Mission',
|
||||||
|
missionDescription: 'We aim to empower artisan communities worldwide, providing a premium, transparent, and direct channel to conscious consumers globally.',
|
||||||
|
team: [
|
||||||
|
{
|
||||||
|
name: 'Sunder R.',
|
||||||
|
role: 'Founder & CEO',
|
||||||
|
avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?auto=format&fit=crop&q=80&w=150'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Sarayu N.',
|
||||||
|
role: 'Head of Artisan Partnerships',
|
||||||
|
avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=crop&q=80&w=150'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'John C.',
|
||||||
|
role: 'Operations Lead',
|
||||||
|
avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&q=80&w=150'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Elena P.',
|
||||||
|
role: 'Tech Lead',
|
||||||
|
avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?auto=format&fit=crop&q=80&w=150'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
// --- Mock Dashboard Data ---
|
||||||
|
dashboardData: {
|
||||||
|
filters: {
|
||||||
|
year: {
|
||||||
|
totalSales: 45280.00,
|
||||||
|
totalEarned: 38488.00,
|
||||||
|
stockDetails: 342,
|
||||||
|
returnedItems: 12,
|
||||||
|
chartValues: [30, 45, 35, 60, 75, 55, 80, 65, 90, 70, 85, 95] // Monthly values
|
||||||
|
},
|
||||||
|
week: {
|
||||||
|
totalSales: 1240.00,
|
||||||
|
totalEarned: 1054.00,
|
||||||
|
stockDetails: 342,
|
||||||
|
returnedItems: 1,
|
||||||
|
chartValues: [40, 60, 50, 70, 45, 80, 90] // Daily values
|
||||||
|
},
|
||||||
|
day: {
|
||||||
|
totalSales: 210.00,
|
||||||
|
totalEarned: 178.50,
|
||||||
|
stockDetails: 342,
|
||||||
|
returnedItems: 0,
|
||||||
|
chartValues: [10, 15, 20, 25, 35, 45, 30, 20, 10] // Hourly intervals
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
totalSales: 5820.00,
|
||||||
|
totalEarned: 4947.00,
|
||||||
|
stockDetails: 342,
|
||||||
|
returnedItems: 3,
|
||||||
|
chartValues: [50, 40, 65, 55, 75, 85, 60, 70] // Range intervals
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialProducts: [
|
||||||
|
{ id: '1', title: 'Handwoven Indigo Shawl', category: 'Apparel', price: 85.00, stock: 45, sku: 'SHAWL-IND-01', image: 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?auto=format&fit=crop&q=80&w=100' },
|
||||||
|
{ id: '2', title: 'Terracotta Clay Pot Set', category: 'Home Decor', price: 42.00, stock: 24, sku: 'POT-TER-02', image: 'https://images.unsplash.com/photo-1612196808214-b8e1d6145a8c?auto=format&fit=crop&q=80&w=100' },
|
||||||
|
{ id: '3', title: 'Brass Elephant Figurine', category: 'Sculptures', price: 120.00, stock: 12, sku: 'FIG-ELE-03', image: 'https://images.unsplash.com/photo-1590736969955-71cc94801759?auto=format&fit=crop&q=80&w=100' }
|
||||||
|
],
|
||||||
|
|
||||||
|
initialOrders: [
|
||||||
|
{ id: 'ORD-8492', date: '2026-08-07', item: 'Handwoven Indigo Shawl', quantity: 1, customer: 'Alice Vance', total: 85.00, status: 'Ready to Ship', carrier: 'DHL Express', tracking: 'DHL-9284102', eta: '2026-08-10' },
|
||||||
|
{ id: 'ORD-8488', date: '2026-08-06', item: 'Terracotta Clay Pot Set', quantity: 2, customer: 'David Miller', total: 84.00, status: 'Shipped', carrier: 'FedEx Ground', tracking: 'FDX-5829104', eta: '2026-08-09' },
|
||||||
|
{ id: 'ORD-8471', date: '2026-08-05', item: 'Brass Elephant Figurine', quantity: 1, customer: 'Sarah Connor', total: 120.00, status: 'Delivered', carrier: 'Local Express', tracking: 'LOC-1294801', eta: '2026-08-07' }
|
||||||
|
],
|
||||||
|
|
||||||
|
initialReturns: [
|
||||||
|
{ id: 'RET-019', orderId: 'ORD-8411', customer: 'Lillian G.', item: 'Handwoven Indigo Shawl', reason: 'Slightly different shade than pictured', status: 'Pending Approval', image: 'https://images.unsplash.com/photo-1544022613-e87ca75a784a?auto=format&fit=crop&q=80&w=100', returningTracking: 'DHL-RET-9031' },
|
||||||
|
{ id: 'RET-018', orderId: 'ORD-8390', customer: 'Robert H.', item: 'Terracotta Clay Pot Set', reason: 'Damaged in transit', status: 'In Transit', image: 'https://images.unsplash.com/photo-1612196808214-b8e1d6145a8c?auto=format&fit=crop&q=80&w=100', returningTracking: 'FDX-RET-2940' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
1114
src/index.css
1114
src/index.css
File diff suppressed because it is too large
Load diff
1
src/setupTests.ts
Normal file
1
src/setupTests.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
import '@testing-library/jest-dom'
|
||||||
13
vitest.config.ts
Normal file
13
vitest.config.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { defineConfig, mergeConfig } from 'vitest/config'
|
||||||
|
import viteConfig from './vite.config.ts'
|
||||||
|
|
||||||
|
export default mergeConfig(
|
||||||
|
viteConfig,
|
||||||
|
defineConfig({
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: './src/setupTests.ts',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
Loading…
Reference in a new issue