diff --git a/backend/app.js b/backend/app.js
index 55d5998..d0c4d1c 100644
--- a/backend/app.js
+++ b/backend/app.js
@@ -19,6 +19,9 @@ app.use(cookieParser());
// Enable CORS
const allowedOrigins = [
process.env.FRONTEND_URL || 'http://localhost:5173', // Default for development
+ 'http://127.0.0.1:5173', // Alternative localhost address
+ 'http://localhost:5174', // Alternative Vite port
+ 'http://127.0.0.1:5174', // Alternative Vite port
process.env.FRONTEND_URL_PROD ||
'https://star-wars-character-data-api.vercel.app/',
];
diff --git a/backend/models/userModel.js b/backend/models/userModel.js
index 0bcf412..c38cce3 100644
--- a/backend/models/userModel.js
+++ b/backend/models/userModel.js
@@ -37,14 +37,13 @@ const userSchema = new mongoose.Schema(
// Hash password before saving
userSchema.pre('save', async function (next) {
- if (!this.isModified('password')) return;
+ if (!this.isModified('password')) return next();
try {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
- // No next() call here—the async function resolving tells Mongoose to proceed.
+ next();
} catch (err) {
- // Re-throw the error so it's caught by controller's catch block
- throw err;
+ next(err);
}
});
diff --git a/documents/UI_Refactor.md b/documents/UI_Refactor.md
index cecc7a4..84601e6 100644
--- a/documents/UI_Refactor.md
+++ b/documents/UI_Refactor.md
@@ -321,12 +321,78 @@ Currently, admin features are mixed into the character list. A dedicated admin d
## Implementation Phases
-### Phase 1: Foundation (Week 1)
-
-1. Set up React Router v6
-2. Create new Layout component with persistent navigation
-3. Implement route guards
-4. Standardize button usage
+### Phase 1: Foundation (Week 1) ✅ COMPLETED
+
+**Status**: All foundation work completed successfully
+**Date**: 2026-02-11
+
+#### 1.1 React Router v6 Migration ✅
+- **App.jsx**: Replaced ViewRouter with React Router Routes
+- **Routes implemented**:
+ - `/` - Home (InfoPage)
+ - `/characters` - Character List
+ - `/characters/:id` - Character Detail
+ - `/login` - Login Form
+ - `/register` - Register Form
+ - `/profile` - User Profile (protected)
+ - `/admin` - Admin Dashboard (admin-only)
+ - `/characters/edit/:id` - Edit Character (admin-only)
+ - `/characters/new` - New Character (admin-only)
+
+#### 1.2 Route Guards ✅
+- **ProtectedRoute.jsx**: Authentication guard for user routes
+- **AdminRoute.jsx**: Role-based guard for admin routes
+
+#### 1.3 Layout Component ✅
+- **Layout.jsx**: Persistent layout wrapper with Navigation
+- **Navigation.jsx**: Fixed navigation bar with:
+ - Logo/Home link
+ - Characters link
+ - User menu (Profile, Admin, Logout)
+ - Auth buttons (Login/Register)
+
+#### 1.4 Button Navigation Fixes ✅
+- **Button.jsx**: Already had href prop support
+- **SpaceBtn.jsx**: Added React Router navigation support with useNavigate
+- **ButtonStyleGuide.jsx**: Added for design reference
+
+#### 1.5 Component Updates ✅
+- **InfoPage.jsx**: Updated to use Button href prop instead of Link wrappers
+- **Characters.jsx**: Fixed all navigation, added Return to Home button
+- **CharacterDetail.jsx**: Fixed Back and Edit button navigation
+- **UserProfile.jsx**: Fixed navigation buttons
+- **LoginForm.jsx** & **RegisterForm.jsx**: Updated for React Router
+- **CharactersForm.jsx**: Updated navigation after submission
+
+#### 1.6 Context Updates ✅
+- **AppContext.jsx**: Removed view-based routing state, simplified for auth management
+
+#### 1.7 Backend Fixes ✅
+- **app.js**: Added 127.0.0.1 and port 5174 to CORS allowed origins
+- **userModel.js**: Fixed password hashing middleware (added missing next() calls)
+
+#### 1.8 Cleanup ✅
+- **ViewRouter.jsx**: Deleted (replaced by React Router)
+
+#### Git Commits (18 total)
+1. feat(routing): Add ProtectedRoute component
+2. feat(routing): Add AdminRoute component
+3. feat(layout): Add Layout component with Navigation
+4. feat(layout): Add Navigation component with nav bar
+5. docs(buttons): Add ButtonStyleGuide component
+6. refactor(routing): Migrate from view-based to React Router v6
+7. refactor(views): Update InfoPage for React Router
+8. refactor(context): Update AppContext for React Router
+9. refactor(views): Update UserProfile for React Router
+10. feat(buttons): Enhance SpaceBtn with React Router support
+11. refactor(components): Update Characters list navigation
+12. refactor(components): Update CharacterDetail navigation
+13. refactor(reg-auth): Update LoginForm
+14. refactor(reg-auth): Update RegisterForm
+15. refactor(components): Update CharactersForm
+16. fix(backend): Update CORS configuration
+17. fix(backend): Fix password hashing middleware
+18. remove(routing): Delete ViewRouter component
### Phase 2: Character Management (Week 2)
@@ -392,44 +458,14 @@ Currently, admin features are mixed into the character list. A dedicated admin d
## Next Steps
-1. **Review this plan** and prioritize features
-2. **Create mockups** for key screens (Figma/pen-and-paper)
-3. **Set up React Router** as the foundation
-4. **Implement components** following the design system
-5. **Test with users** and iterate
-
----
-
-_Document Version: 1.0_
-_Created: 2026-02-11_
-_Status: Planning Phase_
-
-- **Current**: Context API is sufficient
-- **Future**: If app grows, consider Zustand or Redux Toolkit
-
----
-
-## Success Metrics
-
-| Metric | Current | Target |
-| ---------------------- | ------- | ------------------ |
-| Time to find character | ~30s | <10s (with search) |
-| Form completion rate | Unknown | >80% |
-| Mobile usability | Poor | Good (responsive) |
-| Accessibility score | Unknown | WCAG 2.1 AA |
-
----
-
-## Next Steps
-
-1. **Review this plan** and prioritize features
-2. **Create mockups** for key screens (Figma/pen-and-paper)
-3. **Set up React Router** as the foundation
-4. **Implement components** following the design system
-5. **Test with users** and iterate
+1. ✅ **Phase 1 Complete**: Foundation (React Router, Layout, Navigation)
+2. **Begin Phase 2**: Character Management (cards, search, filter, pagination)
+3. Review this plan and prioritize Phase 2 features
+4. Test with users and iterate
---
_Document Version: 1.0_
_Created: 2026-02-11_
-_Status: Planning Phase_
+_Updated: 2026-02-11_
+_Status: Phase 1 Complete - Ready for Phase 2_
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index e0e56ad..d14d2b5 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,45 +1,52 @@
+import { Routes, Route, Navigate } from 'react-router-dom';
+import { AppProvider } from './context/AppContext';
+import Layout from './components/layout/Layout';
+import ProtectedRoute from './components/routing/ProtectedRoute';
+import AdminRoute from './components/routing/AdminRoute';
import NebulaCanvas from './components/spaceAtmos/NebulaCanvas';
-import starWarsNeonLogo from './assets/star-wars-neon.svg';
-import ViewRouter from './components/ViewRouter';
-import { AppProvider, useApp } from './context/AppContext';
-import './App.css';
-function Layout() {
- const { background } = useApp();
+// Pages
+import InfoPage from './components/views/InfoPage';
+import Characters from './components/Characters';
+import CharacterDetail from './components/CharacterDetail';
+import CharactersForm from './components/CharactersForm';
+import LoginForm from './components/reg-auth/LoginForm';
+import RegisterForm from './components/reg-auth/RegisterForm';
+import UserProfile from './components/views/UserProfile';
- return (
- <>
-
Coming soon...
+- - {label}: - {' '} - {value} -
- ); -} - -Detail.propTypes = { - label: PropTypes.string.isRequired, - value: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.bool, - ]).isRequired, -}; - -function CharacterDetail({ characterId, onBack, onEdit }) { +function CharacterDetail() { + const { id } = useParams(); const [userRole, setUserRole] = useState('user'); const [character, setCharacter] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); - // console.log('User role in CharacterDetail:', userRole); - // Fetch character details and user role on mount - // using the same logic as in Characters.jsx useEffect(() => { const fetchCharacterDetails = async () => { try { - setLoading(true); // Start loading - - const role = getUserRole(); // Returns 'user' by default if no token + setLoading(true); + const role = getUserRole(); setUserRole(role); - - const data = await apiRequest('GET', `/characters/${characterId}`); + const data = await apiRequest('GET', `/characters/${id}`); setCharacter(data); - } catch (err) { - console.error('Fetch error:', err.message); - setError('Failed to load character details.'); + } catch { + setError('Failed to load character.'); } finally { - setLoading(false); // End loading + setLoading(false); } }; - fetchCharacterDetails(); - }, [characterId]); - if (error) { - return- {userRole === 'admin' - ? 'As an admin, you can manage the characters below.' - : 'As a user, you can view the available characters.'} -
- {/* Header row */} -+ Height: {character.height} cm +
++ Species: {character.species} +
++ Home world: {character.homeworld} +
++ Affiliation: {character.affiliation} +
++ Force Rating: {character.stats?.forceRating} +
++ Combat Skill: {character.stats?.combatSkill} +
++ Piloting Ability: {character.stats?.pilotingAbility} +
++ Diplomacy Rating: {character.stats?.diplomacyRating} +
++ Is Jedi: {character.isJedi ? 'Yes' : 'No'} +
++ Master: {character.master || 'None'} +
++ Apprentices: {character.apprentices?.join(', ') || 'None'} +
++ Weapons: {character.weapons?.join(', ') || 'None'} +
++ Vehicles: {character.vehicles?.join(', ') || 'None'} +
++ Notable Achievements: {character.notableAchievements?.join(', ') || 'None'} +
{error}
-{error}
} -- {userRole === 'admin' - ? 'As an admin, you can manage the characters below.' - : 'As a user, you can view the available characters.'} -
- +{message}
} + {userRole === 'admin' && ( - <> -No characters found.
+No characters found.
) : ( -