diff --git a/COMPONENTS_GUIDE.md b/COMPONENTS_GUIDE.md new file mode 100644 index 0000000..2269235 --- /dev/null +++ b/COMPONENTS_GUIDE.md @@ -0,0 +1,286 @@ +# โœ… Components Created - Quick Access Guide + +## ๐ŸŽจ Theme System + +**File:** `src/theme/index.ts` + +Complete theme configuration with: + +- โœ… Color palette (emerald/teal + gold) +- โœ… Typography system (display, h1-h4, body, buttons) +- โœ… Spacing (xs to massive) +- โœ… Border radius +- โœ… Icon sizes +- โœ… Shadow system +- โœ… Animation durations +- โœ… Breakpoints +- โœ… Z-index layers + +**Usage:** + +```typescript +import { theme, colors, typography, spacing } from "./theme"; +``` + +--- + +## ๐Ÿ—๏ธ Core Components Created + +### 1. Screen Component + +**File:** `src/components/Screen.tsx` + +Main wrapper for pages with: + +- Background image with 8px blur +- Dark overlay (rgba(4, 24, 21, 0.75)) +- Proper z-index layering +- Floating AI assistant button support + +**Usage:** + +```tsx + + {/* Your content */} + +``` + +--- + +### 2. StatCard Component + +**File:** `src/components/StatCard.tsx` + +Display metrics with trend indicators. + +**Usage:** + +```tsx +...} + label="Revenue" + value="โ‚น1.2M" + trend={{ value: "+18%", isPositive: true }} + iconColor="#4ADE80" +/> +``` + +--- + +### 3. QuickActionCard Component + +**File:** `src/components/QuickActionCard.tsx` + +Horizontal action card with icon and description. + +**Usage:** + +```tsx +...} + label="Send salary slips" + description="Monthly payroll ready" + iconColor="#CBA951" + badge={5} + onPress={() => console.log("Pressed")} +/> +``` + +--- + +### 4. SectionCard Component + +**File:** `src/components/SectionCard.tsx` + +Container for grouped content. + +**Usage:** + +```tsx + + {/* Your content */} + +``` + +--- + +### 5. SummaryCard Component + +**File:** `src/components/SummaryCard.tsx` + +List items with icons and count badges. + +**Usage:** + +```tsx +..., + label: "Pending approvals", + count: 5, + iconColor: "#FBBF24", + }, + ]} +/> +``` + +--- + +### 6. CompanySelector Component + +**File:** `src/components/CompanySelector.tsx` + +Company dropdown with modal. + +**Usage:** + +```tsx + console.log(id)} +/> +``` + +--- + +## ๐Ÿ“„ Pages Created + +### HomePage + +**File:** `src/pages/HomePage.tsx` +**Route:** `/dashboard` + +Complete Home Screen with: + +1. โœ… Greeting (time-based) +2. โœ… Company Selector +3. โœ… Decorative Divider +4. โœ… Quick Stats (horizontal scroll) +5. โœ… AI Insights Summary +6. โœ… Suggested Actions + +--- + +## ๐Ÿš€ How to View + +### Option 1: Direct URL + +1. Start your dev server: `npm run dev` +2. Navigate to: `http://localhost:5173/dashboard` + +### Option 2: From Login Page + +1. Go to: `http://localhost:5173/login` +2. Click "Demo Login" +3. This goes to `/home` (current LandingPage with agents) +4. Click "Dashboard" in the sidebar to navigate to `/dashboard` + +### Option 3: Update Login Redirect + +Change the login redirect in `src/pages/LoginPage.tsx` line 13: + +```typescript +// Change this: +navigate("/home"); + +// To this: +navigate("/dashboard"); +``` + +--- + +## ๐ŸŽฏ Routes Available + +| Route | Component | Description | +| ------------------ | ------------------ | ------------------------------------ | +| `/login` | LoginPage | Login screen | +| `/home` | LandingPage | Current agent dashboard | +| `/dashboard` | HomePage | **NEW** Home screen (spec-compliant) | +| `/buy-credits` | BuyCreditsPage | Credits purchase | +| `/forgot-password` | ForgotPasswordPage | Password recovery | + +--- + +## ๐Ÿ“ Next Steps + +### To make HomePage the default: + +```typescript +// In src/App.tsx +} /> +} /> +} /> +``` + +### To integrate with existing nav: + +The HomePage already integrates with: + +- โœ… Theme system +- โœ… Translation context (ready to use) +- โœ… Responsive design +- โœ… Screen component with background + +--- + +## ๐ŸŽจ Design Specifications Used + +All components follow the exact design from: + +- **Document:** `WEB_APP_REPLICATION_PROMPT.md` +- **Section:** Home Screen +- **Colors:** Deep emerald (#041815) + Gold (#CBA951) +- **Typography:** Bold headings, proper spacing +- **Shadows:** Medium elevation for cards +- **Borders:** 2px gold borders with 35-60% opacity + +--- + +## โœ… All Files Created Successfully + +- โœ… `src/theme/index.ts` (326 lines) +- โœ… `src/components/Screen.tsx` (112 lines) +- โœ… `src/components/StatCard.tsx` (95 lines) +- โœ… `src/components/QuickActionCard.tsx` (155 lines) +- โœ… `src/components/SectionCard.tsx` (85 lines) +- โœ… `src/components/SummaryCard.tsx` (130 lines) +- โœ… `src/components/CompanySelector.tsx` (180 lines) +- โœ… `src/pages/HomePage.tsx` (275 lines) + +**Total:** 8 new files, ~1,358 lines of code + +All files have: + +- โœ… No TypeScript errors +- โœ… Proper typing +- โœ… Documentation comments +- โœ… Theme integration +- โœ… Responsive design + +--- + +## ๐Ÿ› Troubleshooting + +### Can't see HomePage? + +1. Check console for errors +2. Verify route in `src/App.tsx` line 63 +3. Clear cache and restart dev server + +### Styles not applying? + +1. Verify `src/theme/index.ts` exists +2. Check import path: `import { theme } from '../theme'` + +### Background not showing? + +1. Add background image: `public/bg-pennyzo.png` +2. Or set `showBackground={false}` in Screen component + +--- + +**๐ŸŽ‰ Everything is ready to use!** diff --git a/WEB_APP_REPLICATION_PROMPT.md b/WEB_APP_REPLICATION_PROMPT.md new file mode 100644 index 0000000..30418cf --- /dev/null +++ b/WEB_APP_REPLICATION_PROMPT.md @@ -0,0 +1,1247 @@ +# Pennyzo Web App Replication Prompt for GitHub Copilot + +## ๐ŸŽฏ Objective + +Create a React/TypeScript web application that **exactly replicates** the design, components, theme, and user experience of the existing Pennyzo React Native mobile app. + +--- + +## ๐ŸŽจ Design System & Theme + +### Color Palette + +```typescript +const colors = { + // Background colors - Deep emerald/teal theme + background: '#041815', // Primary dark background + surface: '#06231F', // Card/container surfaces + surfaceAlt: '#0B312A', // Alternative surface (lighter) + accent: '#1A4036', // Accent containers + primary: '#0E5F4F', // Primary emerald + + // Highlight colors - Luxurious gold + highlight: '#CBA951', // Primary gold + highlightAlt: '#F2E5B5', // Light cream gold + + // Text colors + textPrimary: '#F8F5EB', // Primary text (cream white) + textSecondary: '#C8D9D4', // Secondary text (light teal) + + // Borders & decorative + border: 'rgba(203, 169, 81, 0.35)', // Subtle gold border + borderStrong: 'rgba(203, 169, 81, 0.6)', // Strong gold border + + // Shadows & effects + shadow: 'rgba(0, 0, 0, 0.4)', + shadowLight: 'rgba(0, 0, 0, 0.2)', + glowGold: 'rgba(203, 169, 81, 0.25)', + glowEmerald: 'rgba(14, 95, 79, 0.3)', + + // Special colors + tabIconInactive: '#6C7D78', + overlayDark: 'rgba(4, 24, 21, 0.6)', +}; +``` + +### Typography System + +```typescript +const typography = { + // Display - Hero sections + display: { + fontSize: '38px', + fontWeight: 900, + letterSpacing: '1px', + lineHeight: '46px', + }, + + // Headings + h1: { + fontSize: '32px', + fontWeight: 800, + letterSpacing: '0.8px', + lineHeight: '40px', + }, + h2: { + fontSize: '26px', + fontWeight: 800, + letterSpacing: '0.6px', + lineHeight: '34px', + }, + h3: { + fontSize: '22px', + fontWeight: 700, + letterSpacing: '0.5px', + lineHeight: '30px', + }, + h4: { + fontSize: '18px', + fontWeight: 700, + letterSpacing: '0.4px', + lineHeight: '26px', + }, + + // Body text + body: { + fontSize: '15px', + fontWeight: 400, + letterSpacing: '0.2px', + lineHeight: '22px', + }, + bodyBold: { + fontSize: '15px', + fontWeight: 700, + letterSpacing: '0.3px', + lineHeight: '22px', + }, + + // Supporting text + caption: { + fontSize: '13px', + fontWeight: 600, + letterSpacing: '0.2px', + lineHeight: '18px', + }, + + // Buttons + button: { + fontSize: '16px', + fontWeight: 800, + letterSpacing: '0.8px', + textTransform: 'uppercase', + }, + buttonSmall: { + fontSize: '14px', + fontWeight: 700, + letterSpacing: '0.6px', + textTransform: 'uppercase', + }, + + // Tab labels + tabLabel: { + fontSize: '11px', + fontWeight: 700, + letterSpacing: '0.5px', + textTransform: 'uppercase', + }, +}; +``` + +### Spacing System + +```typescript +const spacing = { + xs: '4px', + sm: '8px', + md: '12px', + lg: '16px', + xl: '20px', + xxl: '24px', + xxxl: '32px', + huge: '40px', + massive: '48px', +}; +``` + +### Border Radius + +```typescript +const borderRadius = { + sm: '8px', + md: '12px', + lg: '16px', + xl: '20px', + xxl: '24px', + round: '999px', +}; +``` + +### Icon Sizes + +```typescript +const iconSizes = { + xs: '16px', + sm: '20px', + md: '24px', + lg: '28px', + xl: '32px', + xxl: '40px', +}; +``` + +### Shadow System + +```typescript +const shadows = { + sm: { + boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', + }, + md: { + boxShadow: '0 8px 12px rgba(0, 0, 0, 0.3)', + }, + lg: { + boxShadow: '0 12px 16px rgba(0, 0, 0, 0.4)', + }, + xl: { + boxShadow: '0 16px 20px rgba(0, 0, 0, 0.5)', + }, + glow: { + boxShadow: '0 8px 12px rgba(203, 169, 81, 0.4)', + }, + glowStrong: { + boxShadow: '0 12px 20px rgba(203, 169, 81, 0.6)', + }, +}; +``` + +--- + +## ๐Ÿงฉ Core Components Library + +### 1. Screen Container Component + +**Purpose**: Main wrapper for all pages with optional background image + +**Features**: + +- Optional scrollable content +- Background image with blur effect (8px) and dark overlay (rgba(4, 24, 21, 0.75)) +- Background image: Uses "bg pennyzo.png" (emerald/teal themed background) +- Safe area padding +- Floating AI assistant button +- Default padding: 24px horizontal, 32px top, 100px bottom + +**Props**: + +```typescript +interface ScreenProps { + children: ReactNode; + scrollable?: boolean; + contentStyle?: CSSProperties; + showBackground?: boolean; + showAssistant?: boolean; +} +``` + +**Styling**: + +- Background overlay: `rgba(4, 24, 21, 0.75)` +- Blur on background: 8px +- Content gap: 24px + +--- + +### 2. PrimaryButton Component + +**Variants**: `filled` (gold background) | `outline` (translucent with gold border) + +**Filled Style**: + +- Background: `#CBA951` (gold) +- Text color: `#041815` (dark background color) +- Border: 2px solid `rgba(203, 169, 81, 0.6)` +- Height: 56px +- Border radius: 28px (fully rounded) +- Shadow: Strong elevation shadow +- Font: 17px, weight 800, uppercase, 0.8px letter-spacing + +**Outline Style**: + +- Background: `rgba(26, 64, 54, 0.92)` +- Text color: `#F2E5B5` (light gold) +- Border: 2px solid `rgba(203, 169, 81, 0.6)` +- Same dimensions as filled + +**Hover/Press Effects**: + +- Opacity: 0.85 +- Scale: 0.98 + +--- + +### 3. AgentCard Component + +**Design**: Vertical card with avatar, name, role, and status badge + +**Structure**: + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Avatar (80px) โ”‚ +โ”‚ with glow ring โ”‚ +โ”‚ status badge โ”‚ +โ”‚ โ”‚ +โ”‚ Agent Name โ”‚ +โ”‚ Role Text โ”‚ +โ”‚ [Status Badge] โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +**Styling**: + +- Card: `#0B312A` background, 2px gold border, 16px padding +- Border radius: 20px +- Avatar: 80px ร— 80px with glow effect +- Status indicator: 24px circle, positioned bottom-right of avatar +- Status colors: + - Active: `#4ADE80` (green) + - Idle: `#FBBF24` (yellow) + - Busy: `#F87171` (red) +- Shadows: Medium elevation + +--- + +### 4. StatCard Component + +**Design**: Compact metric display with icon, value, label, and optional trend + +**Layout**: + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ [Icon] [Trendโ†‘] โ”‚ +โ”‚ โ”‚ +โ”‚ Large Value โ”‚ +โ”‚ Small Label โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +**Styling**: + +- Background: `#0B312A` +- Border: 2px gold +- Icon wrapper: 44px ร— 44px, colored background (22% opacity of icon color) +- Value: h2 typography, gold color +- Trend badge: Green/red background with icon and percentage +- Padding: 16px + +--- + +### 5. QuickActionCard Component + +**Design**: Horizontal card with icon, label, description, and arrow + +**Layout**: + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ [Icon] Label [Arrowโ†’] โ”‚ +โ”‚ Description โ”‚ +โ”‚ [Badge if present] โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +**Styling**: + +- Background: `#0B312A` +- Icon container: 56px ร— 56px, rounded, with colored background +- Badge: Top-right of icon, red background `#EF4444` +- Chevron right: Gold color +- Padding: 16px + +--- + +### 6. SectionCard Component + +**Purpose**: Container for grouped content with header and optional footer + +**Styling**: + +- Background: `rgba(6, 35, 31, 0.95)` +- Border: 2px strong gold border +- Border radius: 24px +- Padding: 22px vertical, 24px horizontal +- Strong shadow elevation (14) +- Gap: 16px between sections + +--- + +### 7. SummaryCard Component + +**Design**: List of items with icons, labels, and count badges + +**Structure**: + +- Title with info icon +- Divider line +- List of items (icon + label + count badge) + +**Item Layout**: + +``` +[Icon 36ร—36] Label Text [Count Badge] +``` + +**Styling**: + +- Count badge: Rounded, `#1A4036` background, gold border +- Icons: 20px size in colored containers + +--- + +### 8. TaskHeader Component + +**Features**: Title, caption, and tab navigation + +**Tab Pills**: + +- Inactive: Transparent, gray text +- Active: `#1A4036` background, gold border, gold text +- Border radius: 18px +- Padding: 8px vertical, 18px horizontal +- Glow effect on active tab + +--- + +### 9. ListButton Component + +**Design**: Horizontal button with optional icon, label, and chevron + +**Styling**: + +- Background: `#0B312A` +- Icon container: 40px ร— 40px +- Chevron right indicator +- 2px gold border +- Padding: 16px + +--- + +### 10. FloatingAssistantButton Component + +**Special Features**: + +- **Position**: Fixed bottom-right (90px from bottom, 20px from right) +- **Size**: 72px ร— 72px circular button +- **Design**: Gold background with company logo +- **Effects**: + - Continuous pulse animation (1.0 โ†’ 1.15 scale, 1500ms duration) + - Glow animation (opacity pulse) + - Pulse ring behind button (fades out as it scales) + - Microphone indicator badge (bottom-right, green `#4ADE80`) + - "Ask AI Assistant" label (shows for 5 seconds, then hides) +- **Label**: Positioned to left of button, with arrow pointing to button +- **Interactions**: Opens ChatbotModal on click + +**Animation Specs**: + +```typescript +// Pulse animation - continuous loop +scale: 1.0 โ†’ 1.15 (1500ms ease-in-out) +// Glow animation +opacity: 0 โ†’ 1 (2000ms ease-in-out) +``` + +--- + +### 11. ChatbotModal Component + +**Design**: Full-screen modal with chat interface + +**Layout**: + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Header (Avatar + Title) โ”‚ +โ”‚ [Close button] โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ โ”‚ +โ”‚ Chat Messages Area โ”‚ +โ”‚ (Scrollable) โ”‚ +โ”‚ โ”‚ +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ [Audio Visualization] โ”‚ โ† Shows when recording/thinking +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ [๐ŸŽค] [Text Input] [Send โ†’] โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +**Message Bubbles**: + +- User messages: Right-aligned, gold background, dark text +- AI messages: Left-aligned, with AI icon, teal background, light text +- Timestamps: Small, below each message +- Thinking indicator: Three pulsing dots + +**Audio Visualization**: + +- 5 vertical bars with wave animation +- Heights: 24px, 32px, 40px, 32px, 24px +- Opacity animation: 0.3 โ†” 1.0 + +**Input Area**: + +- Voice button: Gold when active, outlined when inactive +- Text input: Flexible height (max 100px) +- Send button: Gold background, disabled when empty + +--- + +### 12. LanguageSelector Component + +**Design**: Modal with language list + +**Languages Supported**: + +1. English +2. Hindi (เคนเคฟเคจเฅเคฆเฅ€) +3. Bengali (เฆฌเฆพเฆ‚เฆฒเฆพ) +4. Telugu (เฐคเฑ†เฐฒเฑเฐ—เฑ) +5. Marathi (เคฎเคฐเคพเค เฅ€) +6. Tamil (เฎคเฎฎเฎฟเฎดเฏ) +7. Gujarati (เช—เซเชœเชฐเชพเชคเซ€) +8. Kannada (เฒ•เฒจเณเฒจเฒก) +9. Malayalam (เดฎเดฒเดฏเดพเดณเด‚) +10. Punjabi (เจชเฉฐเจœเจพเจฌเฉ€) + +**List Item**: + +- Language name (English) +- Native name (in native script) +- Checkmark icon when selected +- Selected: `#1A4036` background + +--- + +## ๐Ÿ“ฑ Screen Layouts + +### Welcome Screen + +**Layout**: Centered vertical stack + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ โ”‚ +โ”‚ [Company Logo] โ”‚ +โ”‚ 200 ร— 200 โ”‚ +โ”‚ โ”‚ +โ”‚ Your AI team for โ”‚ +โ”‚ business growth โ”‚ +โ”‚ โ”‚ +โ”‚ Subtitle text here โ”‚ +โ”‚ โ”‚ +โ”‚ [Sign Up Button] โ”‚ +โ”‚ [Log In Button] โ”‚ +โ”‚ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +**Key Elements**: + +- Logo: 200px ร— 200px centered +- Hero title: 34px, weight 900, gold color, center-aligned +- Subtitle: 16px, gray color +- Gap between sections: 48px +- Buttons: Full width with 16px gap + +--- + +### Home Screen + +**Structure & Components**: + +1. **Top Bar** (Flex row) + +- `Text` greeting using `typography.h2` +- Action buttons: Profile (`ListButton` styling), Language selector trigger, Notifications with badge +- All buttons reuse shared styles: 44px square, `colors.surfaceAlt` background, `borderRadius.md` + +2. **Company Selector Card** + +- Reuse `SectionCard` styling condensed to 72px height +- Contains logo image, company name (`typography.h4`), industry label (`typography.caption`) +- Chevron icon from MaterialCommunityIcons + +3. **Decorative Divider** + +- 1px `colors.highlight` line, 50% opacity, full width + +4. **Quick Stats Row** + +- Horizontal `ScrollView`/`div` with 16px gap +- Render three `StatCard` components (Revenue, Employees, Growth) +- Provide trend data: `{ value: '+18%', isPositive: true }` + +5. **AI Insights Summary** + +- Single `SummaryCard` with items array (Invoices, HR approvals, Renewals) +- Each item uses icon, color accent, count + +6. **Suggested Actions** + +- Header text block (title + subtitle) +- Vertical stack of `QuickActionCard` components (Send Salary Slips, Renew Vendor Contract, Review P&L Report) + +**Sample Prompt**: + +> "Using the design tokens, build the Home screen with a top greeting bar, company selector card, stat cards (revenue, employees, growth), AI insights `SummaryCard`, and three `QuickActionCard`s. Use the data structures defined in the RN HomeScreen.tsx file for copy and counts." + +**Color Accents**: Green `#4ADE80`, Yellow `#FBBF24`, Red `#EF4444` + +--- + +### Agents Screen + +**Hero Row**: + +- Title (`typography.h1`) + subtitle (`typography.body`) +- Add Agent button: 48px square, `colors.highlight` background, `shadows.glow` + +**Status Summary Bar**: + +- Container uses `SectionCard` skeleton with `flexDirection: 'row'` +- Three segments separated by 1px divider (`colors.border`) +- Each segment: dot indicator (8px), label text from i18n: Active (3), Idle (2), Busy (1) + +**Available Agents Grid**: + +- Responsive grid (mobile: 2 columns, desktop: auto-fill min 220px) +- Render `AgentCard` for each entry (Evelyn, Malik, Aria, Marcus, Sofia, Alex) +- Use avatar URLs from original RN screen (`https://i.pravatar.cc/120?img=X`) + +**Quick Actions Row**: + +- Two pill buttons using `QuickActionCard` styling reduced to 180px width +- Icons: `message-text`, `history` + +**Sample Prompt**: + +> "Recreate the Agents screen: header with title, subtitle, and gold add button; status summary bar showing Active/Idle/Busy counts; responsive grid of `AgentCard`s using the exact agent list from AgentsScreen.tsx; and two `QuickActionCard`-style buttons for Chat and Reports." + +--- + +### Tasks Screen + +**Features**: + +- TaskHeader with 3 tabs: HR | CRM | Strategy +- Tab content fades in/out on switch (140ms fade out, 180ms fade in) +- Each tab has distinct content sections + +**Shared Layout Rules**: + +- Wrap tab content inside `Animated.View` with fade transitions +- Section headers use `typography.caption` uppercase with 1.2px letter-spacing +- 16px vertical gaps between sections; inner cards reuse `StatCard`, `SummaryCard`, and `QuickActionCard` + +**HR Tab Composition**: + +1. Overview: Three `StatCard`s for Headcount, Present, On leave +2. Team Directory: `SummaryCard` with leadership/product/operations counts +3. Actions: Three `QuickActionCard`s (Process payroll, Send salary slips, Generate reports) +4. Insights: Custom `SectionCard` with icon (`lightbulb-outline`) and narrative text + +**CRM Tab Composition**: + +1. Performance Stats: `StatCard`s for Pipeline value, Conversion rate, Escalations (red accent) +2. Pipeline Summary: `SummaryCard` listing Follow-ups, Contracts, Responses +3. Actions: `QuickActionCard`s for Client concierge and Launch campaign +4. Insights: `SectionCard` with `chart-areaspline` icon and copy from translations + +**Strategy Tab Composition**: + +1. Progress Stats: `StatCard`s for OKRs, Initiatives, Markets +2. SWOT Grid: Four `SectionCard`-like cells (Strengths, Weaknesses, Opportunities, Threats) +3. Actions: `QuickActionCard`s for Executive summary and Steering committee + +**Sample Prompt**: + +> "Implement the Tasks screen with a `TaskHeader` controlling HR/CRM/Strategy tabs. Each tab reuses the same data and copy from TasksScreen.tsx: stat cards up top, summary cards, quick actions, and insights/SWOT sections. Include the fade animation between tabs and maintain the uppercase section labels." + +--- + +### Business Setup Screen + +**Multi-step onboarding** (3 steps): + +**Progress Bar**: + +- 6px height +- Gold fill animates: 33% โ†’ 66% โ†’ 100% +- Step counter: "Step X of 3" + +**Step 1 - Company Name**: + +- Office building icon (60px, gold) +- Title: "Welcome to Pennyzo! ๐Ÿ‘‹" +- Text input for company name +- Optional: Company logo upload + - Dashed border button (3px, gold, dashed) + - Image preview: 200px ร— 200px + - Change/Remove buttons + +**Step 2 - Industry**: + +- Domain icon (60px) +- Title: "Choose your industry" +- Grid: 2 columns of industry cards + - Each card: Icon + label + - Selected: Gold background + +**Industries**: + +- Retail, Services, Manufacturing, Tech, Healthcare, Education, Hospitality, Other + +**Step 3 - Agents**: + +- Robot icon (60px) +- Title: "Select your AI team" +- Vertical list of agent cards + - Icon (50px), Name, Description + - Checkbox (28px) + - Selected: Gold border + glow + +**Footer**: + +- Back button (if not first step) +- Continue button (full width, gold) +- Finish button on last step + +--- + +### Documents Screen + +**Header**: + +- Title (`typography.h1`) and subtitle (`typography.body`) + +**Overview Stack**: + +- Use three `StatCard`s for document counts (Auto-prepped, Contracts, Legal) mirroring RN layout + +**Recent Activity**: + +- `SectionCard` containing list of activity rows +- Each row: icon bubble (MaterialCommunityIcons), description text from i18n, timestamp chip (`typography.caption`) +- Divider between rows using `colors.border` + +**Quick Actions**: + +- Two `QuickActionCard`s: Search Documents, Bulk Upload + +**Sample Prompt**: + +> "Build the Documents screen using the same copy as DocumentsScreen.tsx: header, stat cards for overview, recent activity list inside a `SectionCard`, and quick actions for Search Documents and Bulk Upload with their icons." + +--- + +### Generate Screen + +**Hero Block**: + +- Title + subtitle, optional CTA button (reuse `PrimaryButton` outline variant) + +**Seasonal Campaigns Carousel**: + +- Horizontal scroll of `QuickActionCard`-style tiles (Diwali, New Year) with badges `AI generated` + +**Content Templates Grid**: + +- 2ร—2 grid on desktop (Blog Post, Email Campaign, Social Media, Design Assets) +- Each tile uses `SectionCard` mini variant with icon, title, short description + +**Brand Voice Section**: + +- `SectionCard` with sliders or badges referencing brand tone, using `ListButton` entries for editing voice presets + +**Sample Prompt**: + +> "Recreate the Generate screen: hero copy, seasonal campaigns row, four content template cards, and a brand voice `SectionCard`. Use the template names and descriptions straight from GenerateScreen.tsx." + +--- + +### Profile Screen + +**Header Card**: + +- `SectionCard` with avatar circle (96px), user name (`typography.h2`), role, company stats badges (Member since 2022) + +**Menu Grid**: + +- Use `ListButton` components for User Info, Subscription, Integrations, Settings, Help, Logout +- Each includes icon mapping from RN file + +**Generate & Language Shortcuts**: + +- Secondary `SectionCard` linking to Generate content and Language selector modal + +**Sample Prompt**: + +> "Mirror the Profile screen: top `SectionCard` for the user profile (John Doe, Executive Director, Member since 2022) and a list of `ListButton`s for User Info, Subscription, Integrations, Settings, Help, Logout." + +--- + +## ๐ŸŽญ Animations & Interactions + +### Button Press Animation + +```css +transition: all 150ms ease; +&:active { + opacity: 0.85; + transform: scale(0.98); +} +``` + +### Card Hover (for web) + +```css +transition: all 200ms ease; +&:hover { + transform: translateY(-2px); + box-shadow: [enhanced shadow]; +} +``` + +### Fade In Animation + +```css +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +animation: fadeIn 300ms ease; +``` + +### Tab Switching + +```typescript +// Fade out current (140ms) โ†’ Switch content โ†’ Fade in new (180ms) +opacity: 1 โ†’ 0 (140ms) โ†’ [change] โ†’ 0 โ†’ 1 (180ms) +``` + +--- + +## ๐ŸŒ Navigation Structure + +### Root Stack (Auth Flow) + +1. **Welcome** โ†’ Login / Signup +2. **Login** โ†’ MainTabs +3. **Signup** โ†’ BusinessSetup +4. **BusinessSetup** โ†’ MainTabs + +### Main Navigation (Mobile vs Web) + +- **Mobile/Tablet**: Bottom tab bar identical to the native app for consistency. +- **Desktop/Web**: Persistent **left sidebar** that replaces the bottom tabs. The same five primary destinations map directly to sidebar buttons. + +### Sidebar Navigation (Web Primary Navigation) + +1. **Home** โ€“ Dashboard & insights (`home`, `home-outline`) +2. **Agents** โ€“ AI team management (`robot`, `robot-outline`) +3. **Tasks** โ€“ HR, CRM, Strategy tabs (`clipboard-text`, `clipboard-text-outline`) +4. **Documents** โ€“ File management (`file-document`, `file-document-outline`) +5. **More** โ€“ Secondary hub (Profile, Generate, Settings) (`dots-horizontal-circle`, `dots-horizontal-circle-outline`) + +**Sidebar Layout Specs**: + +- Width: 280px expanded, 92px collapsed (hover-reveal for labels). +- Background: `#06231F` top-to-bottom gradient overlay on `colors.surface`. +- Border: Right edge 1.5px solid `rgba(203, 169, 81, 0.35)`. +- Padding: 28px top, 20px horizontal, 24px bottom. +- Item spacing: 14px vertical gap between navigation buttons. +- Sticky: Fixed to left, full height, scrolls independently if needed. +- Logo area: 72px tall header block with app logo (`ic_launcher_foreground.png`) and "Pennyzo" wordmark in `typography.h4`. + +**Navigation Item Styling**: + +- Container: 56px height pill button, border radius 18px. +- Active state: Background `rgba(203, 169, 81, 0.18)`, left accent bar 4px wide in `colors.highlight`, icon/text color `colors.highlightAlt`, bold label. +- Inactive state: Background transparent, icon `colors.tabIconInactive`, label `colors.textSecondary`. +- Hover: Background `rgba(26, 64, 54, 0.6)`, subtle glow shadow `shadows.sm`. +- Icon size: 24px (inactive), 26px (active). +- Label typography: `typography.tabLabel` (uppercase, 0.5px letter-spacing). +- Notifications: Optional badge (same spec as mobile) positioned top-right of button. + +**Sidebar Footer**: + +- Add `ListButton`-style entries for Support, Settings, and Sign Out (if required by web IA). +- Include language selector trigger (opens `LanguageSelector` modal) in footer area. + +**Responsive Behavior**: + +- โ‰ค1024px: Sidebar collapses to 92px rail with icons only; labels show on hover tooltips. +- โ‰ค768px: Slide-in drawer triggered by hamburger button; bottom tab bar appears for phones. +- โ‰ฅ1440px: Sidebar remains expanded; main content receives 48px left padding to account for sidebar. + +**Routing**: + +- Each nav item routes to the respective screen component described in this document (`HomeScreen`, `AgentsScreen`, `TasksScreen`, `DocumentsScreen`, `ProfileScreen / GenerateScreen` under the "More" umbrella). +- Active route highlights the corresponding sidebar button. + +> โœ… **Important**: The content, names, and styling for each sidebar destination must exactly match the mobile screens described above. Reuse the same component structure (StatCard, QuickActionCard, etc.) when rendering the desktop views. + +--- + +## ๐Ÿ”ค Internationalization (i18n) + +**Setup**: React i18next with AsyncStorage persistence + +**Supported Languages**: 10 Indian languages + English + +**Key Translation Keys** (sample): + +```typescript +{ + home: 'Home', + agents: 'Agents', + tasks: 'Tasks', + yourAiTeam: 'Your AI team', + forBusinessGrowth: 'for business growth', + homeScreen: { + greeting: { morning, afternoon, evening }, + stats: { revenue, employees, growth }, + actions: { sendSalarySlips, renewVendorContract, ... } + }, + agentsScreen: { ... }, + tasksScreen: { ... }, + // ... etc +} +``` + +**Implementation**: + +- Use `useTranslation()` hook +- Store language preference in localStorage/AsyncStorage +- Language selector modal component +- All text must be wrapped in `t('key')` + +--- + +## ๐Ÿ“ฆ Required Dependencies + +```json +{ + "dependencies": { + "react": "^18.x", + "react-dom": "^18.x", + "react-router-dom": "^6.x", + "i18next": "^23.x", + "react-i18next": "^13.x", + "framer-motion": "^10.x", // For animations + "react-icons": "^4.x", // Material Design icons + "@emotion/react": "^11.x", // Or styled-components + "@emotion/styled": "^11.x" + } +} +``` + +--- + +## ๐ŸŽฏ Implementation Checklist + +### Phase 1: Foundation + +- [ ] Set up theme system (colors, typography, spacing) +- [ ] Create base Screen component with background +- [ ] Implement PrimaryButton component +- [ ] Set up routing structure +- [ ] Add background image and overlay system + +### Phase 2: Core Components + +- [ ] AgentCard component +- [ ] StatCard component +- [ ] QuickActionCard component +- [ ] SectionCard component +- [ ] SummaryCard component +- [ ] TaskHeader component +- [ ] ListButton component + +### Phase 3: Special Components + +- [ ] FloatingAssistantButton with animations +- [ ] ChatbotModal with message system +- [ ] LanguageSelector modal +- [ ] Audio visualization component + +### Phase 4: Screens + +- [ ] Welcome screen +- [ ] Login screen +- [ ] Signup screen +- [ ] BusinessSetup screen (multi-step) +- [ ] Home screen +- [ ] Agents screen +- [ ] Tasks screen (with tabs) +- [ ] Documents screen +- [ ] Generate screen +- [ ] Profile screen + +### Phase 5: Features + +- [ ] i18n setup (10 languages) +- [ ] Unified navigation (sidebar on web, bottom tabs on mobile) +- [ ] Modal system +- [ ] Animation system +- [ ] State management +- [ ] LocalStorage/API integration + +### Phase 6: Polish + +- [ ] Responsive design (mobile, tablet, desktop) +- [ ] Accessibility (ARIA labels, keyboard navigation) +- [ ] Loading states +- [ ] Error handling +- [ ] Performance optimization + +--- + +## ๐Ÿงญ Sidebar Implementation Steps + +1. **Scaffold Layout Shell** + +- Create `AppShell` with `Sidebar` component on the left and `MainContent` on the right. +- Reserve 280px for the sidebar on desktop, handle collapsed and mobile drawer states. + +2. **Build Sidebar Component** + +- Implement logo header, navigation list, and footer actions using the specs in _Sidebar Navigation_. +- Use the icon mapping provided and wire each button to its route via React Router. + +3. **Wire Active State Logic** + +- Highlight active route (left accent bar + filled background + larger icon). +- Add hover/tap transitions using `framer-motion` or CSS transitions. + +4. **Integrate Screen Components** + +- For each nav destination, reuse the screen content defined above (HomeScreen, AgentsScreen, etc.). +- Ensure the screen components sit inside `Screen` wrapper so background/assistant features remain consistent. + +5. **Responsive Behavior** + +- Desktop โ‰ฅ1025px: Expanded sidebar. +- Tablet 768โ€“1024px: Collapsible rail with tooltip labels. +- Mobile โ‰ค767px: Hide sidebar, use bottom tab bar and hamburger-triggered drawer. + +6. **Accessibility & UX Polish** + +- Provide aria-labels, focus outlines, and keyboard navigation (Arrow keys cycle items, Enter activates). +- Ensure language selector and sign-out actions are reachable via the sidebar footer. + +> Follow these steps in order to adapt the existing mobile-first navigation into a desktop-friendly sidebar without changing the underlying screen content. + +--- + +## ๐Ÿ“ Prompt Cheat Sheet (Copy/Paste) + +1. **Theme & Layout Shell** + +- _"Set up the Pennyzo theme using the colors, typography, spacing, and shadows from WEB_APP_REPLICATION_PROMPT.md, and scaffold an AppShell with a left sidebar and main content area."_ + +2. **Sidebar Navigation** + +- _"Implement the Pennyzo sidebar exactly as specified: logo header, five nav buttons (Home, Agents, Tasks, Documents, More), active state glow, footer actions, responsive behavior."_ + +3. **Home Screen** + +- _"Using the Pennyzo components (StatCard, SummaryCard, QuickActionCard), recreate the Home screen layout: greeting bar, company selector card, three stat cards, AI insights summary, and suggested actions."_ + +4. **Agents Screen** + +- _"Build the Agents screen with header, status summary bar, responsive grid of AgentCard components populated with the original agent list, and quick action buttons for Chat and Reports."_ + +5. **Tasks Screen** + +- _"Create the Tasks screen with TaskHeader tabs (HR/CRM/Strategy) and reuse the arrays from TasksScreen.tsx to render stat cards, summary cards, quick actions, insights, and SWOT sections with fade transitions."_ + +6. **Documents Screen** + +- _"Construct the Documents screen: header, overview stat cards, SectionCard for recent activity rows, and quick action cards for Search Documents and Bulk Upload."_ + +7. **Generate Screen** + +- _"Lay out the Generate screen with hero copy, seasonal campaign carousel, four content template cards, and a brand voice SectionCard using the copy from GenerateScreen.tsx."_ + +8. **Profile / More Screens** + +- _"Replicate the Profile screen with a SectionCard header (avatar, name, role, member since) and ListButton entries for User Info, Subscription, Integrations, Settings, Help, Logout, plus shortcuts to Generate and Language selector."_ + +9. **Chatbot & Assistant** + +- _"Port the FloatingAssistantButton and ChatbotModal exactly, including pulse/glow animations, microphone badge, and message bubble styling."_ + +10. **Business Setup Flow** + +- _"Implement the three-step Business Setup onboarding with progress bar, company input/logo upload, industry grid, and AI agent selection using the defined components."_ + +Run these prompts sequentially in Copilot to guarantee every screen and feature mirrors the native app. + +--- + +## ๐ŸŽจ Design Philosophy + +**Key Characteristics**: + +1. **Luxurious & Professional**: Gold accents on dark emerald/teal +2. **High Contrast**: Light text on dark backgrounds for readability +3. **Generous Spacing**: Never cramped, breathing room between elements +4. **Soft Glows**: Shadow system creates depth without harshness +5. **Rounded Corners**: Everything is rounded (8-24px) +6. **Bold Typography**: Heavy weights (700-900) for headers +7. **Subtle Animations**: Smooth transitions, pulse effects +8. **Consistent Elevation**: Cards, buttons, modals have distinct layers + +**Visual Hierarchy**: + +- Primary actions: Gold filled buttons +- Secondary actions: Gold outlined buttons +- Tertiary actions: Text buttons or icons +- Information cards: Medium elevation shadows +- Active states: Glow effects +- Disabled states: 50% opacity + +--- + +## ๐Ÿ“ Responsive Breakpoints + +```css +/* Mobile first approach */ +mobile: 0-640px +tablet: 641px-1024px +desktop: 1025px+ + +/* Adjustments for web */ +- Tab bar: Bottom on mobile, sidebar on desktop +- Grid columns: 2 on mobile, 3-4 on tablet, 4-6 on desktop +- Floating button: Bottom-right on all sizes +- Modals: Full screen on mobile, centered card on desktop +- Navigation: Hamburger on mobile, persistent on desktop +``` + +--- + +## ๐ŸŽฌ Special Notes for GitHub Copilot + +1. **Background Image**: The app uses "bg pennyzo.png" - a teal/emerald gradient background. Apply 8px blur + dark overlay (75% opacity) on all main screens. + +2. **Company Logo**: "ic_launcher_foreground.png" - appears in multiple places (welcome screen, floating button, company selector). Size varies by context. + +3. **Icon Library**: Use Material Community Icons or React Icons library. Map icon names from React Native to web equivalents. + +4. **Tab Navigation**: Bottom navigation on mobile should transform to sidebar/horizontal tabs on desktop for better UX. + +5. **Floating Button**: The AI assistant button is a signature feature - must pulse, glow, and animate exactly as described. + +6. **Card Interactions**: All cards should have press/click feedback. Scale down slightly and reduce opacity on interaction. + +7. **Modal System**: Modals should overlay with dark backdrop (70% opacity) and animate in from bottom/center. + +8. **Text Rendering**: Use system fonts that support international scripts (Indic languages). Fallback chain: -apple-system, Segoe UI, Roboto, etc. + +9. **State Management**: Use React Context or Redux for global state (user, company selection, language, theme). + +10. **Performance**: Lazy load screens, optimize images, use CSS transforms for animations (GPU accelerated). + +--- + +## ๐Ÿš€ Getting Started Commands + +```bash +# Create React app with TypeScript +npx create-react-app pennyzo-web --template typescript + +# Or use Vite for faster dev experience +npm create vite@latest pennyzo-web -- --template react-ts + +# Install dependencies +npm install react-router-dom i18next react-i18next framer-motion react-icons @emotion/react @emotion/styled + +# Project structure +src/ + โ”œโ”€โ”€ components/ # All reusable components + โ”œโ”€โ”€ screens/ # Page components + โ”œโ”€โ”€ theme/ # Design system (colors, typography, etc.) + โ”œโ”€โ”€ i18n/ # Internationalization setup + โ”œโ”€โ”€ assets/ # Images, icons + โ”œโ”€โ”€ hooks/ # Custom React hooks + โ”œโ”€โ”€ contexts/ # React Context providers + โ””โ”€โ”€ types/ # TypeScript interfaces +``` + +--- + +## โœ… Final Output Requirements + +The web app should be: + +1. **Pixel-perfect**: Match mobile app design exactly +2. **Responsive**: Works on all screen sizes +3. **Accessible**: WCAG 2.1 AA compliant +4. **Performant**: Fast load times, smooth animations +5. **Internationalized**: Support all 10 languages +6. **Maintainable**: Clean code, documented components +7. **Tested**: Unit tests for components, E2E for critical flows + +**Success Criteria**: + +- [ ] User can complete entire onboarding flow +- [ ] All screens render correctly +- [ ] Navigation works seamlessly +- [ ] Language switching works +- [ ] AI chatbot modal functions +- [ ] All animations are smooth +- [ ] No console errors +- [ ] Responsive on mobile, tablet, desktop + +--- + +## ๐Ÿ“ž Component Usage Examples + +### Screen Template + +```tsx +import { Screen } from '@/components/Screen'; + +function MyScreen() { + return ( + + {/* Your content here */} + + ); +} +``` + +### Button Usage + +```tsx + navigate('/next')} +/> +``` + +### Agent Card + +```tsx + openChat('evelyn')} +/> +``` + +### Stat Card + +```tsx + +``` + +--- + +This document provides everything needed to replicate the Pennyzo mobile app design in a web application. Follow the specifications precisely for consistent results. diff --git a/package-lock.json b/package-lock.json index 8138595..06b1783 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,12 @@ "name": "pennyzo-web-app", "version": "0.0.0", "dependencies": { + "framer-motion": "^12.23.24", + "i18next": "^25.6.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-i18next": "^16.2.1", + "react-icons": "^5.5.0", "react-router-dom": "^7.9.1" }, "devDependencies": { @@ -276,6 +280,15 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", @@ -2648,6 +2661,33 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framer-motion": { + "version": "12.23.24", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.24.tgz", + "integrity": "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.23.23", + "motion-utils": "^12.23.6", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2786,6 +2826,46 @@ "node": ">= 0.4" } }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/i18next": { + "version": "25.6.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.6.0.tgz", + "integrity": "sha512-tTn8fLrwBYtnclpL5aPXK/tAYBLWVvoHM1zdfXoRNLcI+RvtMsoZRV98ePlaW3khHYKuNh/Q65W/+NVFUeIwVw==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.6" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3119,6 +3199,21 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/motion-dom": { + "version": "12.23.23", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz", + "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.23.6" + } + }, + "node_modules/motion-utils": { + "version": "12.23.6", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", + "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3590,6 +3685,42 @@ "react": "^19.1.1" } }, + "node_modules/react-i18next": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.2.1.tgz", + "integrity": "sha512-z7TVwd8q4AjFo2n7oOwzNusY7xVL4uHykwX1zZRvasUQnmnXlp7Z1FZqXvhK/6hQaCvWTZmZW1bMaUWKowtvVw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.6", + "html-parse-stringify": "^3.0.1", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "i18next": ">= 25.5.2", + "react": ">= 16.8.0", + "typescript": "^5" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", @@ -4145,6 +4276,12 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4162,7 +4299,7 @@ "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -4237,6 +4374,15 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4350,6 +4496,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index e370866..f9f2e13 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,12 @@ "preview": "vite preview" }, "dependencies": { + "framer-motion": "^12.23.24", + "i18next": "^25.6.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-i18next": "^16.2.1", + "react-icons": "^5.5.0", "react-router-dom": "^7.9.1" }, "devDependencies": { diff --git a/src/App.tsx b/src/App.tsx index ac1c292..6f043ec 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,15 +1,24 @@ import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import { Suspense, lazy } from 'react'; +import { TranslationProvider } from './context/TranslationContext'; // Route-level code splitting (improves first paint for initial /login route) const LandingPage = lazy(() => import('./pages/LandingPage')); +const HomePage = lazy(() => import('./pages/HomePage')); +const AgentsPage = lazy(() => import('./pages/AgentsPage')); +const TasksPage = lazy(() => import('./pages/TasksPage')); +const DocumentsPage = lazy(() => import('./pages/DocumentsPage')); +const MorePage = lazy(() => import('./pages/MorePage')); const LoginPage = lazy(() => import('./pages/LoginPage')); const ForgotPasswordPage = lazy(() => import('./pages/ForgotPasswordPage')); const BuyCreditsPage = lazy(() => import('./pages/BuyCreditsPage')); +const ProfilePage = lazy(() => import('./pages/ProfilePage')); +const SettingsPage = lazy(() => import('./pages/SettingsPage')); function App() { return ( - + +
{/* Background System - Fixed layers with proper z-index */}
{/* Main Content - Highest z-index for interactivity */} -
+
@@ -57,7 +66,15 @@ function App() { } /> } /> + } /> + } /> + } /> + } /> + } /> + } /> } /> + } /> + } /> } /> } /> @@ -65,6 +82,7 @@ function App() {
+ ); } diff --git a/src/assets/ic_launcher_foreground.png b/src/assets/ic_launcher_foreground.png new file mode 100644 index 0000000..d695de9 Binary files /dev/null and b/src/assets/ic_launcher_foreground.png differ diff --git a/src/components/AgentCard.tsx b/src/components/AgentCard.tsx new file mode 100644 index 0000000..bc2014b --- /dev/null +++ b/src/components/AgentCard.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import type { ReactNode } from 'react'; +import { theme } from '../theme'; + +export type AgentStatus = 'active' | 'idle' | 'busy'; + +export interface AgentCardProps { + name: string; + role: string; + status: AgentStatus; + avatar: string; + accent?: string; + footer?: ReactNode; + onClick?: () => void; +} + +const STATUS_COLOR: Record = { + active: theme.colors.success, + idle: theme.colors.warning, + busy: theme.colors.error, +}; + +const STATUS_LABEL: Record = { + active: 'Active', + idle: 'Idle', + busy: 'Busy', +}; + +/** + * Agent card replicates the mobile Agent panel styling with glow avatar, badge, and status indicator. + */ +const AgentCard: React.FC = ({ name, role, status, avatar, accent, footer, onClick }) => { + const statusColor = STATUS_COLOR[status]; + + return ( + + ); +}; + +export default AgentCard; diff --git a/src/components/AgentPanel.tsx b/src/components/AgentPanel.tsx index d013800..72a552f 100644 --- a/src/components/AgentPanel.tsx +++ b/src/components/AgentPanel.tsx @@ -1,4 +1,5 @@ import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; export type Agent = { id: string; @@ -14,18 +15,19 @@ interface AgentPanelProps { } const AgentPanel: React.FC = ({ agents, activeAgentId, onChangeAgent }) => { + const { t } = useTranslation(); const active = useMemo(() => agents.find(a => a.id === activeAgentId) || agents[0], [agents, activeAgentId]); // 8 diverse agents for the 3D carousel const carouselAgents = useMemo(() => [ - { id: 'hr', name: 'HR Command', emoji: '๐Ÿ‘ฅ', color: 'from-luxury-gold/30 to-brass/30' }, - { id: 'finance', name: 'Finance Sage', emoji: '๐Ÿ’ฐ', color: 'from-bronze/30 to-luxury-gold/30' }, - { id: 'project', name: 'Project Sensei', emoji: '๐Ÿ“Š', color: 'from-brass/30 to-bronze/30' }, - { id: 'marketing', name: 'Marketing Genius', emoji: '๐ŸŽฏ', color: 'from-luxury-gold/30 to-cream/30' }, - { id: 'analytics', name: 'Data Wizard', emoji: '๐Ÿ“ˆ', color: 'from-bronze/30 to-brass/30' }, - { id: 'security', name: 'Security Guard', emoji: '๐Ÿ›ก๏ธ', color: 'from-deep-forest/40 to-luxury-gold/30' }, - { id: 'support', name: 'Support Hero', emoji: '๐ŸŽง', color: 'from-brass/30 to-rich-brown/30' }, - { id: 'research', name: 'Research Bot', emoji: '๐Ÿ”', color: 'from-luxury-gold/30 to-bronze/30' } + { id: 'hr', translationKey: 'hr_command', emoji: '๐Ÿ‘ฅ', color: 'from-luxury-gold/30 to-brass/30' }, + { id: 'finance', translationKey: 'finance_sage', emoji: '๐Ÿ’ฐ', color: 'from-bronze/30 to-luxury-gold/30' }, + { id: 'project', translationKey: 'project_sensei', emoji: '๐Ÿ“Š', color: 'from-brass/30 to-bronze/30' }, + { id: 'marketing', translationKey: 'marketing_genius', emoji: '๐ŸŽฏ', color: 'from-luxury-gold/30 to-cream/30' }, + { id: 'analytics', translationKey: 'data_wizard', emoji: '๐Ÿ“ˆ', color: 'from-bronze/30 to-brass/30' }, + { id: 'security', translationKey: 'security_guard', emoji: '๐Ÿ›ก๏ธ', color: 'from-deep-forest/40 to-luxury-gold/30' }, + { id: 'support', translationKey: 'support_hero', emoji: '๐ŸŽง', color: 'from-brass/30 to-rich-brown/30' }, + { id: 'research', translationKey: 'research_bot', emoji: '๐Ÿ”', color: 'from-luxury-gold/30 to-bronze/30' } ], []); return ( @@ -66,9 +68,9 @@ const AgentPanel: React.FC = ({ agents, activeAgentId, onChange style={{ left: '50%', top: '50%', - transform: `translate(${x - 24}px, ${y - 24}px)`, + transform: `t(${x - 24}px, ${y - 24}px)`, }} - title={agent.name} + title={t(agent.translationKey)} >
@@ -97,11 +99,11 @@ const AgentPanel: React.FC = ({ agents, activeAgentId, onChange style={{ left: '50%', top: '50%', - transform: `translate(${x - 24}px, ${y + 40}px)`, + transform: `t(${x - 24}px, ${y + 40}px)`, }} >
- {agent.name} + {t(agent.translationKey)}
@@ -114,7 +116,7 @@ const AgentPanel: React.FC = ({ agents, activeAgentId, onChange
๐Ÿค–
-
HUB
+
{t('hub')}
{/* Removed pulsing rings for a calmer static display */} @@ -128,3 +130,4 @@ const AgentPanel: React.FC = ({ agents, activeAgentId, onChange }; export default AgentPanel; + diff --git a/src/components/ChatDock.tsx b/src/components/ChatDock.tsx index 7a657a8..b5ed58c 100644 --- a/src/components/ChatDock.tsx +++ b/src/components/ChatDock.tsx @@ -1,4 +1,5 @@ import React, { useState, useRef, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; export type ChatMessage = { id: string; @@ -14,9 +15,12 @@ interface ChatDockProps { leftOffsetClass?: string; // e.g., 'left-20 md:left-64' } -const ChatDock: React.FC = ({ messages, onSend, placeholder = 'Ask anythingโ€ฆ', className = '', leftOffsetClass = 'left-0' }) => { +const ChatDock: React.FC = ({ messages, onSend, placeholder, className = '', leftOffsetClass = 'left-0' }) => { + const { t } = useTranslation(); const [text, setText] = useState(''); const listRef = useRef(null); + + const effectivePlaceholder = placeholder || t('chat_placeholder'); useEffect(() => { if (listRef.current) listRef.current.scrollTop = listRef.current.scrollHeight; @@ -52,11 +56,11 @@ const ChatDock: React.FC = ({ messages, onSend, placeholder = 'As onChange={(e) => setText(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } }} rows={2} - placeholder={placeholder} + placeholder={effectivePlaceholder} className="flex-1 resize-none px-4 py-3 h-12 bg-deep-forest/70 border border-luxury-gold/40 rounded-xl text-cream focus:outline-none focus:ring-2 focus:ring-luxury-gold/40" /> @@ -65,3 +69,4 @@ const ChatDock: React.FC = ({ messages, onSend, placeholder = 'As }; export default ChatDock; + diff --git a/src/components/ChatbotModal.tsx b/src/components/ChatbotModal.tsx new file mode 100644 index 0000000..ea0eadc --- /dev/null +++ b/src/components/ChatbotModal.tsx @@ -0,0 +1,230 @@ +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import type { FormEvent } from 'react'; +import { AnimatePresence, motion } from 'framer-motion'; +import { theme } from '../theme'; + +export type ChatMessageRole = 'assistant' | 'user'; + +export interface ChatMessage { + id: string; + role: ChatMessageRole; + content: string; + timestamp: string; +} + +interface ChatbotModalProps { + isOpen: boolean; + onClose: () => void; + messages: ChatMessage[]; + onSend: (content: string) => void; + onRequestVoice?: () => void; + isThinking?: boolean; +} + +const overlayVariants = { + hidden: { opacity: 0 }, + visible: { opacity: 1 }, + exit: { opacity: 0 }, +}; + +const modalVariants = { + hidden: { opacity: 0, y: 60 }, + visible: { opacity: 1, y: 0 }, + exit: { opacity: 0, y: 60 }, +}; + +const dotsVariants = { + animate: { + opacity: [0.2, 1, 0.2], + transition: { + duration: 1.2, + repeat: Infinity, + ease: 'easeInOut' as const, + times: [0, 0.5, 1], + }, + }, +}; + +const VISUALIZER_BARS = [24, 32, 40, 32, 24]; + +const ChatbotModal: React.FC = ({ isOpen, onClose, messages, onSend, onRequestVoice, isThinking }) => { + const [input, setInput] = useState(''); + const scrollRef = useRef(null); + const [voiceActive, setVoiceActive] = useState(false); + + useEffect(() => { + if (!isOpen) { + setInput(''); + setVoiceActive(false); + } + }, [isOpen]); + + useEffect(() => { + if (!isOpen) return; + const container = scrollRef.current; + if (container) { + container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' }); + } + }, [messages, isOpen]); + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + if (!input.trim()) return; + onSend(input.trim()); + setInput(''); + }; + + const groupedMessages = useMemo(() => messages, [messages]); + + return ( + + {isOpen && ( + + + {/* Header */} +
+
+
+ Assistant +
+
+ Pennyzo AI Concierge + Premium Intelligence Desk +
+
+ +
+ + {/* Messages */} +
+ {groupedMessages.map((message) => ( + +
+

{message.content}

+ + {message.timestamp} + +
+
+ ))} + + {isThinking && ( +
+ Thinking + + + + + +
+ )} +
+ + {/* Audio visualization */} + {voiceActive && ( +
+ {VISUALIZER_BARS.map((height, index) => ( + + ))} +
+ )} + + {/* Input */} +
+ + +
+