Skip to content

Commit

Permalink
timeline and various ui updates
Browse files Browse the repository at this point in the history
  • Loading branch information
xvvvyz committed Jul 12, 2024
1 parent 092fddd commit 770eafc
Show file tree
Hide file tree
Showing 27 changed files with 546 additions and 264 deletions.
4 changes: 3 additions & 1 deletion app/(pages)/(with-nav)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const Layout = async ({ children }: LayoutProps) => {
getCurrentUser(),
]);

if (!user) return null;

return (
<div className="mx-auto max-w-lg pb-20">
<Subscriptions />
Expand All @@ -26,7 +28,7 @@ const Layout = async ({ children }: LayoutProps) => {
<Button activeClassName="text-fg-2" href="/subjects" variant="link">
Subjects
</Button>
{!user?.user_metadata?.is_client && (
{!user.user_metadata.is_client && (
<>
<Button
activeClassName="text-fg-2"
Expand Down
32 changes: 20 additions & 12 deletions app/(pages)/(with-nav)/subjects/(list)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
import Button from '@/_components/button';
import getCurrentUser from '@/_queries/get-current-user';
import PlusIcon from '@heroicons/react/24/outline/PlusIcon';
import { ReactNode } from 'react';

interface LayoutProps {
children: ReactNode;
}

const Layout = async ({ children }: LayoutProps) => (
<>
<div className="my-16 flex h-8 items-center justify-between gap-8 px-4">
<h1 className="text-2xl">Subjects</h1>
<Button href="/subjects/create" scroll={false} size="sm">
<PlusIcon className="-ml-0.5 w-5" />
New subject
</Button>
</div>
<div className="space-y-4">{children}</div>
</>
);
const Layout = async ({ children }: LayoutProps) => {
const user = await getCurrentUser();
if (!user) return null;

return (
<>
{!user.user_metadata.is_client && (
<div className="mt-16 flex h-8 items-center justify-between gap-8 px-4">
<h1 className="text-2xl">Subjects</h1>
<Button href="/subjects/create" scroll={false} size="sm">
<PlusIcon className="-ml-0.5 w-5" />
New subject
</Button>
</div>
)}
<div className="mt-16 space-y-4">{children}</div>
</>
);
};

export default Layout;
14 changes: 9 additions & 5 deletions app/_components/event-comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useToggle } from '@uidotdev/usehooks';
interface EventCommentProps {
content: string;
createdAt: string;
hideCommentTimestamp?: boolean;
id: string;
profile: Database['public']['Tables']['profiles']['Row'];
isArchived?: boolean;
Expand All @@ -25,6 +26,7 @@ interface EventCommentProps {
const EventComment = ({
content,
createdAt,
hideCommentTimestamp,
id,
profile,
isArchived,
Expand All @@ -50,11 +52,13 @@ const EventComment = ({
<span className="w-0 flex-1 truncate">
{profile.first_name} {profile.last_name}
</span>
<DateTime
className="flex-shrink-0 whitespace-nowrap"
date={createdAt}
formatter="date-time"
/>
{!hideCommentTimestamp && (
<DateTime
className="flex-shrink-0 whitespace-nowrap"
date={createdAt}
formatter="date-time"
/>
)}
</div>
{!isPublic &&
!isArchived &&
Expand Down
3 changes: 3 additions & 0 deletions app/_components/event-comments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface EventCommentsProps {
id: string;
profile: Database['public']['Tables']['profiles']['Row'];
}>;
hideCommentTimestamp?: boolean;
isArchived?: boolean;
isPublic?: boolean;
isTeamMember?: boolean;
Expand All @@ -21,6 +22,7 @@ interface EventCommentsProps {
const EventComments = ({
className,
comments,
hideCommentTimestamp,
isArchived,
isPublic,
isTeamMember,
Expand All @@ -34,6 +36,7 @@ const EventComments = ({
<EventComment
content={content}
createdAt={created_at}
hideCommentTimestamp={hideCommentTimestamp}
id={id}
isArchived={isArchived}
isPublic={isPublic}
Expand Down
46 changes: 46 additions & 0 deletions app/_components/event-menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use client';

import Alert from '@/_components/alert';
import DropdownMenu from '@/_components/dropdown-menu';
import deleteEvent from '@/_mutations/delete-event';
import EllipsisVerticalIcon from '@heroicons/react/24/outline/EllipsisVerticalIcon';
import TrashIcon from '@heroicons/react/24/outline/TrashIcon';
import { useToggle } from '@uidotdev/usehooks';

interface EventMenuProps {
eventId: string;
}

const EventMenu = ({ eventId }: EventMenuProps) => {
const [deleteAlert, toggleDeleteAlert] = useToggle(false);

return (
<>
<DropdownMenu
trigger={
<div className="group absolute right-0 top-0 flex items-center justify-center px-2 py-2.5 text-fg-3 hover:text-fg-2 active:text-fg-2">
<div className="rounded-full p-2 group-hover:bg-alpha-1 group-active:bg-alpha-1">
<EllipsisVerticalIcon className="w-5" />
</div>
</div>
}
>
<DropdownMenu.Content className="-mt-[3.35rem] mr-1.5">
<DropdownMenu.Button onClick={() => toggleDeleteAlert(true)}>
<TrashIcon className="w-5 text-fg-4" />
Delete
</DropdownMenu.Button>
</DropdownMenu.Content>
</DropdownMenu>
<Alert
confirmText="Delete event"
isConfirmingText="Deleting…"
isOpen={deleteAlert}
onClose={toggleDeleteAlert}
onConfirm={() => deleteEvent(eventId)}
/>
</>
);
};

export default EventMenu;
33 changes: 15 additions & 18 deletions app/_components/event-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const EventPage = async ({ eventId, isPublic, subjectId }: EventPageProps) => {
subtitle={
<>
{event && (
<div className="smallcaps flex items-center gap-2 pt-3 text-fg-4">
<div className="smallcaps flex items-center gap-2 pt-2 text-fg-4">
{event.type.session ? 'Completed' : 'Recorded'} by
<Avatar
className="-my-[0.15rem]"
Expand All @@ -46,26 +46,23 @@ const EventPage = async ({ eventId, isPublic, subjectId }: EventPageProps) => {
</div>
)}
{event.type.session && (
<div className="-mr-12 flex items-baseline gap-4 pt-1.5">
<span className="smallcaps text-fg-4">
Session {Number(event.type.session.order) + 1}
</span>
<span className="smallcaps text-fg-4">
Module {Number(event.type.order) + 1}
</span>
<Button
href={`/${shareOrSubjects}/${subjectId}/training-plans/${event.type.session.mission?.id}/sessions/${event.type.session.id}`}
scroll={false}
variant="link"
>
View full session
<ArrowUpRightIcon className="w-5" />
</Button>
</div>
<Button
className="pt-4"
href={`/${shareOrSubjects}/${subjectId}/training-plans/${event.type.session.mission?.id}/sessions/${event.type.session.id}`}
scroll={false}
variant="link"
>
View full session
<ArrowUpRightIcon className="w-5" />
</Button>
)}
</>
}
title={event.type.name ?? event.type.session?.mission?.name}
title={
event.type.session
? `Module ${Number(event.type.order) + 1}${event.type.name ? `: ${event.type.name}` : ''}`
: event.type.name
}
/>
<EventCard
event={event}
Expand Down
9 changes: 5 additions & 4 deletions app/_components/module-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ const ModuleCard = ({
className="space-y-16 pb-8 pt-10"
defaultOpen={!event && !disabled}
title={
<div className="py-2 text-left">
<div className="-mt-0.5">
<div className="min-w-0 py-2 text-left">
<div className="truncate leading-snug">
Module {(eventType.order as number) + 1}
{eventType.name ? `: ${eventType.name}` : ''}
</div>
{event && (
<div className="smallcaps flex items-center gap-2 pt-1 text-fg-4">
<div className="smallcaps flex items-center gap-2 pb-0.5 pt-1.5 text-fg-4">
Completed by
<Avatar
className="-my-[0.15rem]"
Expand All @@ -59,7 +60,7 @@ const ModuleCard = ({
)}
</div>
}
titleClassName="sm:pl-8 border-0 my-0 pr-6 sm:pr-10"
titleClassName="sm:pl-8 border-0 my-0 pr-6 sm:pr-10 hover:bg-alpha-1 active:bg-alpha-1"
>
{eventType.content && (
<DirtyHtml className="px-4 sm:px-8">{eventType.content}</DirtyHtml>
Expand Down
28 changes: 21 additions & 7 deletions app/_components/module-form-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
} from '@headlessui/react';

import DropdownMenu from '@/_components/dropdown-menu';
import Input from '@/_components/input';
import {
ArrayPath,
Controller,
Expand Down Expand Up @@ -100,8 +101,8 @@ const ModuleFormSection = <T extends FieldValues, U extends ArrayPath<T>>({
return (
<li
className={twMerge(
'relative rounded bg-bg-2',
isDragging && 'z-10 drop-shadow-2xl',
'bg-bg-2',
isDragging && 'relative z-10 drop-shadow-2xl',
)}
ref={setNodeRef}
style={{
Expand Down Expand Up @@ -162,6 +163,12 @@ const ModuleFormSection = <T extends FieldValues, U extends ArrayPath<T>>({
</DropdownMenu.Content>
</DropdownMenu>
</div>
<Input
className="rounded-none border-t-0"
maxLength={49}
placeholder="Module title"
{...form.register(`modules[${eventTypeIndex}].name` as Path<T>)}
/>
<Controller
control={form.control}
name={`modules[${eventTypeIndex}].content` as T[string]}
Expand Down Expand Up @@ -213,17 +220,24 @@ const ModuleFormSection = <T extends FieldValues, U extends ArrayPath<T>>({
instanceId="template-select"
noOptionsMessage={() => 'No templates.'}
onChange={(t) => {
const template = (
t as NonNullable<ListTemplatesWithDataData>[0]
)?.data as TemplateDataJson;
const template =
t as NonNullable<ListTemplatesWithDataData>[0];

const data = template?.data as TemplateDataJson;

const inputs = availableInputs.filter(({ id }) =>
forceArray(template?.inputIds).includes(id),
forceArray(data?.inputIds).includes(id),
) as PathValue<T, T[string]>;

form.setValue(
`modules[${eventTypeIndex}].name` as Path<T>,
template?.name as PathValue<T, Path<T>>,
{ shouldDirty: true },
);

form.setValue(
`modules[${eventTypeIndex}].content` as Path<T>,
template?.content as PathValue<T, Path<T>>,
data?.content as PathValue<T, Path<T>>,
{ shouldDirty: true },
);

Expand Down
5 changes: 1 addition & 4 deletions app/_components/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,7 @@ const Menu = <TOption extends IOption>({
children,
...props
}: MenuProps<TOption>) => (
<components.Menu
className="overflow-hidden rounded-b bg-bg-2 drop-shadow"
{...props}
>
<components.Menu className="rounded-b bg-bg-2 drop-shadow" {...props}>
<div className="rounded-b border border-t-0 border-alpha-1 bg-alpha-2">
{children}
</div>
Expand Down
9 changes: 6 additions & 3 deletions app/_components/session-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ type SessionFormValues = {
content: string;
id?: string;
inputs: Array<Database['public']['Tables']['inputs']['Row']>;
name?: string | null;
}>;
scheduledFor: string | null;
title: string;
title?: string | null;
};

const SessionForm = ({
Expand Down Expand Up @@ -106,6 +107,7 @@ const SessionForm = ({
inputs: availableInputs.filter((input) =>
module.inputs.some(({ input_id }) => input_id === input.id),
),
name: module.name,
}))
: [{ content: '', inputs: [] }],
scheduledFor:
Expand All @@ -114,7 +116,7 @@ const SessionForm = ({
new Date(session.scheduled_for) < new Date())
? null
: formatDatetimeLocal(session.scheduled_for, { seconds: false }),
title: session?.title ?? '',
title: session?.title,
},
},
{ ignoreValues: ['draft', 'order'] },
Expand Down Expand Up @@ -179,7 +181,8 @@ const SessionForm = ({
>
<div className="flex items-center gap-6">
<Input
placeholder={`Session ${currentOrder + 1}`}
placeholder="Session title"
maxLength={49}
{...form.register('title')}
/>
<Button
Expand Down
4 changes: 2 additions & 2 deletions app/_components/session-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const SessionPage = async ({
>
{session.scheduled_for &&
new Date(session.scheduled_for) > new Date() ? (
<Empty className="border-0 pb-12">
<Empty className="mt-6 border-0">
<CalendarDaysIcon className="w-7" />
<p>
Scheduled for{' '}
Expand All @@ -80,7 +80,7 @@ const SessionPage = async ({
) : (
<>
{session.title && (
<p className="mx-auto max-w-xs px-4 text-center">
<p className="mx-auto max-w-xs px-4 text-center leading-snug">
{session.title}
</p>
)}
Expand Down
Loading

0 comments on commit 770eafc

Please sign in to comment.