Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions apps/frontend/src/app/[locale]/courses/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,30 @@ export default function CoursesPage() {
return (
<ProtectedRoute>
<main className="max-w-4xl mx-auto p-8">
<h1 className="text-3xl font-bold mb-6 text-gray-900 dark:text-white">{t('title')}</h1>
{/* List semantics so screen readers announce item count */}
<ul className="grid gap-4 list-none p-0">
{courses.map((course) => (
<li
key={course.id}
className="border border-gray-200 dark:border-gray-700 rounded-lg p-6 bg-white dark:bg-gray-900 hover:shadow-md transition-shadow"
<h1 className="text-3xl font-bold mb-6 text-gray-900 dark:text-white">{t('title')}</h1>
{/* List semantics so screen readers announce item count */}
<ul className="grid gap-4 list-none p-0">
{courses.map((course) => (
<li
key={course.id}
className="border border-gray-200 dark:border-gray-700 rounded-lg p-6 bg-white dark:bg-gray-900 hover:shadow-md transition-shadow"
>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{course.title}</h2>
<p className="text-gray-700 dark:text-gray-400 mt-1">
<div className="grid gap-4">
{courses.map((course) => (
<div
key={course.id}
className="border border-gray-200 dark:border-gray-700 rounded-lg p-6 bg-white dark:bg-gray-900 hover:shadow-md dark:hover:shadow-gray-800 transition-shadow"
>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{course.title}</h2>
<p className="text-gray-500 dark:text-gray-400 mt-1">
{t(`levels.${course.level}`)} · {course.duration}
</p>
<Link
href={`/courses/${course.id}`}
aria-label={t('viewCourseLabel', { title: course.title })}
className="mt-3 inline-block text-blue-700 dark:text-blue-400 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 rounded"
>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{course.title}</h2>
<p className="text-gray-700 dark:text-gray-400 mt-1">
Expand All @@ -42,5 +59,6 @@ export default function CoursesPage() {
}
</div>
</main>
</ProtectedRoute>
);
}
46 changes: 27 additions & 19 deletions apps/frontend/src/app/[locale]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,33 @@ export default function HomePage() {
return (
<ProtectedRoute>
<main className="min-h-screen flex flex-col items-center justify-center p-8">
<h1 className="text-4xl font-bold mb-4 text-gray-900 dark:text-white">{t('title')}</h1>
<p className="text-lg text-gray-700 dark:text-gray-300 mb-8 text-center max-w-xl">
{t('description')}
</p>
<div className="flex gap-4 flex-wrap justify-center">
<Link
href="/courses"
className="px-6 py-3 bg-blue-700 text-white rounded-lg hover:bg-blue-800 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
>
{t('browseCourses')}
</Link>
<Link
href="/auth/register"
className="px-6 py-3 border-2 border-blue-700 text-blue-700 dark:text-blue-400 dark:border-blue-400 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-950 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
>
{t('getStarted')}
</Link>
</div>
</main>
<h1 className="text-4xl font-bold mb-4 text-gray-900 dark:text-white">{t('title')}</h1>
<p className="text-lg text-gray-700 dark:text-gray-300 mb-8 text-center max-w-xl">
{t('description')}
</p>
<div className="flex gap-4 flex-wrap justify-center">
<Link
href="/courses"
className="px-6 py-3 bg-blue-700 text-white rounded-lg hover:bg-blue-800 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
>
{t('browseCourses')}
</Link>
<Link
href="/auth/register"
className="px-6 py-3 border-2 border-blue-700 text-blue-700 dark:text-blue-400 dark:border-blue-400 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-950 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
>
<p className="text-lg text-gray-600 dark:text-gray-400 mb-8 text-center max-w-xl">
{t('description')}
</p>
<div className="flex gap-4">
<Link href="/courses" className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
{t('browseCourses')}
</Link>
<Link href="/auth/register" className="px-6 py-3 border border-blue-600 text-blue-600 dark:text-blue-400 dark:border-blue-400 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-950 transition-colors">
{t('getStarted')}
</Link>
</div>
</main>
</ProtectedRoute>
);
}
12 changes: 12 additions & 0 deletions apps/frontend/src/lib/auth-context.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client';

import React, { createContext, useContext, useReducer, useEffect, ReactNode } from 'react';

interface AuthUser {
Expand All @@ -21,6 +23,7 @@ type AuthAction =
| { type: 'LOGOUT' }
| { type: 'SET_USER'; payload: AuthUser };

const authReducer = (state: AuthState, action: AuthAction): AuthState => {
const decodeJWT = (token: string) => {
try {
const payload = JSON.parse(atob(token.split('.')[1]));
Expand All @@ -45,6 +48,15 @@ const decodeJWT = (token: string) => {
}
};

const decodeJWT = (token: string) => {
try {
const payload = JSON.parse(atob(token.split('.')[1]));
return payload;
} catch {
return null;
}
};

const AuthContext = createContext<{
state: AuthState;
dispatch: React.Dispatch<AuthAction>;
Expand Down
Loading