Design for feature-sliced architecture, 8 bug fixes, and glass-morphism UI redesign. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.4 KiB
8.4 KiB
Frontend Major Refactor — Design Document
Date: 2026-06-01
Scope: /mnt/code/bete/frontend/ — React + Vite + Tailwind
Stack: React 18, Vite, TailwindCSS, TanStack Query, lucide-react
Problem Statement
package.jsonhilang — project tidak bisapnpm installApp.tsx285 baris monolithic (audio, socket, state, layout semua satu file)useMemodipakai untuk side effect (LivePanel:47) — anti-pattern React- Shared
ArrayBufferbug saat kirim PCM ke WebSocket (App:166) ws/client.tsduplikat socket logic denganhooks/useDashboardSocket.ts- Async handler tanpa await (MessageCard:88)
- UI terlihat "jelek" — flat dark theme tanpa depth/visual interest
- Mobile UX buruk — tab bar di atas, tidak ada sidebar drawer
Section 1: Arsitektur — Feature-Sliced Directory
frontend/
├── index.html
├── package.json # [NEW] Lengkap dengan semua deps
├── vite.config.ts
├── tailwind.config.js
├── postcss.config.js
├── tsconfig.json
└── src/
├── main.tsx # React entry + QueryClient
├── styles.css # Tailwind + design tokens
├── App.tsx # Thin shell (~60 baris)
│
├── entities/ # Domain types
│ ├── message/types.ts
│ ├── guild/types.ts
│ ├── voice/types.ts
│ ├── media/types.ts
│ └── ui/types.ts
│
├── shared/ # Cross-cutting utilities
│ ├── api/client.ts # HTTP client + typed endpoints
│ ├── ws/socket.ts # WebSocket connection manager
│ ├── ws/events.ts # Typed event map + dispatcher
│ ├── hooks/useAudioPlayback.ts
│ ├── hooks/useAudioTransmit.ts
│ ├── hooks/useLocalStorage.ts
│ └── ui/ # UI primitives
│ ├── button.tsx
│ ├── card.tsx
│ ├── badge.tsx
│ ├── input.tsx
│ ├── select.tsx
│ ├── tabs.tsx
│ └── scroll-area.tsx
│
├── features/ # Feature-specific logic + presentation
│ ├── live/
│ │ ├── hooks/useVoiceControl.ts
│ │ ├── hooks/useMediaControl.ts
│ │ ├── index.tsx # LivePanel
│ │ ├── components/VoiceConnectionCard.tsx
│ │ ├── components/AudioVisualizer.tsx
│ │ ├── components/ActiveSpeakers.tsx
│ │ ├── components/NowPlaying.tsx
│ │ ├── components/MusicSubPanel.tsx
│ │ ├── components/ScreenSubPanel.tsx
│ │ └── components/RecordingsSubPanel.tsx
│ ├── messages/
│ │ ├── hooks/useMessages.ts
│ │ ├── index.tsx # MessagesPanel
│ │ ├── components/MessageFeed.tsx
│ │ ├── components/MessageCard.tsx
│ │ └── components/ImageGrid.tsx
│ ├── analytics/
│ │ ├── hooks/useAnalytics.ts
│ │ ├── index.tsx # AnalyticsPanel
│ │ └── components/ # (charts, tables kept as-is)
│ └── auth/
│ └── index.tsx # AuthOverlay
│
└── widgets/ # Composite layouts
├── DashboardLayout.tsx
├── Header.tsx
└── Sidebar.tsx
Key Architectural Decisions
App.tsx= hanya layout shell + providers. Semua hooks pindah kefeatures/.- Socket = satu instance di
shared/ws/socket.ts. Features subscribe via typed event bus. - Entities = pure types, zero logic.
- Features = self-contained (hooks + components). Tidak cross-import antar feature.
- Widgets = layout compositions (sidebar, header, dashboard shell).
Section 2: Bug Fixes
| # | Bug | Location | Fix |
|---|---|---|---|
| 1 | useMemo untuk async fetch (anti-pattern) |
LivePanel.tsx:47 |
Ganti ke useEffect + useCallback |
| 2 | Shared ArrayBuffer dikirim ke WS |
App.tsx:166 |
.slice() sebelum send |
| 3 | Missing useEffect deps | App.tsx:187 |
Add proper dependency arrays |
| 4 | Unstable keys (i sebagai fallback) |
LivePanel.tsx:246 |
Gunakan s.userId ?? 'unknown-${i}' |
| 5 | Async handler tanpa await | MessageCard.tsx:88 |
onReanalyze → Promise<void>, di-await |
| 6 | monitorGuild recompute tiap render |
App.tsx:65 |
Pakai useMemo |
| 7 | Socket localStorage tanpa validasi | useUIState.ts:9 |
Schema validation sebelum parse |
| 8 | Duplikat socket (ws/client.ts vs hooks/useDashboardSocket.ts) |
Global | Hapus ws/client.ts, satu socket di shared/ws/socket.ts |
Section 3: UI Redesign — Glass-morphism Modern
Color Tokens
--background: 222 47% 8%; /* slightly darker */
--foreground: 210 40% 98%;
--card: 222 47% 12% / 0.7; /* semi-transparent */
--card-border: 222 47% 25% / 0.4;/* translucent border */
--primary: 199 89% 52%; /* brighter cyan-blue */
--accent: 217 33% 20%;
--muted: 217 33% 20%;
--radius: 0.85rem;
Visual Changes
- Background: Gradient mesh (dark → dark-purple → dark) dengan subtle noise overlay
- Cards:
backdrop-blur-xl+ semi-transparent bg + subtle glow border - Sidebar: Expandable — icon-only (w-16) ↔ full (w-64) dengan smooth transition
- Mobile: Bottom tab bar (bukan top tabs), slide-in sidebar
- Typography: Inter tetap, heading scale lebih besar, weight lebih variatif
- Micro-interactions:
transition-all duration-200, hover scale1.01, focus rings - Audio Visualizer: CSS animated bars (bukan static levels map)
- Message cards: Rounded-xl, subtle shadow, AI badge dengan color coding yang lebih jelas
- Charts: Recharts-based (existing), tapi dengan color scheme yang matching theme
Responsive Breakpoints
| Breakpoint | Layout |
|---|---|
< 768px |
Bottom tab bar, no sidebar, full-width content |
768px–1024px |
Collapsed sidebar (icon-only), full content |
> 1024px |
Full sidebar (w-64), spaced content |
Section 4: Error Handling
- Error Boundaries: Setiap feature punya error boundary (existing
AnalyticsErrorBoundarypattern) - API Errors: Global error toast via
shared/ui/Toastcomponent - Socket Errors: Auto-reconnect dengan exponential backoff (existing pattern, diperbaiki)
- Loading States: Skeleton loaders (bukan text "Loading...") untuk semua data panels
Section 5: Data Flow
Browser → shared/ws/socket.ts → shared/ws/events.ts (dispatch)
↓
features/* subscribe via typed handlers
↓
features/*/hooks/ (React Query / useState)
↓
features/*/components (render)
↓
widgets/ (layout shell)
- REST API: React Query hooks di
features/*/hooks/ - WebSocket Events: Event bus di
shared/ws/events.ts, hooks subscribe ke events - UI State:
localStorage+shared/ws/socket.tssync (existing pattern, dengan validasi)
Section 6: Testing Strategy
- Unit: Hooks testing dengan
@testing-library/react— socket mocking - Integration: Component render tests untuk panels
- E2E: Tidak termasuk scope initial refactor (future enhancement)
Section 7: Migration Plan
Phase 1: Foundation
package.jsonlengkaptsconfig.json+vite.config.tsverifiedshared/structure + UI primitivesentities/types extracted
Phase 2: Bug Fixes + Hooks Extraction
- Extract hooks dari
App.tsx→features/*/hooks/ - Fix semua 8 bugs yang teridentifikasi
- Single socket instance di
shared/ws/socket.ts App.tsxthin shell
Phase 3: UI Polish
- Design tokens baru (glass-morphism)
- Sidebar redesign (expandable + mobile drawer)
- Audio visualizer animated
- Message card redesign
- Loading skeletons
- Error boundaries + toast
Phase 4: Verification
pnpm run typecheck— zero errorspnpm run lint— zero warnings- App runs + all 3 tabs functional
- WebSocket connects + events work
- Mobile responsive verified