Files
saladeaula.digital/apps/admin.saladeaula.digital/app/routes/_.$orgid.scheduled/route.tsx
2025-12-14 21:17:21 -03:00

120 lines
3.4 KiB
TypeScript

import type { Route } from './+types/route'
import { EllipsisIcon } from 'lucide-react'
import { DateTime } from 'luxon'
import { Fragment, Suspense } from 'react'
import { Await } from 'react-router'
import { Skeleton } from '@repo/ui/components/skeleton'
import { request as req } from '@repo/util/request'
import { Card, CardContent } from '@repo/ui/components/ui/card'
import {
Item,
ItemActions,
ItemContent,
ItemDescription,
ItemGroup,
ItemSeparator,
ItemTitle
} from '@repo/ui/components/ui/item'
import { Button } from '@repo/ui/components/ui/button'
export function meta({}: Route.MetaArgs) {
return [{ title: 'Matrículas agendadas' }]
}
export async function loader({ context, request, params }: Route.LoaderArgs) {
const scheduled = req({
url: `/orgs/${params.orgid}/enrollments/scheduled`,
context,
request
}).then((r) => r.json())
return {
scheduled
}
}
export default function Route({
loaderData: { scheduled }
}: Route.ComponentProps) {
return (
<Suspense fallback={<Skeleton />}>
<div className="space-y-0.5 mb-8">
<h1 className="text-2xl font-bold tracking-tight">
Matrículas agendadas
</h1>
<p className="text-muted-foreground">
Acompanhe todas as matrículas agendadas, cancele quando quiser ou
matricule imediatamente.
</p>
</div>
<Await resolve={scheduled}>
{({ items }) => {
return (
<div className="space-y-5 lg:max-w-4xl mx-auto">
{grouping(items).map(([run_at, items]) => (
<div className="grid grid-cols-5 gap-2.5">
<div>
{DateTime.fromISO(run_at)
.setLocale('pt-BR')
.toFormat('cccc, dd LLL yyyy')}
</div>
<Card className="col-span-4">
<CardContent>
<ItemGroup>
{items.map(({ user, course, scheduled_at }, index) => (
<Fragment key={index}>
<Item>
<ItemContent>
<ItemTitle>{course.name}</ItemTitle>
<ItemDescription>{user.name}</ItemDescription>
</ItemContent>
<ItemActions>
<Button variant="ghost" size="icon-sm">
<EllipsisIcon />
</Button>
</ItemActions>
</Item>
{index !== items.length - 1 && <ItemSeparator />}
</Fragment>
))}
</ItemGroup>
</CardContent>
</Card>
</div>
))}
</div>
)
}}
</Await>
</Suspense>
)
}
function grouping(items) {
const newItems = Object.entries(
items.reduce((acc, item) => {
const [run_at] = item.sk.split('#')
if (!acc[run_at]) {
acc[run_at] = []
}
acc[run_at].push(item)
return acc
}, [])
)
return newItems.sort((x, y) => x[0].localeCompare(y[0]))
}
const datetime = new Intl.DateTimeFormat('pt-BR', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
})