Skip to content

Commit

Permalink
Merge pull request #312 from claushaas/staging
Browse files Browse the repository at this point in the history
add pages for saved, completed and favorited lessons
  • Loading branch information
claushaas authored Jul 22, 2024
2 parents d18695b + 37a4054 commit cc7e69f
Show file tree
Hide file tree
Showing 11 changed files with 588 additions and 10 deletions.
3 changes: 2 additions & 1 deletion app/components/navigation-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ export function NavigateBar({userData}: {readonly userData: TypeUserSession | un
<NavigationMenu.Content className='data-[motion=from-start]:animate-enterFromLeft data-[motion=from-end]:animate-enterFromRight data-[motion=to-start]:animate-exitToLeft data-[motion=to-end]:animate-exitToRight px-4 py-2 bg-mauve-3 dark:bg-mauvedark-3 absolute top-0 right-0 rounded-md max-xs:w-[calc(100vw_-_calc(100vw_*_5_/_100))] w-72'>
<ul className='grid grid-cols-2 gap-3'>
{pathname !== '/' && <NavigateLink to='/'>Home</NavigateLink>}
{userData?.roles?.includes('admin') && pathname !== '/admin' && <NavigateLink to='/admin'>Admin</NavigateLink>}
{userData?.roles?.includes('admin') && !pathname.startsWith('/admin') && <NavigateLink to='/admin'>Admin</NavigateLink>}
{pathname !== '/courses' && <NavigateLink to='/courses'>Cursos</NavigateLink>}
{!pathname.startsWith('/profile') && userData?.id && <NavigateLink to='/profile'>Minha Área</NavigateLink>}
{userData?.id && pathname !== '/logout' && <NavigateLink to='/logout'>Sair</NavigateLink>}
</ul>
</NavigationMenu.Content>
Expand Down
4 changes: 2 additions & 2 deletions app/routes/admin.comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export const loader = defineLoader(({request}: LoaderFunctionArgs) => ({

export default function Comments() {
return (
<main>
<div>
<h1>Comments</h1>
</main>
</div>
);
}
4 changes: 2 additions & 2 deletions app/routes/admin.courses_.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default function Courses() {
} = useLoaderData<typeof loader>();

return (
<main>
<>
<SuccessOrErrorMessage success={success} error={error}/>

<div className='flex items-center gap-5'>
Expand All @@ -105,6 +105,6 @@ export default function Courses() {
<AdminEntityCard key={course?.id} course={course ?? {}} to={`./${course?.slug}`}/>
))}
</div>
</main>
</>
);
}
6 changes: 3 additions & 3 deletions app/routes/courses.$course-slug.$module-slug.$lesson-slug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const loader = defineLoader(async ({request, params}: LoaderFunctionArgs)
const userId = (userSession.data as TUser).id;

const {data: lesson} = new LessonService().getBySlugFromCache(moduleSlug!, lessonSlug!, userSession.data as TUser);
const {data: module} = new ModuleService().getBySlugFromCache(courseSlug!, moduleSlug!, userSession.data as TUser);
const {data: module} = new ModuleService().getBySlugFromCache(courseSlug!, moduleSlug!, userSession.data as TUser, []);
const {data: course} = new CourseService().getBySlugFromCache(courseSlug!, userSession.data as TUser);
const userLessonActivity = new LessonActivityService().getLessonActivityForUser(lessonSlug!, userId);

Expand Down Expand Up @@ -169,7 +169,7 @@ export default function Lesson() {

<Tooltip.Portal>
<Tooltip.Content sideOffset={5} className='bg-mauve-5 dark:bg-mauvedark-5 px-4 py-3 rounded-2xl shadow-sm shadow-mauve-8 dark:shadow-mauvedark-8'>
{userLessonActivity.data?.completed ? <p>Remover Aula Salva</p> : <p>Salvar Aula</p>}
{userLessonActivity.data?.saved ? <p>Remover Aula Salva</p> : <p>Salvar Aula</p>}
<Tooltip.Arrow className='fill-mauve-5 stroke-none'/>
</Tooltip.Content>
</Tooltip.Portal>
Expand All @@ -186,7 +186,7 @@ export default function Lesson() {

<Tooltip.Portal>
<Tooltip.Content sideOffset={5} className='bg-mauve-5 dark:bg-mauvedark-5 px-4 py-3 rounded-2xl shadow-sm shadow-mauve-8 dark:shadow-mauvedark-8'>
{userLessonActivity.data?.completed ? <p>Remover Aula Favorita</p> : <p>Favoritar Aula</p>}
{userLessonActivity.data?.favorited ? <p>Remover Aula Favorita</p> : <p>Favoritar Aula</p>}
<Tooltip.Arrow className='fill-mauve-5 stroke-none'/>
</Tooltip.Content>
</Tooltip.Portal>
Expand Down
1 change: 1 addition & 0 deletions app/routes/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export default function Login() {
return (
<>
<NavigateBar userData={userData}/>

<main className='flex flex-col flex-grow-[0.6] mt-20'>
<div className='my-auto'>
<RadixForm.Root asChild method='post'>
Expand Down
64 changes: 64 additions & 0 deletions app/routes/profile.completed-lessons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {type LoaderFunctionArgs, unstable_defineLoader as defineLoader} from '@remix-run/node';
import {useLoaderData, type MetaArgs_SingleFetch} from '@remix-run/react';
import {LessonEntityCard} from '~/components/entities-cards';
import {LessonActivityService} from '~/services/lesson-activity.service.server';
import {LessonService} from '~/services/lesson.service.server';
import {type TypeUserSession} from '~/types/user-session.type';
import {getUserSession} from '~/utils/session.server';

export const meta = ({data}: MetaArgs_SingleFetch<typeof loader>) => [
{title: 'Yoga em Movimento - Área Pessoal - Aulas Assistidas'},
{name: 'description', content: 'Aulas assistidas por cada aluno.'},
{name: 'robots', content: 'noindex, nofollow'},
...data!.meta,
];

export const loader = defineLoader(async ({request, response}: LoaderFunctionArgs) => {
const userSession = await getUserSession(request.headers.get('Cookie'));
const userData = userSession.data as TypeUserSession;

if (!userData.id) {
response!.headers.set('Location', '/');
response!.status = 303;

throw response; // eslint-disable-line @typescript-eslint/only-throw-error
}

const completedLessons = await new LessonService().getCompletedLessonsByUser(userData);

const completedLessonsWithActivity = completedLessons.data.map(lesson => ({
...lesson,
activity: new LessonActivityService().getLessonActivityForUser(lesson.lessonSlug, userData.id),
}));

return {
meta: [{tagName: 'link', rel: 'canonical', href: new URL('/profile/completed-lessons', request.url).toString()}],
userData,
completedLessonsWithActivity,
};
});

export default function CompletedLessons() {
const {completedLessonsWithActivity, userData} = useLoaderData<typeof loader>();

if (completedLessonsWithActivity.length === 0) {
return (
<div>
<h1>Aulas Assistidas</h1>
<p>{userData.firstName}, você ainda não completou nenhuma aula. Conforme assistir as aulas e marcá-las como completas, a lista de suas aulas assistidas aparecerá aqui.</p>
</div>
);
}

return (
<div>
<h1>Aulas Assistidas</h1>

<div className='flex gap-4 my-4 flex-wrap'>
{completedLessonsWithActivity.map(lesson => (
<LessonEntityCard key={lesson.id} course={lesson.lesson} to={lesson.link} activity={lesson.activity}/>
))}
</div>
</div>
);
}
64 changes: 64 additions & 0 deletions app/routes/profile.favorited-lessons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {type LoaderFunctionArgs, unstable_defineLoader as defineLoader} from '@remix-run/node';
import {useLoaderData, type MetaArgs_SingleFetch} from '@remix-run/react';
import {LessonEntityCard} from '~/components/entities-cards';
import {LessonActivityService} from '~/services/lesson-activity.service.server';
import {LessonService} from '~/services/lesson.service.server';
import {type TypeUserSession} from '~/types/user-session.type';
import {getUserSession} from '~/utils/session.server';

export const meta = ({data}: MetaArgs_SingleFetch<typeof loader>) => [
{title: 'Yoga em Movimento - Área Pessoal - Aulas Favoritadas'},
{name: 'description', content: 'Aulas favoritadas de cada aluno.'},
{name: 'robots', content: 'noindex, nofollow'},
...data!.meta,
];

export const loader = defineLoader(async ({request, response}: LoaderFunctionArgs) => {
const userSession = await getUserSession(request.headers.get('Cookie'));
const userData = userSession.data as TypeUserSession;

if (!userData.id) {
response!.headers.set('Location', '/');
response!.status = 303;

throw response; // eslint-disable-line @typescript-eslint/only-throw-error
}

const favoritedLessons = await new LessonService().getFavoritedLessonsByUser(userData);

const favoritedLessonsWithActivity = favoritedLessons.data.map(lesson => ({
...lesson,
activity: new LessonActivityService().getLessonActivityForUser(lesson.lessonSlug, userData.id),
}));

return {
meta: [{tagName: 'link', rel: 'canonical', href: new URL('/profile/completed-lessons', request.url).toString()}],
userData,
favoritedLessonsWithActivity,
};
});

export default function FavoritedLessons() {
const {favoritedLessonsWithActivity, userData} = useLoaderData<typeof loader>();

if (favoritedLessonsWithActivity.length === 0) {
return (
<div>
<h1>Aulas Favoritas</h1>
<p>{userData.firstName}, você ainda não favoritou nenhuma aula. Conforme assistir as aulas e marcá-las como favoritas, a lista de suas aulas favoritas aparecerá aqui.</p>
</div>
);
}

return (
<div>
<h1>Aulas Favoritas</h1>

<div className='flex gap-4 my-4 flex-wrap'>
{favoritedLessonsWithActivity.map(lesson => (
<LessonEntityCard key={lesson.id} course={lesson.lesson} to={lesson.link} activity={lesson.activity}/>
))}
</div>
</div>
);
}
64 changes: 64 additions & 0 deletions app/routes/profile.saved-lessons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {type LoaderFunctionArgs, unstable_defineLoader as defineLoader} from '@remix-run/node';
import {useLoaderData, type MetaArgs_SingleFetch} from '@remix-run/react';
import {LessonEntityCard} from '~/components/entities-cards';
import {LessonActivityService} from '~/services/lesson-activity.service.server';
import {LessonService} from '~/services/lesson.service.server';
import {type TypeUserSession} from '~/types/user-session.type';
import {getUserSession} from '~/utils/session.server';

export const meta = ({data}: MetaArgs_SingleFetch<typeof loader>) => [
{title: 'Yoga em Movimento - Área Pessoal - Aulas salvas'},
{name: 'description', content: 'Aulas salvadas por cada aluno.'},
{name: 'robots', content: 'noindex, nofollow'},
...data!.meta,
];

export const loader = defineLoader(async ({request, response}: LoaderFunctionArgs) => {
const userSession = await getUserSession(request.headers.get('Cookie'));
const userData = userSession.data as TypeUserSession;

if (!userData.id) {
response!.headers.set('Location', '/');
response!.status = 303;

throw response; // eslint-disable-line @typescript-eslint/only-throw-error
}

const savedLessons = await new LessonService().getSavedLessonsByUser(userData);

const savedLessonsWithActivity = savedLessons.data.map(lesson => ({
...lesson,
activity: new LessonActivityService().getLessonActivityForUser(lesson.lessonSlug, userData.id),
}));

return {
meta: [{tagName: 'link', rel: 'canonical', href: new URL('/profile/completed-lessons', request.url).toString()}],
userData,
savedLessonsWithActivity,
};
});

export default function CompletedLessons() {
const {savedLessonsWithActivity, userData} = useLoaderData<typeof loader>();

if (savedLessonsWithActivity.length === 0) {
return (
<div>
<h1>Aulas Salvadas</h1>
<p>{userData.firstName}, você ainda não salcou nenhuma aula. Conforme assistir as aulas e marcá-las como salvas, a lista de suas aulas salvadas aparecerá aqui.</p>
</div>
);
}

return (
<div>
<h1>Aulas Salvadas</h1>

<div className='flex gap-4 my-4 flex-wrap'>
{savedLessonsWithActivity.map(lesson => (
<LessonEntityCard key={lesson.id} course={lesson.lesson} to={lesson.link} activity={lesson.activity}/>
))}
</div>
</div>
);
}
64 changes: 64 additions & 0 deletions app/routes/profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {type LoaderFunctionArgs, unstable_defineLoader as defineLoader} from '@remix-run/node';
import {
Link, Outlet, useLocation,
type MetaArgs_SingleFetch,
useLoaderData,
} from '@remix-run/react';
import {NavigateBar} from '~/components/navigation-bar.js';
import {type TypeUserSession} from '~/types/user-session.type';
import {getUserSession} from '~/utils/session.server';

export const meta = ({data}: MetaArgs_SingleFetch<typeof loader>) => [
{title: 'Yoga em Movimento - Área Pessoal'},
{name: 'description', content: 'Área pessoal de cada aluno dentro do site da Yoga em Movimento.'},
{name: 'robots', content: 'noindex, nofollow'},
...data!.meta,
];

export const loader = defineLoader(async ({request, response}: LoaderFunctionArgs) => {
const userSession = await getUserSession(request.headers.get('Cookie'));
const data = userSession.data as TypeUserSession;

if (!data.id) {
response!.headers.set('Location', '/');
response!.status = 303;

throw response; // eslint-disable-line @typescript-eslint/only-throw-error
}

return {
meta: [{tagName: 'link', rel: 'canonical', href: new URL('/profile', request.url).toString()}],
userData: data,
};
});

export default function Profile() {
const {userData} = useLoaderData<typeof loader>();
const {pathname} = useLocation();

return userData?.id && (
<>
<NavigateBar userData={userData}/>

<div className='flex max-w-[95%] w-full mx-auto flex-col sm:flex-row gap-4'>
<aside className='w-64 p-3 bg-mauve-3 dark:bg-mauvedark-3 shadow-sm shadow-mauve-11 dark:shadow-mauvedark-3 rounded-lg h-fit flex flex-col gap-3'>
<Link to='/profile/completed-lessons'>
<p>Aulas Assistidas</p>
</Link>
<Link to='/profile/saved-lessons'>
<p>Aulas Salvadas</p>
</Link>
<Link to='/profile/favorited-lessons'>
<p>Aulas Favoritadas</p>
</Link>
</aside>
<main className='flex-grow flex-shrink p-3'>
{(pathname === '/profile' || pathname === '/profile/') && (
<p>Selecione a opção no menu ao lado</p>
)}
<Outlet/>
</main>
</div>
</>
);
}
Loading

0 comments on commit cc7e69f

Please sign in to comment.