docs: add comprehensive frontend refactoring analysis and Phase 1 roadmap to TODO.md
This commit is contained in:
374
docs/TODO.md
374
docs/TODO.md
@@ -360,6 +360,380 @@ See the complete security audit report generated by nodejs-security-auditor agen
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## ⚛️ FRONTEND REFACTORING (2025-11-20)
|
||||||
|
|
||||||
|
**Analysis Status:** Comprehensive React architecture review completed
|
||||||
|
**Code Analyzed:** 27 JSX components, ~4000 lines of code
|
||||||
|
**Refactoring Potential:** ~35% code reduction possible
|
||||||
|
**Recommended Phase:** Phase 1 (Quick Wins) - START IMMEDIATELY
|
||||||
|
|
||||||
|
### 📊 Current State Analysis
|
||||||
|
|
||||||
|
**Strengths:**
|
||||||
|
- ✅ Functional code, all features working
|
||||||
|
- ✅ Good folder structure (pages, components, hooks)
|
||||||
|
- ✅ Existing reusable components (Avatar, Layout, HeatsBanner)
|
||||||
|
|
||||||
|
**Issues:**
|
||||||
|
- ⚠️ **~40% code duplication** (especially in chat components)
|
||||||
|
- ⚠️ **Very large components** (EventChatPage: 761 lines, MatchChatPage: 567 lines, ProfilePage: 558 lines)
|
||||||
|
- ⚠️ **Lack of abstraction** for repeating patterns
|
||||||
|
- ⚠️ **Inline components** and modals polluting main components
|
||||||
|
- ⚠️ **Duplicated Socket.IO logic** across chat pages
|
||||||
|
|
||||||
|
**Metrics:**
|
||||||
|
```
|
||||||
|
Before Refactoring:
|
||||||
|
- Total LOC: ~4000
|
||||||
|
- Duplicated code: ~40%
|
||||||
|
- Largest component: 761 lines
|
||||||
|
- Reusable components: 8
|
||||||
|
- Custom hooks: 1
|
||||||
|
|
||||||
|
After Refactoring (projected):
|
||||||
|
- Total LOC: ~2600 (-35%)
|
||||||
|
- Duplicated code: ~10%
|
||||||
|
- Largest component: ~350 lines
|
||||||
|
- Reusable components: 25+
|
||||||
|
- Custom hooks: 6+
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🎯 PHASE 1: QUICK WINS (RECOMMENDED TO START)
|
||||||
|
|
||||||
|
**Effort:** 1 week (15 hours)
|
||||||
|
**Impact:** High - reduces codebase by ~30%, eliminates major duplication
|
||||||
|
**Priority:** HIGH - should be done before adding new features
|
||||||
|
|
||||||
|
#### 1. Alert/Message Components (30 min) ⭐⭐⭐
|
||||||
|
|
||||||
|
**Create:**
|
||||||
|
- `components/common/Alert.jsx` - Unified success/error/warning/info alerts
|
||||||
|
- Replace 10+ inline alert boxes in ProfilePage, RegisterPage, LoginPage, etc.
|
||||||
|
|
||||||
|
**Files to create:**
|
||||||
|
```jsx
|
||||||
|
// components/common/Alert.jsx
|
||||||
|
const Alert = ({ type = 'info', message, icon: Icon }) => {
|
||||||
|
// Unified alert component with 4 variants (success, error, warning, info)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact:** -50 lines of duplicated alert code
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 2. Loading Components (20 min) ⭐⭐⭐
|
||||||
|
|
||||||
|
**Create:**
|
||||||
|
- `components/common/LoadingSpinner.jsx` - Centralized loading spinner
|
||||||
|
- `components/common/LoadingButton.jsx` - Button with loading state
|
||||||
|
|
||||||
|
**Files to create:**
|
||||||
|
```jsx
|
||||||
|
// components/common/LoadingSpinner.jsx
|
||||||
|
const LoadingSpinner = ({ size = 'md', text, fullPage = false }) => {
|
||||||
|
// Unified loading spinner (small, medium, large, full-page variants)
|
||||||
|
};
|
||||||
|
|
||||||
|
// components/common/LoadingButton.jsx
|
||||||
|
const LoadingButton = ({ loading, children, loadingText, ...props }) => {
|
||||||
|
// Button with built-in loading state
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact:** -40 lines of duplicated loading UI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 3. EventCard Extraction (30 min) ⭐⭐⭐
|
||||||
|
|
||||||
|
**Create:**
|
||||||
|
- `components/events/EventCard.jsx` - Extract inline component from EventsPage
|
||||||
|
|
||||||
|
**Files affected:**
|
||||||
|
- `pages/EventsPage.jsx` - Remove inline EventCard (lines 120-192)
|
||||||
|
|
||||||
|
**Impact:** -72 lines, better component organization
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4. Form Input Components (2 hours) ⭐⭐⭐⭐⭐
|
||||||
|
|
||||||
|
**Create:**
|
||||||
|
- `components/common/FormInput.jsx` - Text/email/password/url inputs with icons
|
||||||
|
- `components/common/FormSelect.jsx` - Select dropdowns with icons
|
||||||
|
|
||||||
|
**Files affected:**
|
||||||
|
- `pages/ProfilePage.jsx` - 15+ input fields → use FormInput/FormSelect
|
||||||
|
- `pages/RegisterPage.jsx` - Registration form inputs
|
||||||
|
- `pages/LoginPage.jsx` - Login form inputs
|
||||||
|
|
||||||
|
**Example transformation:**
|
||||||
|
```jsx
|
||||||
|
// BEFORE (15 lines)
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-2">First Name</label>
|
||||||
|
<input type="text" name="firstName" value={...} onChange={...} className="w-full px-3 py-2..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// AFTER (5 lines)
|
||||||
|
<FormInput label="First Name" name="firstName" value={profileData.firstName} onChange={handleProfileChange} />
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact:** -150 lines of repetitive form code
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 5. Modal Components (2 hours) ⭐⭐⭐⭐⭐
|
||||||
|
|
||||||
|
**Create:**
|
||||||
|
- `components/modals/Modal.jsx` - Generic modal wrapper
|
||||||
|
- `components/modals/ConfirmationModal.jsx` - Reusable confirmation dialog
|
||||||
|
|
||||||
|
**Files affected:**
|
||||||
|
- `pages/EventChatPage.jsx`:
|
||||||
|
- Leave Event Modal (lines 682-729) → use ConfirmationModal
|
||||||
|
- Edit Heats Modal (lines 732-754) → use Modal
|
||||||
|
- Future: Any new modals use these components
|
||||||
|
|
||||||
|
**Example transformation:**
|
||||||
|
```jsx
|
||||||
|
// BEFORE (47 lines of inline modal JSX)
|
||||||
|
{showLeaveModal && (
|
||||||
|
<div className="fixed inset-0 bg-black bg-opacity-50...">
|
||||||
|
{/* 40+ lines */}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
// AFTER (8 lines)
|
||||||
|
<ConfirmationModal
|
||||||
|
isOpen={showLeaveModal}
|
||||||
|
onClose={() => setShowLeaveModal(false)}
|
||||||
|
onConfirm={handleLeaveEvent}
|
||||||
|
title="Leave Event?"
|
||||||
|
description={`Are you sure you want to leave ${event.name}?`}
|
||||||
|
confirmText="Leave Event"
|
||||||
|
isLoading={isLeaving}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact:** -70 lines of modal boilerplate, reusable for future features
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 6. Chat Components (3 hours) ⭐⭐⭐⭐⭐
|
||||||
|
|
||||||
|
**Create:**
|
||||||
|
- `components/chat/ChatMessageList.jsx` - Message container with scroll
|
||||||
|
- `components/chat/ChatMessage.jsx` - Individual message bubble
|
||||||
|
- `components/chat/ChatInput.jsx` - Message input with send button
|
||||||
|
|
||||||
|
**Files affected:**
|
||||||
|
- `pages/EventChatPage.jsx` (lines 594-666) - Use chat components
|
||||||
|
- `pages/MatchChatPage.jsx` (lines 354-549) - Use chat components
|
||||||
|
|
||||||
|
**Duplication eliminated:**
|
||||||
|
- Message rendering logic: ~40 lines × 2 = 80 lines
|
||||||
|
- Message input form: ~20 lines × 2 = 40 lines
|
||||||
|
- Total: ~120 lines of duplicated code
|
||||||
|
|
||||||
|
**Example transformation:**
|
||||||
|
```jsx
|
||||||
|
// BEFORE (66 lines in EventChatPage + 60 lines in MatchChatPage)
|
||||||
|
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
||||||
|
{messages.map((message) => (
|
||||||
|
<div className={...}>
|
||||||
|
{/* 30+ lines of message rendering */}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// AFTER (3 lines!)
|
||||||
|
<ChatMessageList
|
||||||
|
messages={messages}
|
||||||
|
currentUserId={user.id}
|
||||||
|
messagesEndRef={messagesEndRef}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact:** -120 lines of duplicated chat UI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📦 Phase 1 Summary
|
||||||
|
|
||||||
|
**Total effort:** 15 hours (1 week)
|
||||||
|
**Lines of code removed:** ~450 lines
|
||||||
|
**Code reduction:** ~30%
|
||||||
|
**Components created:** 11 new reusable components
|
||||||
|
|
||||||
|
**Immediate benefits:**
|
||||||
|
1. ✅ Eliminates major code duplication
|
||||||
|
2. ✅ Reduces ProfilePage from 558 → ~400 lines (-28%)
|
||||||
|
3. ✅ Reduces EventChatPage from 761 → ~550 lines (-28%)
|
||||||
|
4. ✅ Reduces MatchChatPage from 567 → ~400 lines (-29%)
|
||||||
|
5. ✅ Future features faster to implement (use existing components)
|
||||||
|
6. ✅ Easier to maintain (change in one place affects all uses)
|
||||||
|
7. ✅ Better testability (small components easier to test)
|
||||||
|
|
||||||
|
**New folder structure after Phase 1:**
|
||||||
|
```
|
||||||
|
frontend/src/
|
||||||
|
├── components/
|
||||||
|
│ ├── common/
|
||||||
|
│ │ ├── Alert.jsx ⭐ NEW
|
||||||
|
│ │ ├── Avatar.jsx (existing)
|
||||||
|
│ │ ├── FormInput.jsx ⭐ NEW
|
||||||
|
│ │ ├── FormSelect.jsx ⭐ NEW
|
||||||
|
│ │ ├── LoadingSpinner.jsx ⭐ NEW
|
||||||
|
│ │ ├── LoadingButton.jsx ⭐ NEW
|
||||||
|
│ │ ├── PasswordStrengthIndicator.jsx (existing)
|
||||||
|
│ │ └── VerificationBanner.jsx (existing)
|
||||||
|
│ ├── chat/ ⭐ NEW FOLDER
|
||||||
|
│ │ ├── ChatMessageList.jsx ⭐ NEW
|
||||||
|
│ │ ├── ChatMessage.jsx ⭐ NEW
|
||||||
|
│ │ └── ChatInput.jsx ⭐ NEW
|
||||||
|
│ ├── events/ ⭐ NEW FOLDER
|
||||||
|
│ │ └── EventCard.jsx ⭐ NEW
|
||||||
|
│ ├── modals/ ⭐ NEW FOLDER
|
||||||
|
│ │ ├── Modal.jsx ⭐ NEW
|
||||||
|
│ │ └── ConfirmationModal.jsx ⭐ NEW
|
||||||
|
│ ├── heats/
|
||||||
|
│ ├── layout/
|
||||||
|
│ ├── pwa/
|
||||||
|
│ └── WebRTCWarning.jsx (existing)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🔄 PHASE 2: Custom Hooks (Future - After Phase 1)
|
||||||
|
|
||||||
|
**Effort:** 1 week (12 hours)
|
||||||
|
**Impact:** High - separates business logic from UI
|
||||||
|
**Priority:** MEDIUM - do after Phase 1 is complete
|
||||||
|
|
||||||
|
#### Tasks:
|
||||||
|
1. **useForm Hook** (1h) - Generic form state management
|
||||||
|
2. **useEventChat Hook** (3h) - Extract Socket.IO logic from EventChatPage
|
||||||
|
3. **useMatchChat Hook** (2h) - Extract Socket.IO logic from MatchChatPage
|
||||||
|
4. **useInfiniteScroll Hook** (45min) - Reusable infinite scroll logic
|
||||||
|
|
||||||
|
**Impact:** -200 lines, better separation of concerns
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🎨 PHASE 3: Advanced Components (Future)
|
||||||
|
|
||||||
|
**Effort:** 1 week (10 hours)
|
||||||
|
**Impact:** Medium - completes component library
|
||||||
|
**Priority:** LOW - nice to have, do after Phase 1 & 2
|
||||||
|
|
||||||
|
#### Tasks:
|
||||||
|
1. **ParticipantsSidebar** (2h) - Extract from EventChatPage
|
||||||
|
2. **UserListItem** (1h) - Reusable user list entry
|
||||||
|
3. **HeatBadges** (30min) - Reusable heat display component
|
||||||
|
4. **WebRTC Components** (2h) - File transfer UI components
|
||||||
|
|
||||||
|
**Impact:** -150 lines, fully modular codebase
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📋 REFACTORING CHECKLIST - PHASE 1 (Quick Wins)
|
||||||
|
|
||||||
|
**Week 1 - Day 1-2:**
|
||||||
|
- [ ] Create `components/common/Alert.jsx`
|
||||||
|
- [ ] Create `components/common/LoadingSpinner.jsx`
|
||||||
|
- [ ] Create `components/common/LoadingButton.jsx`
|
||||||
|
- [ ] Replace all inline alerts in ProfilePage, LoginPage, RegisterPage
|
||||||
|
- [ ] Replace all inline loading spinners across pages
|
||||||
|
- [ ] Test: Verify all pages still work correctly
|
||||||
|
|
||||||
|
**Week 1 - Day 3:**
|
||||||
|
- [ ] Create `components/events/EventCard.jsx`
|
||||||
|
- [ ] Extract EventCard from EventsPage.jsx
|
||||||
|
- [ ] Test: Events page renders correctly
|
||||||
|
|
||||||
|
**Week 1 - Day 4-5:**
|
||||||
|
- [ ] Create `components/common/FormInput.jsx`
|
||||||
|
- [ ] Create `components/common/FormSelect.jsx`
|
||||||
|
- [ ] Refactor ProfilePage to use FormInput/FormSelect
|
||||||
|
- [ ] Refactor RegisterPage to use FormInput/FormSelect
|
||||||
|
- [ ] Refactor LoginPage to use FormInput/FormSelect
|
||||||
|
- [ ] Test: All forms submit correctly, validation works
|
||||||
|
|
||||||
|
**Week 1 - Day 6:**
|
||||||
|
- [ ] Create `components/modals/Modal.jsx`
|
||||||
|
- [ ] Create `components/modals/ConfirmationModal.jsx`
|
||||||
|
- [ ] Refactor EventChatPage modals
|
||||||
|
- [ ] Test: Modals open/close correctly
|
||||||
|
|
||||||
|
**Week 1 - Day 7:**
|
||||||
|
- [ ] Create `components/chat/ChatMessageList.jsx`
|
||||||
|
- [ ] Create `components/chat/ChatMessage.jsx`
|
||||||
|
- [ ] Create `components/chat/ChatInput.jsx`
|
||||||
|
- [ ] Refactor EventChatPage to use chat components
|
||||||
|
- [ ] Refactor MatchChatPage to use chat components
|
||||||
|
- [ ] Test: Chat functionality works in both pages
|
||||||
|
- [ ] Final testing: Full regression test of all pages
|
||||||
|
|
||||||
|
**Completion criteria:**
|
||||||
|
- ✅ All new components created and tested
|
||||||
|
- ✅ No regressions in existing functionality
|
||||||
|
- ✅ Code review completed
|
||||||
|
- ✅ ~450 lines of code removed
|
||||||
|
- ✅ Commit: "refactor(frontend): Phase 1 - create reusable components and eliminate duplication"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 💡 ADDITIONAL RECOMMENDATIONS
|
||||||
|
|
||||||
|
#### Performance Optimizations (Future):
|
||||||
|
```jsx
|
||||||
|
// Memoization for expensive components
|
||||||
|
const ChatMessage = React.memo(({ message, isOwn }) => { /* ... */ });
|
||||||
|
|
||||||
|
// Lazy loading for modals
|
||||||
|
const EditHeatsModal = React.lazy(() => import('./modals/EditHeatsModal'));
|
||||||
|
|
||||||
|
// useMemo for expensive calculations
|
||||||
|
const filteredUsers = useMemo(() => {
|
||||||
|
return users.filter(u => !shouldHideUser(u.userId));
|
||||||
|
}, [users, hideMyHeats]);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Code Splitting (Future):
|
||||||
|
```jsx
|
||||||
|
// routes/index.jsx - Lazy load heavy pages
|
||||||
|
const EventChatPage = lazy(() => import('../pages/EventChatPage'));
|
||||||
|
const MatchChatPage = lazy(() => import('../pages/MatchChatPage'));
|
||||||
|
```
|
||||||
|
|
||||||
|
#### TypeScript Migration (Future):
|
||||||
|
Consider migrating to TypeScript for:
|
||||||
|
- Better type safety
|
||||||
|
- IntelliSense in IDE
|
||||||
|
- Easier refactoring
|
||||||
|
- Fewer runtime bugs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📊 ESTIMATED ROI
|
||||||
|
|
||||||
|
**Investment:** 15 hours (Phase 1)
|
||||||
|
**Returns:**
|
||||||
|
- Immediate: 30% less code to maintain (~450 lines removed)
|
||||||
|
- Short-term: 3-4 hours saved per new feature (reusable components)
|
||||||
|
- Long-term: 50% faster development of chat/form features
|
||||||
|
|
||||||
|
**Payback period:** ~1 week (time saved on next feature)
|
||||||
|
**Recommendation:** ⭐⭐⭐⭐⭐ **START PHASE 1 IMMEDIATELY**
|
||||||
|
|
||||||
|
The refactoring will pay for itself after implementing just 1-2 new features, and will make the codebase significantly more maintainable.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### 📋 FUTURE UX/UI IMPROVEMENTS
|
### 📋 FUTURE UX/UI IMPROVEMENTS
|
||||||
|
|
||||||
**Dashboard Page (Post-Login):**
|
**Dashboard Page (Post-Login):**
|
||||||
|
|||||||
Reference in New Issue
Block a user