diff --git a/app/(pages)/(with-nav)/inputs/layout.tsx b/app/(pages)/(with-nav)/inputs/layout.tsx index 29517454..cca15b23 100644 --- a/app/(pages)/(with-nav)/inputs/layout.tsx +++ b/app/(pages)/(with-nav)/inputs/layout.tsx @@ -11,7 +11,7 @@ const Layout = ({ children }: LayoutProps) => (

Inputs

diff --git a/app/(pages)/(with-nav)/subjects/(list)/layout.tsx b/app/(pages)/(with-nav)/subjects/(list)/layout.tsx index 83db1635..da77431b 100644 --- a/app/(pages)/(with-nav)/subjects/(list)/layout.tsx +++ b/app/(pages)/(with-nav)/subjects/(list)/layout.tsx @@ -11,7 +11,7 @@ const Layout = async ({ children }: LayoutProps) => (

Subjects

diff --git a/app/(pages)/(with-nav)/subjects/(list)/page.tsx b/app/(pages)/(with-nav)/subjects/(list)/page.tsx index 72f14463..200ba77c 100644 --- a/app/(pages)/(with-nav)/subjects/(list)/page.tsx +++ b/app/(pages)/(with-nav)/subjects/(list)/page.tsx @@ -45,21 +45,23 @@ const Page = async () => { {!clientSubjects.length && !teamSubjects.length && ( - Subjects can be dogs, cats, humans or + Add a subject to start collaboratively
- anything else you want to track. + tracking and improving behavior.
)} - - - + {(!!archivedTeamSubjects.length || !!archivedClientSubjects.length) && ( + + + + )} ); }; diff --git a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/layout.tsx b/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/layout.tsx deleted file mode 100644 index 5d84c1f4..00000000 --- a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/layout.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import SubjectLayout from '@/_components/subject-layout'; -import { ReactNode } from 'react'; - -interface PageProps { - children: ReactNode; - params: { subjectId: string }; -} - -const Layout = ({ children, params: { subjectId } }: PageProps) => ( - {children} -); - -export default Layout; diff --git a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/loading.tsx b/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/loading.tsx deleted file mode 100644 index a626e9fb..00000000 --- a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/loading.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import Spinner from '@/_components/spinner'; - -const Loading = () => ; - -export default Loading; diff --git a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/layout.tsx b/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/layout.tsx deleted file mode 100644 index fc1ebfa1..00000000 --- a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { ReactNode } from 'react'; - -interface LayoutProps { - children: ReactNode; -} - -const Layout = ({ children }: LayoutProps) => children; - -export default Layout; diff --git a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/loading.tsx b/app/(pages)/(with-nav)/subjects/[subjectId]/loading.tsx similarity index 100% rename from app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/loading.tsx rename to app/(pages)/(with-nav)/subjects/[subjectId]/loading.tsx diff --git a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/events/page.tsx b/app/(pages)/(with-nav)/subjects/[subjectId]/page.tsx similarity index 71% rename from app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/events/page.tsx rename to app/(pages)/(with-nav)/subjects/[subjectId]/page.tsx index 10ca69ad..b4b0888a 100644 --- a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/events/page.tsx +++ b/app/(pages)/(with-nav)/subjects/[subjectId]/page.tsx @@ -1,4 +1,4 @@ -import SubjectEventsPage from '@/_components/subject-events-page'; +import SubjectPage from '@/_components/subject-page'; import formatTitle from '@/_utilities/format-title'; interface PageProps { @@ -12,7 +12,7 @@ const Page = ({ params: { subjectId }, searchParams: { from, limit, to }, }: PageProps) => ( - + ); export default Page; diff --git a/app/(pages)/(with-nav)/templates/layout.tsx b/app/(pages)/(with-nav)/templates/layout.tsx index 382b97fd..8c79e817 100644 --- a/app/(pages)/(with-nav)/templates/layout.tsx +++ b/app/(pages)/(with-nav)/templates/layout.tsx @@ -11,7 +11,7 @@ const Layout = ({ children }: LayoutProps) => (

Templates

diff --git a/app/(pages)/share/[subjectId]/(subject-loading)/(subject)/insights/page.tsx b/app/(pages)/@modal/(lg)/share/[subjectId]/insights/page.tsx similarity index 67% rename from app/(pages)/share/[subjectId]/(subject-loading)/(subject)/insights/page.tsx rename to app/(pages)/@modal/(lg)/share/[subjectId]/insights/page.tsx index 9b48a269..4426ac96 100644 --- a/app/(pages)/share/[subjectId]/(subject-loading)/(subject)/insights/page.tsx +++ b/app/(pages)/@modal/(lg)/share/[subjectId]/insights/page.tsx @@ -1,4 +1,4 @@ -import SubjectInsightsPage from '@/_components/subject-insights-page'; +import InsightsPage from '@/_components/insights-page'; import formatTitle from '@/_utilities/format-title'; interface PageProps { @@ -9,11 +9,7 @@ interface PageProps { export const metadata = { title: formatTitle(['Subjects', 'Insights']) }; const Page = async ({ params: { subjectId }, searchParams }: PageProps) => ( - + ); export default Page; diff --git a/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/[insightId]/edit/page.tsx b/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/[insightId]/edit/page.tsx index 0ba7cd1e..47b5176c 100644 --- a/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/[insightId]/edit/page.tsx +++ b/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/[insightId]/edit/page.tsx @@ -26,7 +26,7 @@ const Page = async ({ params: { insightId, subjectId } }: PageProps) => { return ( <> - + ); diff --git a/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/[insightId]/loading.tsx b/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/[insightId]/loading.tsx index e3d948d8..3999a6f2 100644 --- a/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/[insightId]/loading.tsx +++ b/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/[insightId]/loading.tsx @@ -1,5 +1,7 @@ import PageModalLoading from '@/_components/page-modal-loading'; -const Loading = PageModalLoading; +const Loading = () => ( + +); export default Loading; diff --git a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/insights/page.tsx b/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/page.tsx similarity index 69% rename from app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/insights/page.tsx rename to app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/page.tsx index 77f0a661..cc13bf92 100644 --- a/app/(pages)/(with-nav)/subjects/[subjectId]/(subject-loading)/(subject)/insights/page.tsx +++ b/app/(pages)/@modal/(lg)/subjects/[subjectId]/insights/page.tsx @@ -1,4 +1,4 @@ -import SubjectInsightsPage from '@/_components/subject-insights-page'; +import InsightsPage from '@/_components/insights-page'; import formatTitle from '@/_utilities/format-title'; interface PageProps { @@ -9,7 +9,7 @@ interface PageProps { export const metadata = { title: formatTitle(['Subjects', 'Insights']) }; const Page = async ({ params: { subjectId }, searchParams }: PageProps) => ( - + ); export default Page; diff --git a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/edit/page.tsx b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/edit/page.tsx index 98c932f5..fb875260 100644 --- a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/edit/page.tsx +++ b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/edit/page.tsx @@ -1,7 +1,7 @@ -import MissionForm from '@/_components/mission-form'; import PageModalHeader from '@/_components/page-modal-header'; -import getMission from '@/_queries/get-mission'; +import TrainingPlanForm from '@/_components/training-plan-form'; import getSubject from '@/_queries/get-subject'; +import getTrainingPlan from '@/_queries/get-training-plan'; import formatTitle from '@/_utilities/format-title'; interface PageProps { @@ -18,7 +18,7 @@ export const metadata = { const Page = async ({ params: { missionId, subjectId } }: PageProps) => { const [{ data: subject }, { data: mission }] = await Promise.all([ getSubject(subjectId), - getMission(missionId), + getTrainingPlan(missionId), ]); if (!subject || !mission) return null; @@ -26,7 +26,7 @@ const Page = async ({ params: { missionId, subjectId } }: PageProps) => { return ( <> - + ); }; diff --git a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/[sessionId]/edit/page.tsx b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/[sessionId]/edit/page.tsx index e81e393a..85d20a20 100644 --- a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/[sessionId]/edit/page.tsx +++ b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/[sessionId]/edit/page.tsx @@ -3,9 +3,9 @@ import PageModalHeader from '@/_components/page-modal-header'; import SessionForm from '@/_components/session-form'; import SessionLayout from '@/_components/session-layout'; import getCurrentUser from '@/_queries/get-current-user'; -import getMissionWithSessions from '@/_queries/get-mission-with-sessions'; import getSession from '@/_queries/get-session'; import getSubject from '@/_queries/get-subject'; +import getTrainingPlanWithSessions from '@/_queries/get-training-plan-with-sessions'; import listInputsBySubjectId from '@/_queries/list-inputs-by-subject-id'; import listSubjectsByTeamId from '@/_queries/list-subjects-by-team-id'; import listTemplatesWithData from '@/_queries/list-templates-with-data'; @@ -37,7 +37,7 @@ const Page = async ({ user, ] = await Promise.all([ getSubject(subjectId), - getMissionWithSessions(missionId, { draft: true }), + getTrainingPlanWithSessions(missionId, { draft: true }), getSession(sessionId), listInputsBySubjectId(subjectId), listTemplatesWithData(), diff --git a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/create/[order]/from-session/[sessionId]/page.tsx b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/create/[order]/from-session/[sessionId]/page.tsx index 55b0b8b8..e4d9da98 100644 --- a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/create/[order]/from-session/[sessionId]/page.tsx +++ b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/create/[order]/from-session/[sessionId]/page.tsx @@ -3,9 +3,9 @@ import PageModalHeader from '@/_components/page-modal-header'; import SessionForm from '@/_components/session-form'; import SessionLayout from '@/_components/session-layout'; import getCurrentUser from '@/_queries/get-current-user'; -import getMissionWithSessions from '@/_queries/get-mission-with-sessions'; import getSession from '@/_queries/get-session'; import getSubject from '@/_queries/get-subject'; +import getTrainingPlanWithSessions from '@/_queries/get-training-plan-with-sessions'; import listInputsBySubjectId from '@/_queries/list-inputs-by-subject-id'; import listSubjectsByTeamId from '@/_queries/list-subjects-by-team-id'; import listTemplatesWithData from '@/_queries/list-templates-with-data'; @@ -37,7 +37,7 @@ const Page = async ({ user, ] = await Promise.all([ getSubject(subjectId), - getMissionWithSessions(missionId, { draft: true }), + getTrainingPlanWithSessions(missionId, { draft: true }), getSession(sessionId), listInputsBySubjectId(subjectId), listTemplatesWithData(), diff --git a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/create/[order]/page.tsx b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/create/[order]/page.tsx index cd60486f..ea2954db 100644 --- a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/create/[order]/page.tsx +++ b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/[missionId]/sessions/create/[order]/page.tsx @@ -3,8 +3,8 @@ import PageModalHeader from '@/_components/page-modal-header'; import SessionForm from '@/_components/session-form'; import SessionLayout from '@/_components/session-layout'; import getCurrentUser from '@/_queries/get-current-user'; -import getMissionWithSessions from '@/_queries/get-mission-with-sessions'; import getSubject from '@/_queries/get-subject'; +import getTrainingPlanWithSessions from '@/_queries/get-training-plan-with-sessions'; import listInputsBySubjectId from '@/_queries/list-inputs-by-subject-id'; import listSubjectsByTeamId from '@/_queries/list-subjects-by-team-id'; import listTemplatesWithData from '@/_queries/list-templates-with-data'; @@ -32,7 +32,7 @@ const Page = async ({ params: { missionId, order, subjectId } }: PageProps) => { user, ] = await Promise.all([ getSubject(subjectId), - getMissionWithSessions(missionId, { draft: true }), + getTrainingPlanWithSessions(missionId, { draft: true }), listSubjectsByTeamId(), listInputsBySubjectId(subjectId), listTemplatesWithData(), diff --git a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/create/page.tsx b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/create/page.tsx index 5c94ff77..0a3d7067 100644 --- a/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/create/page.tsx +++ b/app/(pages)/@modal/(md)/subjects/[subjectId]/training-plans/create/page.tsx @@ -1,5 +1,5 @@ -import MissionForm from '@/_components/mission-form'; import PageModalHeader from '@/_components/page-modal-header'; +import TrainingPlanForm from '@/_components/training-plan-form'; import getSubject from '@/_queries/get-subject'; import formatTitle from '@/_utilities/format-title'; @@ -20,7 +20,7 @@ const Page = async ({ params: { subjectId } }: PageProps) => { return ( <> - + ); }; diff --git a/app/(pages)/loading.tsx b/app/(pages)/loading.tsx deleted file mode 100644 index b95ccc10..00000000 --- a/app/(pages)/loading.tsx +++ /dev/null @@ -1,3 +0,0 @@ -const Loading = () => null; - -export default Loading; diff --git a/app/(pages)/share/[subjectId]/(subject-loading)/(subject)/layout.tsx b/app/(pages)/share/[subjectId]/(subject-loading)/(subject)/layout.tsx deleted file mode 100644 index 651fa7de..00000000 --- a/app/(pages)/share/[subjectId]/(subject-loading)/(subject)/layout.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import SubjectLayout from '@/_components/subject-layout'; -import { ReactNode } from 'react'; - -interface PageProps { - children: ReactNode; - params: { subjectId: string }; -} - -const Layout = ({ children, params: { subjectId } }: PageProps) => ( - - {children} - -); - -export default Layout; diff --git a/app/(pages)/share/[subjectId]/(subject-loading)/(subject)/loading.tsx b/app/(pages)/share/[subjectId]/(subject-loading)/(subject)/loading.tsx deleted file mode 100644 index a626e9fb..00000000 --- a/app/(pages)/share/[subjectId]/(subject-loading)/(subject)/loading.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import Spinner from '@/_components/spinner'; - -const Loading = () => ; - -export default Loading; diff --git a/app/(pages)/share/[subjectId]/(subject-loading)/layout.tsx b/app/(pages)/share/[subjectId]/(subject-loading)/layout.tsx deleted file mode 100644 index fc1ebfa1..00000000 --- a/app/(pages)/share/[subjectId]/(subject-loading)/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { ReactNode } from 'react'; - -interface LayoutProps { - children: ReactNode; -} - -const Layout = ({ children }: LayoutProps) => children; - -export default Layout; diff --git a/app/(pages)/share/[subjectId]/(subject-loading)/loading.tsx b/app/(pages)/share/[subjectId]/(subject-loading)/loading.tsx deleted file mode 100644 index e25c34a7..00000000 --- a/app/(pages)/share/[subjectId]/(subject-loading)/loading.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import SubjectLoading from '@/_components/subject-loading'; - -export default SubjectLoading; diff --git a/app/(pages)/share/[subjectId]/events.csv/route.tsx b/app/(pages)/share/[subjectId]/events.csv/route.tsx deleted file mode 100644 index 2f168997..00000000 --- a/app/(pages)/share/[subjectId]/events.csv/route.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import Number from '@/_constants/enum-number'; -import listPublicEvents from '@/_queries/list-public-events'; -import formatTabularEventsCsvResponse from '@/_utilities/format-tabular-events-csv-response'; - -interface GetContext { - params: { - subjectId: string; - }; -} - -export const GET = async (_: Request, ctx: GetContext) => { - const { data } = await listPublicEvents(ctx.params.subjectId, { - from: 0, - to: Number.FourByteSignedIntMax - 1, - }); - - return formatTabularEventsCsvResponse(data); -}; diff --git a/app/(pages)/share/[subjectId]/layout.tsx b/app/(pages)/share/[subjectId]/layout.tsx index 8dbced09..a110cf4d 100644 --- a/app/(pages)/share/[subjectId]/layout.tsx +++ b/app/(pages)/share/[subjectId]/layout.tsx @@ -29,7 +29,7 @@ const Layout = async ({ children, params: { subjectId } }: LayoutProps) => { + ) + } + title="Insights" + titlesWrapperClassName="flex w-full sm:pr-2 justify-between items-center" + /> +
+ {!insights?.length ? ( + + + No insights. + + ) : ( +
+ +
+ )} + - - Create insight - - )} - {!insights?.length ? ( - - - No insights. - - ) : ( - - )} -
+ Close + + + ); }; -export default SubjectInsightsPage; +export default InsightsPage; diff --git a/app/_components/insights.tsx b/app/_components/insights.tsx index 717d2a8f..db546031 100644 --- a/app/_components/insights.tsx +++ b/app/_components/insights.tsx @@ -6,12 +6,13 @@ import PlotFigure from '@/_components/plot-figure'; import { ListEventsData } from '@/_queries/list-events'; import { ListInsightsData } from '@/_queries/list-insights'; import { InsightConfigJson } from '@/_types/insight-config-json'; +import ArrowsPointingOutIcon from '@heroicons/react/24/outline/ArrowsPointingOutIcon'; import ArrowUpRightIcon from '@heroicons/react/24/outline/ArrowUpRightIcon'; import { useState } from 'react'; import { twMerge } from 'tailwind-merge'; interface InsightsProps { - events: NonNullable; + events: ListEventsData; insights: NonNullable; isArchived?: boolean; isPublic?: boolean; @@ -39,58 +40,54 @@ const Insights = ({ const isReadOnly = !isTeamMember || isArchived; return ( -
-
-
- - {!isReadOnly && ( - +
+
+ + {!isReadOnly && ( + + )}
-
+ + ); }); }; diff --git a/app/_components/module-card.tsx b/app/_components/module-card.tsx index 696ddcbc..fe739606 100644 --- a/app/_components/module-card.tsx +++ b/app/_components/module-card.tsx @@ -1,8 +1,8 @@ import Avatar from '@/_components/avatar'; import CollapsibleSection from '@/_components/collapsible-section'; import DirtyHtml from '@/_components/dirty-html'; -import { GetMissionWithSessionsData } from '@/_queries/get-mission-with-sessions'; import { GetSessionWithDetailsData } from '@/_queries/get-session-with-details'; +import { GetTrainingPlanWithSessionsData } from '@/_queries/get-training-plan-with-sessions'; import forceArray from '@/_utilities/force-array'; import { User } from '@supabase/supabase-js'; import EventCommentForm from './event-comment-form'; @@ -16,7 +16,7 @@ interface ModuleCardProps { isArchived?: boolean; isPublic?: boolean; isTeamMember?: boolean; - mission: NonNullable; + mission: NonNullable; subjectId: string; user?: User | null; } @@ -40,11 +40,11 @@ const ModuleCard = ({ defaultOpen={!event && !disabled} title={
-
+
Module {(eventType.order as number) + 1}
{event && ( -
+
Completed by { href={ sourceEvent ? `/subjects/${n?.subject?.id}/events/${sourceEvent.id}` - : `/subjects/${n?.subject?.id}/events` + : `/subjects/${n?.subject?.id}` } scroll={!sourceEvent} variant="link" diff --git a/app/_components/page-modal-header.tsx b/app/_components/page-modal-header.tsx index e2a40f50..09fb2077 100644 --- a/app/_components/page-modal-header.tsx +++ b/app/_components/page-modal-header.tsx @@ -8,6 +8,7 @@ interface PageModalHeaderProps { onClose?: () => void; subtitle?: ReactNode; title?: ReactNode; + titlesWrapperClassName?: string; } const PageModalHeader = ({ @@ -15,6 +16,7 @@ const PageModalHeader = ({ onClose, subtitle, title, + titlesWrapperClassName, }: PageModalHeaderProps) => (
-
+
{title &&

{title}

} {subtitle}
diff --git a/app/_components/page-modal-loading.tsx b/app/_components/page-modal-loading.tsx index 3e2d2031..ad0b25e1 100644 --- a/app/_components/page-modal-loading.tsx +++ b/app/_components/page-modal-loading.tsx @@ -4,8 +4,12 @@ import BackIconButton from '@/_components/back-icon-button'; import Spinner from '@/_components/spinner'; import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon'; -const PageModalLoading = () => ( - <> +interface PageModalLoadingProps { + className?: string; +} + +const PageModalLoading = ({ className }: PageModalLoadingProps) => ( +
( icon={} />
-
+
- +
); export default PageModalLoading; diff --git a/app/_components/page-modal.tsx b/app/_components/page-modal.tsx index 53fb9fae..c0363871 100644 --- a/app/_components/page-modal.tsx +++ b/app/_components/page-modal.tsx @@ -16,7 +16,7 @@ const PageModal = ({ children, className }: PageModalProps) => { return ( -
+
; + events: ListEventsData; includeEventsFrom: string | null; includeEventsSince: TimeSinceMilliseconds | null; id?: string; @@ -72,7 +72,7 @@ const PlotFigure = ({ const { parentRef, width } = useParentSize(); useEffect(() => { - if (!containerRef.current) return; + if (!containerRef.current || !events) return; const { input, isDuration, isInputNominal } = getInputDetailsFromEvents({ events, diff --git a/app/_components/scroll-to-top-hack.tsx b/app/_components/scroll-to-top-hack.tsx deleted file mode 100644 index deb7a88b..00000000 --- a/app/_components/scroll-to-top-hack.tsx +++ /dev/null @@ -1,35 +0,0 @@ -'use client'; - -import { usePathname, useSearchParams } from 'next/navigation'; -import { useEffect } from 'react'; - -interface ScrollToTopHackProps { - subjectId: string; -} - -// hack to work around https://github.com/vercel/next.js/issues/63497 -const ScrollToTopHack = ({ subjectId }: ScrollToTopHackProps) => { - const pathname = usePathname(); - const searchParams = useSearchParams(); - - useEffect(() => { - if ( - searchParams.get('s') === '1' || - pathname !== `/subjects/${subjectId}/events` - ) { - return; - } - - window.scrollTo({ top: 0 }); - const newSearchParams = new URLSearchParams(searchParams); - newSearchParams.set('s', '1'); - const searchString = newSearchParams.toString(); - const delimiter = searchString ? '?' : ''; - const url = `${pathname}${delimiter}${searchString}`; - window.history.replaceState(null, '', url); - }, [pathname, searchParams, subjectId]); - - return null; -}; - -export default ScrollToTopHack; diff --git a/app/_components/session-form.tsx b/app/_components/session-form.tsx index a49bd08f..23799d01 100644 --- a/app/_components/session-form.tsx +++ b/app/_components/session-form.tsx @@ -7,8 +7,8 @@ import ModuleFormSection from '@/_components/module-form-section'; import UnsavedChangesBanner from '@/_components/unsaved-changes-banner'; import useCachedForm from '@/_hooks/use-cached-form'; import upsertSession from '@/_mutations/upsert-session'; -import { GetMissionWithSessionsData } from '@/_queries/get-mission-with-sessions'; import { GetSessionData } from '@/_queries/get-session'; +import { GetTrainingPlanWithSessionsData } from '@/_queries/get-training-plan-with-sessions'; import { ListInputsBySubjectIdData } from '@/_queries/list-inputs-by-subject-id'; import { ListSubjectsByTeamIdData } from '@/_queries/list-subjects-by-team-id'; import { ListTemplatesWithDataData } from '@/_queries/list-templates-with-data'; @@ -41,6 +41,7 @@ import { useSensors, } from '@dnd-kit/core'; +import Tip from '@/_components/tip'; import { SortableContext, verticalListSortingStrategy, @@ -50,7 +51,7 @@ interface SessionFormProps { availableInputs: NonNullable; availableTemplates: NonNullable; isDuplicate?: boolean; - mission: NonNullable; + mission: NonNullable; order?: number; session?: NonNullable; subjects: NonNullable; @@ -146,7 +147,7 @@ const SessionForm = ({ return ( <>
startTransition(async () => { values.scheduledFor = values.scheduledFor @@ -233,14 +234,20 @@ const SessionForm = ({ - +
+ + Modules break up your session and allow you to capture inputs at + different points. You can add as many modules as you need. + + +
{form.formState.errors.root && (
{form.formState.errors.root.message} diff --git a/app/_components/session-layout.tsx b/app/_components/session-layout.tsx index 7642297b..5dcdec03 100644 --- a/app/_components/session-layout.tsx +++ b/app/_components/session-layout.tsx @@ -1,6 +1,6 @@ import ForwardSearchParamsButton from '@/_components/forward-search-params-button'; import ForwardSearchParamsIconButton from '@/_components/forward-search-params-icon-button'; -import { GetMissionWithSessionsData } from '@/_queries/get-mission-with-sessions'; +import { GetTrainingPlanWithSessionsData } from '@/_queries/get-training-plan-with-sessions'; import ChevronLeftIcon from '@heroicons/react/24/outline/ChevronLeftIcon'; import ChevronRightIcon from '@heroicons/react/24/outline/ChevronRightIcon'; import EyeIcon from '@heroicons/react/24/outline/EyeIcon'; @@ -18,7 +18,7 @@ interface SessionLayoutProps { missionId: string; order?: string; sessionId?: string; - sessions: NonNullable['sessions']; + sessions: NonNullable['sessions']; subjectId: string; } diff --git a/app/_components/session-menu.tsx b/app/_components/session-menu.tsx index 3b4ad3d0..5906d458 100644 --- a/app/_components/session-menu.tsx +++ b/app/_components/session-menu.tsx @@ -4,7 +4,7 @@ import Alert from '@/_components/alert'; import DropdownMenu from '@/_components/dropdown-menu'; import deleteSession from '@/_mutations/delete-session'; import moveSession from '@/_mutations/move-session'; -import { GetMissionWithSessionsData } from '@/_queries/get-mission-with-sessions'; +import { GetTrainingPlanWithSessionsData } from '@/_queries/get-training-plan-with-sessions'; import ArrowDownIcon from '@heroicons/react/24/outline/ArrowDownIcon'; import ArrowUpIcon from '@heroicons/react/24/outline/ArrowUpIcon'; import DocumentDuplicateIcon from '@heroicons/react/24/outline/DocumentDuplicateIcon'; @@ -18,7 +18,7 @@ interface SessionMenuProps { highestPublishedOrder: number; missionId: string; nextSessionOrder: number; - session: NonNullable['sessions'][0]; + session: NonNullable['sessions'][0]; subjectId: string; } diff --git a/app/_components/session-page.tsx b/app/_components/session-page.tsx index b34cf059..5b631a9b 100644 --- a/app/_components/session-page.tsx +++ b/app/_components/session-page.tsx @@ -6,12 +6,12 @@ import PageModalHeader from '@/_components/page-modal-header'; import SessionLayout from '@/_components/session-layout'; import ViewAllSessionsButton from '@/_components/view-all-sessions-button'; import getCurrentUser from '@/_queries/get-current-user'; -import getMissionWithSessions from '@/_queries/get-mission-with-sessions'; -import getPublicMissionWithSessions from '@/_queries/get-public-mission-with-sessions'; import getPublicSessionWithDetails from '@/_queries/get-public-session-with-details'; import getPublicSubject from '@/_queries/get-public-subject'; +import getPublicTrainingPlanWithSessions from '@/_queries/get-public-training-plan-with-sessions'; import getSessionWithDetails from '@/_queries/get-session-with-details'; import getSubject from '@/_queries/get-subject'; +import getTrainingPlanWithSessions from '@/_queries/get-training-plan-with-sessions'; import firstIfArray from '@/_utilities/first-if-array'; import CalendarDaysIcon from '@heroicons/react/24/outline/CalendarDaysIcon'; @@ -32,8 +32,8 @@ const SessionPage = async ({ await Promise.all([ isPublic ? getPublicSubject(subjectId) : getSubject(subjectId), isPublic - ? getPublicMissionWithSessions(missionId) - : getMissionWithSessions(missionId), + ? getPublicTrainingPlanWithSessions(missionId) + : getTrainingPlanWithSessions(missionId), isPublic ? getPublicSessionWithDetails(sessionId) : getSessionWithDetails(sessionId), diff --git a/app/_components/sessions-page.tsx b/app/_components/sessions-page.tsx index 087169e5..4c66714f 100644 --- a/app/_components/sessions-page.tsx +++ b/app/_components/sessions-page.tsx @@ -5,10 +5,10 @@ import Empty from '@/_components/empty'; import PageModalHeader from '@/_components/page-modal-header'; import SessionMenu from '@/_components/session-menu'; import getCurrentUser from '@/_queries/get-current-user'; -import getMissionWithSessionsAndEvents from '@/_queries/get-mission-with-sessions-and-events'; -import getPublicMissionWithSessionsAndEvents from '@/_queries/get-public-mission-with-sessions-and-events'; import getPublicSubject from '@/_queries/get-public-subject'; +import getPublicTrainingPlanWithSessionsAndEvents from '@/_queries/get-public-training-plan-with-sessions-and-events'; import getSubject from '@/_queries/get-subject'; +import getTrainingPlanWithSessionsAndEvents from '@/_queries/get-training-plan-with-sessions-and-events'; import getHighestPublishedOrder from '@/_utilities/get-highest-published-order'; import ArrowRightIcon from '@heroicons/react/24/outline/ArrowRightIcon'; import InformationCircleIcon from '@heroicons/react/24/outline/InformationCircleIcon'; @@ -34,8 +34,10 @@ const SessionsPage = async ({ const isTeamMember = !!user && subject.team_id === user.id; const { data: mission } = isPublic - ? await getPublicMissionWithSessionsAndEvents(missionId) - : await getMissionWithSessionsAndEvents(missionId, { draft: isTeamMember }); + ? await getPublicTrainingPlanWithSessionsAndEvents(missionId) + : await getTrainingPlanWithSessionsAndEvents(missionId, { + draft: isTeamMember, + }); if (!mission) return null; @@ -68,7 +70,7 @@ const SessionsPage = async ({ scroll={false} > - Add session + New session
)} diff --git a/app/_components/subject-events-date-filter.tsx b/app/_components/subject-events-date-filter.tsx index 0259d877..8f930159 100644 --- a/app/_components/subject-events-date-filter.tsx +++ b/app/_components/subject-events-date-filter.tsx @@ -49,11 +49,11 @@ const SubjectEventsDateFilter = () => { ) : opDate?.from ? ( formatDate(opDate.from, { weekday: undefined }) ) : ( - 'Date range' + 'Filter by date range' )} - + { - const f = formatEventFilters({ from, limit, to }); - - const [{ data: subject }, { data: events }, user] = await Promise.all([ - isPublic ? getPublicSubject(subjectId) : getSubject(subjectId), - isPublic - ? await listPublicEvents(subjectId, f) - : await listEvents(subjectId, f), - getCurrentUser(), - ]); - - if (!subject) return null; - - if (!events?.length) { - return ( - <> -
- - - No events. - - - ); - } - - return ( - - ); -}; - -export default SubjectEventsPage; diff --git a/app/_components/subject-form.tsx b/app/_components/subject-form.tsx index dd7294d3..beed8c18 100644 --- a/app/_components/subject-form.tsx +++ b/app/_components/subject-form.tsx @@ -79,7 +79,7 @@ const SubjectForm = ({ subject }: SubjectFormProps) => { } localStorage.setItem('refresh', '1'); - if (!subject?.id) router.replace(`/subjects/${subjectId}/events`); + if (!subject?.id) router.replace(`/subjects/${subjectId}`); else router.back(); }), )} @@ -89,6 +89,7 @@ const SubjectForm = ({ subject }: SubjectFormProps) => { label="Name" maxLength={49} required + tooltip="Who or what are you tracking?" {...form.register('name')} />
@@ -118,8 +119,8 @@ const SubjectForm = ({ subject }: SubjectFormProps) => { label="Note" tooltip={ <> - Add an optional note to be displayed at the top of the - subject’s profile. + An optional note displayed at the top of the subject’s + profile. } {...field} @@ -130,7 +131,7 @@ const SubjectForm = ({ subject }: SubjectFormProps) => {
Links - Add optional links to be listed at the top of the subject’s + Optional links displayed at the top of the subject’s profile.
diff --git a/app/_components/subject-layout.tsx b/app/_components/subject-layout.tsx deleted file mode 100644 index 61a338a3..00000000 --- a/app/_components/subject-layout.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import Avatar from '@/_components/avatar'; -import BackIconButton from '@/_components/back-icon-button'; -import Button from '@/_components/button'; -import DirtyHtml from '@/_components/dirty-html'; -import EventTypes from '@/_components/event-types'; -import ForwardSearchParamsButton from '@/_components/forward-search-params-button'; -import Missions from '@/_components/missions'; -import ScrollToTopHack from '@/_components/scroll-to-top-hack'; -import SubjectEventsDateFilter from '@/_components/subject-events-date-filter'; -import SubjectMenu from '@/_components/subject-menu'; -import Tip from '@/_components/tip'; -import getCurrentUser from '@/_queries/get-current-user'; -import getPublicSubject from '@/_queries/get-public-subject'; -import getSubject from '@/_queries/get-subject'; -import { SubjectDataJson } from '@/_types/subject-data-json'; -import ArrowLeftIcon from '@heroicons/react/24/outline/ArrowLeftIcon'; -import ArrowTopRightOnSquareIcon from '@heroicons/react/24/outline/ArrowTopRightOnSquareIcon'; -import Bars3Icon from '@heroicons/react/24/outline/Bars3Icon'; -import PlusIcon from '@heroicons/react/24/outline/PlusIcon'; -import { ReactNode } from 'react'; -import { twMerge } from 'tailwind-merge'; - -interface SubjectLayoutProps { - children: ReactNode; - isPublic?: boolean; - subjectId: string; -} - -const SubjectLayout = async ({ - children, - isPublic, - subjectId, -}: SubjectLayoutProps) => { - const [{ data: subject }, user] = await Promise.all([ - isPublic ? getPublicSubject(subjectId) : getSubject(subjectId), - getCurrentUser(), - ]); - - if (!subject) return null; - const isTeamMember = !!user && subject.team_id === user.id; - const shareOrSubjects = isPublic ? 'share' : 'subjects'; - const subjectData = subject.data as SubjectDataJson; - - return ( -
- -
-
- {!isPublic && ( - } - label="Back" - /> - )} -

{subject.name}

-
- {isTeamMember ? ( - -
- - -
-
- ) : ( - - )} -
- {!isPublic && ( -
- {!subject.archived && isTeamMember && ( -
- -

- Event types{' '} - define the events that can be recorded at any time. -

-

- Training plans{' '} - are long-term behavior modification plans for clients. -

-
- - -
- )} -
- {subjectData?.banner && ( - - {subjectData?.banner} - - )} - {!!subjectData?.links?.length && ( - - )} -
- {!subject.archived && ( - <> - - - - )} -
- )} -
-
- - Events - - - Insights - -
- -
- {children} -
- ); -}; - -export default SubjectLayout; diff --git a/app/_components/subject-list.tsx b/app/_components/subject-list.tsx index 3b367794..aaa37350 100644 --- a/app/_components/subject-list.tsx +++ b/app/_components/subject-list.tsx @@ -24,7 +24,7 @@ const SubjectList = async ({ > + +
+ )} + {(subjectData?.banner || !!subjectData?.links?.length) && ( +
+ {subjectData?.banner && ( + + {subjectData?.banner} + + )} + {!!subjectData?.links?.length && ( + + )} +
+ )} + {!subject.archived && ( + <> + + + + )} +
+ )} +
+ + + + Insights + +
+ {!!events?.length ? ( + + ) : ( + <> +
+ + + No events. + + + )} +
+ ); +}; + +export default SubjectPage; diff --git a/app/_components/mission-form.tsx b/app/_components/training-plan-form.tsx similarity index 75% rename from app/_components/mission-form.tsx rename to app/_components/training-plan-form.tsx index 686ebc7c..7aee1286 100644 --- a/app/_components/mission-form.tsx +++ b/app/_components/training-plan-form.tsx @@ -3,25 +3,25 @@ import BackButton from '@/_components/back-button'; import Button from '@/_components/button'; import Input from '@/_components/input'; -import upsertMission from '@/_mutations/upsert-mission'; -import { GetMissionData } from '@/_queries/get-mission'; +import upsertTrainingPlan from '@/_mutations/upsert-training-plan'; +import { GetTrainingPlanData } from '@/_queries/get-training-plan'; import { useRouter } from 'next/navigation'; import { useTransition } from 'react'; import { useForm } from 'react-hook-form'; -interface MissionFormProps { - mission?: NonNullable; +interface TrainingPlanFormProps { + mission?: NonNullable; subjectId: string; } -interface MissionFormValues { +interface TrainingPlanFormValues { name: string; } -const MissionForm = ({ mission, subjectId }: MissionFormProps) => { +const TrainingPlanForm = ({ mission, subjectId }: TrainingPlanFormProps) => { const [isTransitioning, startTransition] = useTransition(); - const form = useForm({ + const form = useForm({ defaultValues: { name: mission?.name }, }); @@ -31,7 +31,7 @@ const MissionForm = ({ mission, subjectId }: MissionFormProps) => { startTransition(async () => { - const res = await upsertMission( + const res = await upsertTrainingPlan( { missionId: mission?.id, subjectId }, values, ); @@ -58,6 +58,7 @@ const MissionForm = ({ mission, subjectId }: MissionFormProps) => { label="Name" maxLength={49} required + tooltip="Succinctly describe the goal or purpose of the training plan." {...form.register('name')} />
@@ -83,5 +84,5 @@ const MissionForm = ({ mission, subjectId }: MissionFormProps) => { ); }; -export type { MissionFormValues }; -export default MissionForm; +export type { TrainingPlanFormValues }; +export default TrainingPlanForm; diff --git a/app/_components/mission-menu.tsx b/app/_components/training-plan-menu.tsx similarity index 85% rename from app/_components/mission-menu.tsx rename to app/_components/training-plan-menu.tsx index e4a5f05c..51282a86 100644 --- a/app/_components/mission-menu.tsx +++ b/app/_components/training-plan-menu.tsx @@ -2,18 +2,18 @@ import Alert from '@/_components/alert'; import DropdownMenu from '@/_components/dropdown-menu'; -import deleteMission from '@/_mutations/delete-mission'; +import deleteTrainingPlan from '@/_mutations/delete-training-plan'; import EllipsisVerticalIcon from '@heroicons/react/24/outline/EllipsisVerticalIcon'; import PencilIcon from '@heroicons/react/24/outline/PencilIcon'; import TrashIcon from '@heroicons/react/24/outline/TrashIcon'; import { useToggle } from '@uidotdev/usehooks'; -interface MissionMenuProps { +interface TrainingPlanMenuProps { missionId: string; subjectId: string; } -const MissionMenu = ({ missionId, subjectId }: MissionMenuProps) => { +const TrainingPlanMenu = ({ missionId, subjectId }: TrainingPlanMenuProps) => { const [deleteAlert, toggleDeleteAlert] = useToggle(false); return ( @@ -46,10 +46,10 @@ const MissionMenu = ({ missionId, subjectId }: MissionMenuProps) => { isConfirmingText="Deleting…" isOpen={deleteAlert} onClose={toggleDeleteAlert} - onConfirm={() => deleteMission(missionId)} + onConfirm={() => deleteTrainingPlan(missionId)} /> ); }; -export default MissionMenu; +export default TrainingPlanMenu; diff --git a/app/_components/missions.tsx b/app/_components/training-plans.tsx similarity index 82% rename from app/_components/missions.tsx rename to app/_components/training-plans.tsx index fce66340..5fc3e8f8 100644 --- a/app/_components/missions.tsx +++ b/app/_components/training-plans.tsx @@ -1,6 +1,6 @@ import Button from '@/_components/button'; -import MissionMenu from '@/_components/mission-menu'; -import listSubjectMissions from '@/_queries/list-subject-missions'; +import TrainingPlanMenu from '@/_components/training-plan-menu'; +import listSubjectTrainingPlans from '@/_queries/list-subject-training-plans'; import ArrowUpRightIcon from '@heroicons/react/24/outline/ArrowUpRightIcon'; import { ReactElement } from 'react'; import { twMerge } from 'tailwind-merge'; @@ -10,8 +10,8 @@ interface MissionsProps { subjectId: string; } -const Missions = async ({ isTeamMember, subjectId }: MissionsProps) => { - const { data: missions } = await listSubjectMissions(subjectId); +const TrainingPlans = async ({ isTeamMember, subjectId }: MissionsProps) => { + const { data: missions } = await listSubjectTrainingPlans(subjectId); if (!missions) return null; const listItems = missions.reduce((acc, mission) => { @@ -53,7 +53,7 @@ const Missions = async ({ isTeamMember, subjectId }: MissionsProps) => { )} {isTeamMember && ( - + )} , ); @@ -70,4 +70,4 @@ const Missions = async ({ isTeamMember, subjectId }: MissionsProps) => { ); }; -export default Missions; +export default TrainingPlans; diff --git a/app/_mutations/delete-mission.ts b/app/_mutations/delete-training-plan.ts similarity index 75% rename from app/_mutations/delete-mission.ts rename to app/_mutations/delete-training-plan.ts index 13ead4bc..5686c09e 100644 --- a/app/_mutations/delete-mission.ts +++ b/app/_mutations/delete-training-plan.ts @@ -3,9 +3,9 @@ import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; import { revalidatePath } from 'next/cache'; -const deleteMission = async (id: string) => { +const deleteTrainingPlan = async (id: string) => { await createServerSupabaseClient().from('missions').delete().eq('id', id); revalidatePath('/', 'layout'); }; -export default deleteMission; +export default deleteTrainingPlan; diff --git a/app/_mutations/upsert-insight.ts b/app/_mutations/upsert-insight.ts index 9f8a3ba2..b249eded 100644 --- a/app/_mutations/upsert-insight.ts +++ b/app/_mutations/upsert-insight.ts @@ -2,6 +2,7 @@ import { InsightFormValues } from '@/_components/insight-form'; import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; +import { revalidatePath } from 'next/cache'; const upsertInsight = async ( context: { insightId?: string; subjectId: string }, @@ -15,6 +16,7 @@ const upsertInsight = async ( }); if (error) return { error: error.message }; + revalidatePath('/', 'layout'); }; export default upsertInsight; diff --git a/app/_mutations/upsert-mission.ts b/app/_mutations/upsert-training-plan.ts similarity index 74% rename from app/_mutations/upsert-mission.ts rename to app/_mutations/upsert-training-plan.ts index 8b3b1648..08241386 100644 --- a/app/_mutations/upsert-mission.ts +++ b/app/_mutations/upsert-training-plan.ts @@ -1,11 +1,11 @@ 'use server'; -import { MissionFormValues } from '@/_components/mission-form'; +import { TrainingPlanFormValues } from '@/_components/training-plan-form'; import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; -const upsertMission = async ( +const upsertTrainingPlan = async ( context: { missionId?: string; subjectId: string }, - data: MissionFormValues, + data: TrainingPlanFormValues, ) => { const supabase = createServerSupabaseClient(); @@ -23,4 +23,4 @@ const upsertMission = async ( return { data: mission }; }; -export default upsertMission; +export default upsertTrainingPlan; diff --git a/app/_queries/get-mission.ts b/app/_queries/get-mission.ts deleted file mode 100644 index 0af7b285..00000000 --- a/app/_queries/get-mission.ts +++ /dev/null @@ -1,12 +0,0 @@ -import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; - -const getMission = (missionId: string) => - createServerSupabaseClient() - .from('missions') - .select('id, name') - .eq('id', missionId) - .single(); - -export type GetMissionData = Awaited>['data']; - -export default getMission; diff --git a/app/_queries/get-public-mission-with-sessions-and-events.ts b/app/_queries/get-public-mission-with-sessions-and-events.ts deleted file mode 100644 index 2e917635..00000000 --- a/app/_queries/get-public-mission-with-sessions-and-events.ts +++ /dev/null @@ -1,10 +0,0 @@ -import getMissionWithSessionsAndEvents from '@/_queries/get-mission-with-sessions-and-events'; -import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; - -const getPublicMissionWithSessionsAndEvents = (missionId: string) => - createServerSupabaseClient().rpc( - 'get_public_mission_with_sessions_and_events', - { public_mission_id: missionId }, - ) as ReturnType; - -export default getPublicMissionWithSessionsAndEvents; diff --git a/app/_queries/get-public-mission-with-sessions.ts b/app/_queries/get-public-mission-with-sessions.ts deleted file mode 100644 index 85b1769b..00000000 --- a/app/_queries/get-public-mission-with-sessions.ts +++ /dev/null @@ -1,9 +0,0 @@ -import getMissionWithSessions from '@/_queries/get-mission-with-sessions'; -import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; - -const getPublicMissionWithSessions = (missionId: string) => - createServerSupabaseClient().rpc('get_public_mission_with_sessions', { - public_mission_id: missionId, - }) as ReturnType; - -export default getPublicMissionWithSessions; diff --git a/app/_queries/get-public-training-plan-with-sessions-and-events.ts b/app/_queries/get-public-training-plan-with-sessions-and-events.ts new file mode 100644 index 00000000..e87dbe26 --- /dev/null +++ b/app/_queries/get-public-training-plan-with-sessions-and-events.ts @@ -0,0 +1,10 @@ +import getTrainingPlanWithSessionsAndEvents from '@/_queries/get-training-plan-with-sessions-and-events'; +import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; + +const getPublicTrainingPlanWithSessionsAndEvents = (trainingPlanId: string) => + createServerSupabaseClient().rpc( + 'get_public_mission_with_sessions_and_events', + { public_mission_id: trainingPlanId }, + ) as ReturnType; + +export default getPublicTrainingPlanWithSessionsAndEvents; diff --git a/app/_queries/get-public-training-plan-with-sessions.ts b/app/_queries/get-public-training-plan-with-sessions.ts new file mode 100644 index 00000000..23cd6098 --- /dev/null +++ b/app/_queries/get-public-training-plan-with-sessions.ts @@ -0,0 +1,9 @@ +import getTrainingPlanWithSessions from '@/_queries/get-training-plan-with-sessions'; +import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; + +const getPublicTrainingPlanWithSessions = (trainingPlanId: string) => + createServerSupabaseClient().rpc('get_public_mission_with_sessions', { + public_mission_id: trainingPlanId, + }) as ReturnType; + +export default getPublicTrainingPlanWithSessions; diff --git a/app/_queries/get-mission-with-sessions-and-events.ts b/app/_queries/get-training-plan-with-sessions-and-events.ts similarity index 70% rename from app/_queries/get-mission-with-sessions-and-events.ts rename to app/_queries/get-training-plan-with-sessions-and-events.ts index 64709dc7..db145c94 100644 --- a/app/_queries/get-mission-with-sessions-and-events.ts +++ b/app/_queries/get-training-plan-with-sessions-and-events.ts @@ -1,7 +1,7 @@ import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; -const getMissionWithSessionsAndEvents = ( - missionId: string, +const getTrainingPlanWithSessionsAndEvents = ( + trainingPlanId: string, { draft } = { draft: false }, ) => createServerSupabaseClient() @@ -22,15 +22,15 @@ const getMissionWithSessionsAndEvents = ( title )`, ) - .eq('id', missionId) + .eq('id', trainingPlanId) .order('order', { referencedTable: 'sessions' }) .not('sessions.draft', 'is', draft ? null : true) .order('draft', { ascending: false, referencedTable: 'sessions' }) .eq('sessions.modules.archived', false) .single(); -export type GetMissionWithSessionsAndEventsData = Awaited< - ReturnType +export type GetTrainingPlanWithSessionsAndEventsData = Awaited< + ReturnType >['data']; -export default getMissionWithSessionsAndEvents; +export default getTrainingPlanWithSessionsAndEvents; diff --git a/app/_queries/get-mission-with-sessions.ts b/app/_queries/get-training-plan-with-sessions.ts similarity index 65% rename from app/_queries/get-mission-with-sessions.ts rename to app/_queries/get-training-plan-with-sessions.ts index e2fa3a88..f05fe767 100644 --- a/app/_queries/get-mission-with-sessions.ts +++ b/app/_queries/get-training-plan-with-sessions.ts @@ -1,20 +1,20 @@ import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; -const getMissionWithSessions = ( - missionId: string, +const getTrainingPlanWithSessions = ( + trainingPlanId: string, { draft } = { draft: false }, ) => createServerSupabaseClient() .from('missions') .select('id, name, sessions(draft, id, order, scheduled_for, title)') - .eq('id', missionId) + .eq('id', trainingPlanId) .order('order', { referencedTable: 'sessions' }) .not('sessions.draft', 'is', draft ? null : true) .order('draft', { ascending: false, referencedTable: 'sessions' }) .single(); -export type GetMissionWithSessionsData = Awaited< - ReturnType +export type GetTrainingPlanWithSessionsData = Awaited< + ReturnType >['data']; -export default getMissionWithSessions; +export default getTrainingPlanWithSessions; diff --git a/app/_queries/get-training-plan.ts b/app/_queries/get-training-plan.ts new file mode 100644 index 00000000..97349023 --- /dev/null +++ b/app/_queries/get-training-plan.ts @@ -0,0 +1,14 @@ +import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; + +const getTrainingPlan = (trainingPlanId: string) => + createServerSupabaseClient() + .from('missions') + .select('id, name') + .eq('id', trainingPlanId) + .single(); + +export type GetTrainingPlanData = Awaited< + ReturnType +>['data']; + +export default getTrainingPlan; diff --git a/app/_queries/list-subject-missions.ts b/app/_queries/list-subject-training-plans.ts similarity index 74% rename from app/_queries/list-subject-missions.ts rename to app/_queries/list-subject-training-plans.ts index 9d9b7f72..c3ff1385 100644 --- a/app/_queries/list-subject-missions.ts +++ b/app/_queries/list-subject-training-plans.ts @@ -1,6 +1,6 @@ import createServerSupabaseClient from '@/_utilities/create-server-supabase-client'; -const listSubjectMissions = (subjectId: string) => +const listSubjectTrainingPlans = (subjectId: string) => createServerSupabaseClient() .from('missions') .select( @@ -16,8 +16,8 @@ const listSubjectMissions = (subjectId: string) => }) .eq('sessions.modules.archived', false); -export type ListSubjectMissionsData = Awaited< - ReturnType +export type ListSubjectTrainingPlansData = Awaited< + ReturnType >['data']; -export default listSubjectMissions; +export default listSubjectTrainingPlans;