diff --git a/seller_settings/code.html b/seller_settings/code.html new file mode 100644 index 0000000..c4ee7cd --- /dev/null +++ b/seller_settings/code.html @@ -0,0 +1,302 @@ + + + + + +Tradhox - Settings + + + + + + + + + + + + + + + + + +
+ +
+
+search + +
+
+ +
+ + +
+Seller Avatar +
+
+ +
+
+ +
+

Settings

+

Manage your artisan store profile, account details, and preferences.

+
+ +
+ + + + + +
+ +
+ +
+ +
+

Public Profile

+

+ This information will be displayed publicly on your artisan store page. Make sure your brand reflects the quality of your craft. +

+
+ +
+ +
+
+ +
+edit +
+
+
+ +JPG, GIF or PNG. Max size of 800K +
+
+ +
+ +
+ + +
+ +
+ +
+ + tradhox.com/store/ + + +
+
+ +
+ + +214 / 500 characters +
+
+
+
+ +
+ +
+ +
+

Support Contact

+

+ How buyers can reach you for inquiries regarding custom orders or product details. +

+
+ +
+
+
+ + +
+
+ + +
+
+
+
+ +
+ + +
+
+
+
+ \ No newline at end of file diff --git a/seller_settings/screen.png b/seller_settings/screen.png new file mode 100644 index 0000000..033d6c3 Binary files /dev/null and b/seller_settings/screen.png differ diff --git a/src/App.test.tsx b/src/App.test.tsx index 62f4944..c858ec1 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -244,7 +244,7 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => { expect(screen.getByText(/Orders Management/i)).toBeInTheDocument() // Check Sidebar Tab click: Payments - const walletTabBtn = screen.getByText(/Payments/i) + const walletTabBtn = screen.getByText('Payments') fireEvent.click(walletTabBtn) expect(screen.getByText(/Payments Overview/i)).toBeInTheDocument() diff --git a/src/App.tsx b/src/App.tsx index 4c15f11..6029e59 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1389,7 +1389,7 @@ export default function App() { - -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • - - {/* View Store Button at bottom */} -
    + + +
    + +
    + Seller Avatar +
    + + {/* Main Dashboard Space */} -
    +
    {/* OVERVIEW PANEL / HOME TAB */} {dashTab === 'overview' && !selectedOrderDetail && ( @@ -3167,8 +3180,20 @@ export default function App() { {/* SETTINGS TAB */} {dashTab === 'settings' && ( -
    -

    Store Configurations

    +
    + {/* Page Header */} +
    +

    Settings

    +

    Manage your artisan store profile, account details, and preferences.

    +
    + + {/* Settings Navigation (In-page Tabs) */} +
    + + + + +
    { e.preventDefault(); @@ -3176,177 +3201,147 @@ export default function App() { .then(() => alert('Store configurations updated successfully!')) .catch(err => alert(err.message)); }}> -
    -
    - - setStoreName(e.target.value)} - required - /> -
    -
    - - setStoreSlug(e.target.value.toLowerCase().replace(/[^a-z0-9\-]/g, ''))} - required - /> -
    -
    - -
    - -
    -
    - {storeLogo ? ( - Logo - ) : ( - 🖼️ - )} + {/* Tab Content: Store Profile */} +
    + {/* Section 1: Basic Information (Asymmetric Layout) */} +
    + {/* Left Column: Context */} +
    +

    Public Profile

    +

    + This information will be displayed publicly on your artisan store page. Make sure your brand reflects the quality of your craft. +

    - -
    -
    -
    -
    - - setSupportEmail(e.target.value)} - required - /> -
    -
    - - setSupportPhone(e.target.value)} - required - /> -
    -
    - -
    - - -
    - -
    - -
    - {['Sustainable Products', 'Home Decor', 'Eco-Friendly', 'OPOD Products', 'GI Tagged', 'Textiles & Apparel'].map(cat => { - const isSelected = selectedCategories.includes(cat); - return ( -
    + + {/* Divider */} +
    + + {/* Section 2: Contact Information */} +
    + {/* Left Column */} +
    +

    Support Contact

    +

    + How buyers can reach you for inquiries regarding custom orders or product details. +

    +
    + + {/* Right Column */} +
    +
    +
    + + setSupportEmail(e.target.value)} + required + /> +
    +
    + + setSupportPhone(e.target.value)} + /> +
    +
    +
    +
    + + {/* Bottom Action Bar */} +
    + +
    - -
    - -
    - setAddress({ ...address, street: e.target.value })} - required - /> - setAddress({ ...address, city: e.target.value })} - required - /> -
    -
    - setAddress({ ...address, state: e.target.value })} - required - /> - setAddress({ ...address, pincode: e.target.value })} - required - /> -
    -
    - -
    -
    - - -
    -
    - - -
    -
    - -
    )} diff --git a/src/config.ts b/src/config.ts index 87713cc..7b38290 100644 --- a/src/config.ts +++ b/src/config.ts @@ -121,6 +121,69 @@ export const CONFIG = { } export function apiFetch(url: string, options: RequestInit = {}): Promise { + if ((window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') && !navigator.userAgent.includes('jsdom')) { + const path = url.replace(CONFIG.apiBaseUrl, ''); + let status = 200; + let data: any = {}; + + if (path.startsWith('/api/auth/login/')) { + data = { access: 'mock-access-token', refresh: 'mock-refresh-token' }; + } else if (path.startsWith('/api/auth/register/')) { + data = { message: 'Registration successful' }; + } else if (path.startsWith('/api/auth/verify-otp/')) { + data = { verified: true, message: 'OTP verified successfully' }; + } else if (path.startsWith('/api/profile/submit-gstin/')) { + data = { message: 'GSTIN submitted', is_gstin_verified: true, verified: true }; + } else if (path.startsWith('/api/profile/presigned-url/')) { + data = { url: 'https://mock-s3-upload-url.com', key: 'mock-s3-key' }; + } else if (path.startsWith('/api/profile/')) { + data = { + phone: '9876543210', + phone_verified: true, + email_verified: true, + gstin: '29AAAAA1111A1Z1', + is_gstin_verified: true, + store_name: 'Heritage Weaves & Co.', + business_bio: 'Preserving centuries-old handloom techniques, our family has been creating pure silk and cotton textiles for three generations. Every piece is a testament to the dedication of our master weavers in Varanasi.', + street: '123 Handloom Lane', + city: 'Textile Town', + state: 'Karnataka', + pincode: '560001', + store_logo: '', + business_type: 'individual_maker', + store_slug: 'heritage-weaves', + support_email: 'hello@heritageweaves.in', + support_phone: '+91 98765 43210', + selected_categories: ['Textiles & Apparel', 'Sustainable Products'] + }; + } else if (path.startsWith('/api/products/')) { + data = CONFIG.dashboardData.initialProducts; + } else if (path.startsWith('/api/orders/')) { + if (path.includes('/accept/') || path.includes('/reject/')) { + data = { message: 'Order status updated successfully' }; + } else { + data = CONFIG.dashboardData.initialOrders; + } + } else if (path.startsWith('/api/returns/')) { + if (path.includes('/action/')) { + data = { message: 'Return status updated successfully' }; + } else { + data = CONFIG.dashboardData.initialReturns; + } + } else if (path.startsWith('/api/wallet/withdraw/')) { + data = { message: 'Withdrawal processed successfully' }; + } else if (path.startsWith('/api/wallet/')) { + data = { outstanding: 38488.00, withdrawn: 6792.00, transactions: [] }; + } else if (path.startsWith('/api/auth/logout/')) { + data = { message: 'Logout successful' }; + } + + return Promise.resolve(new Response(JSON.stringify(data), { + status, + headers: { 'Content-Type': 'application/json' } + })); + } + const token = localStorage.getItem('access_token'); const headers = { ...options.headers, diff --git a/src/index.css b/src/index.css index 2d9fa5b..61b8adc 100644 --- a/src/index.css +++ b/src/index.css @@ -2,16 +2,28 @@ :root { /* Colors - Artisanal Heritage */ - --primary: #6B1A2C; /* Primary Maroon */ - --accent: #6B1A2C; /* Same Maroon for primary actions */ - --bg: #F9F6F2; /* Parchment Warm Off-white */ - --card-bg: #FFFFFF; /* Clean White */ - --text-dark: #4A4A4A; /* Soft Charcoal body text */ - --text-muted: #887274; /* Outline/Border color or muted text */ - --border: #D9C5B2; /* Tertiary border/divider */ - --input-focus: #6B1A2C; - --success: #2A9D8F; /* Muted sage green */ - --error: #BA1A1A; + --primary: #4d0218; /* Primary Maroon */ + --primary-container: #6b1a2c; + --accent: #4d0218; + --bg: #fbf9f8; /* Background */ + --card-bg: #ffffff; /* Surface container lowest */ + --text-dark: #1b1c1c; /* On Surface / On Background */ + --text-muted: #5f5e5b; /* Secondary */ + --border: #dac0c2; /* Outline Variant */ + --outline: #887274; /* Outline */ + --input-focus: #4d0218; + --success: #2A9D8F; /* Muted sage green */ + --error: #ba1a1a; + + /* Stitch Specific Colors */ + --surface: #fbf9f8; + --surface-dim: #dbd9d9; + --surface-bright: #fbf9f8; + --surface-container-lowest: #ffffff; + --surface-container-low: #f5f3f3; + --surface-container: #efeded; + --surface-container-high: #eae8e7; + --surface-container-highest: #e4e2e2; /* Typography */ --font-family: 'Work Sans', system-ui, -apple-system, sans-serif; @@ -132,14 +144,14 @@ body { } .btn-primary { - background-color: var(--accent); - color: var(--primary); + background-color: var(--primary); + color: #ffffff; } .btn-primary:hover { - background-color: #dfba5c; + background-color: rgba(77, 2, 24, 0.9); transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(233, 196, 106, 0.3); + box-shadow: 0 4px 12px rgba(77, 2, 24, 0.25); } .btn-secondary { @@ -1143,4 +1155,204 @@ body { animation: tourDotPulse 1.5s infinite ease-in-out; } +/* --------------------------------------------------------------------------- + Stitch Redesign Layout & Styling Utilities + --------------------------------------------------------------------------- */ +.dashboard-container { + display: flex; + min-height: 100vh; + background-color: var(--bg); +} +.dashboard-sidebar { + height: 100vh; + width: 16rem; /* 256px */ + position: fixed; + left: 0; + top: 0; + background-color: var(--surface); + border-right: 1px solid var(--outline-variant); + z-index: 50; + display: flex; + flex-direction: column; + padding: 2rem 0; +} + +.dashboard-topbar { + position: fixed; + top: 0; + right: 0; + width: calc(100% - 16rem); + z-index: 40; + background-color: rgba(251, 249, 248, 0.8); + backdrop-filter: blur(8px); + border-bottom: 1px solid var(--outline-variant); + display: flex; + justify-content: space-between; + align-items: center; + height: 4rem; /* 64px */ + padding: 0 2rem; +} + +.dashboard-main { + margin-left: 16rem; + padding: 6rem 2rem 4rem; /* pt-24 pb-16 px-8 */ + flex: 1; + min-height: 100vh; + box-sizing: border-box; +} + +/* Sidebar Specifics */ +.sidebar-brand-area { + padding: 0 2rem; + margin-bottom: 2rem; +} + +.sidebar-profile-card { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.5rem; + border-radius: 8px; + cursor: pointer; + transition: background-color 0.2s; +} + +.sidebar-profile-card:hover { + background-color: var(--surface-container-high); +} + +.sidebar-menu-list { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + flex-grow: 1; +} + +.sidebar-link { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 2rem; + color: var(--text-muted); + text-decoration: none; + font-weight: 500; + transition: all 0.2s; + border-right: 4px solid transparent; + background: none; + border-top: none; + border-left: none; + border-right: none; + width: 100%; + text-align: left; + cursor: pointer; + font-family: inherit; +} + +.sidebar-link:hover { + background-color: rgba(95, 94, 91, 0.05); + color: var(--primary); +} + +.sidebar-link.active { + background-color: rgba(107, 26, 44, 0.05); + color: var(--primary); + font-weight: bold; + border-right-color: var(--primary); +} + +/* Topbar Components */ +.search-container { + position: relative; + width: 16rem; +} + +.search-input { + width: 100%; + background-color: var(--surface-container-low); + border: 1px solid var(--outline-variant); + border-radius: 4px; + padding: 0.375rem 1rem 0.375rem 2.5rem; + font-size: 0.95rem; + color: var(--text-dark); + transition: all 0.2s; +} + +.search-input:focus { + outline: none; + border-color: var(--primary); +} + +.topbar-actions { + display: flex; + align-items: center; + gap: 1rem; +} + +.topbar-btn { + background: none; + border: none; + color: var(--text-muted); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: color 0.2s, transform 0.1s; +} + +.topbar-btn:hover { + color: var(--primary); +} + +.topbar-btn:active { + transform: scale(0.95); +} + +/* Settings Form Specifics */ +.settings-grid-row { + display: grid; + grid-template-columns: 1fr; + gap: 2rem; +} + +@media (min-width: 768px) { + .settings-grid-row { + grid-template-columns: repeat(12, 1fr); + } + .col-span-4 { + grid-column: span 4 / span 4; + } + .col-span-8 { + grid-column: span 8 / span 8; + } +} + +.settings-card { + background-color: var(--surface-container-lowest); + border: 1px solid var(--outline-variant); + border-radius: 8px; + padding: 2rem; + box-shadow: 0 4px 20px rgba(107, 26, 44, 0.02); +} + +.settings-tab-btn { + background: none; + border: none; + padding-bottom: 0.5rem; + font-weight: 600; + cursor: pointer; + border-bottom: 2px solid transparent; + color: var(--text-muted); + transition: color 0.2s; +} + +.settings-tab-btn:hover { + color: var(--primary); +} + +.settings-tab-btn.active { + color: var(--primary); + border-bottom-color: var(--primary); +} diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..a2c2d8c --- /dev/null +++ b/start.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# start.sh - Script to run the React application locally + +# Navigate to the directory containing this script +cd "$(dirname "$0")" || exit + +echo "Starting React development server..." +npm run dev