diff --git a/apps/eat-backend/src/trpc/init.ts b/apps/eat-backend/src/trpc/init.ts index d626c9c..fbe3864 100644 --- a/apps/eat-backend/src/trpc/init.ts +++ b/apps/eat-backend/src/trpc/init.ts @@ -25,10 +25,17 @@ const isAuthed = middleware(async ({ ctx, next }) => { const currentUser = await db.users.findOne({ email: (ctx.req.user as any).email, }); - const currentCompetition = await db.competitions.findOne({ + +const currentCompetition = await db.competitions.findOne( + { startDate: { $lte: dayjs().format('YYYY-MM-DD') }, - endDate: { $gte: dayjs().format('YYYY-MM-DD') }, - }); + isActive: true, + }, + { + orderBy: { startDate: 'DESC' }, + } +); + if (!currentUser) { throw new TRPCError({ diff --git a/apps/eat-backend/src/trpc/routers/activities-router.ts b/apps/eat-backend/src/trpc/routers/activities-router.ts index 10dc466..7dba808 100644 --- a/apps/eat-backend/src/trpc/routers/activities-router.ts +++ b/apps/eat-backend/src/trpc/routers/activities-router.ts @@ -141,6 +141,10 @@ export const activitesRouter = router({ throw new Error('No active competition found'); } + if(input.date > currentCompetition.endDate || input.date < currentCompetition.startDate) { + throw new Error('Activity date must be within the competition period'); + } + const activity = db.activities.create({ activityType: input.activityType, date: input.date, diff --git a/apps/eat-backend/src/trpc/routers/competitions-router.ts b/apps/eat-backend/src/trpc/routers/competitions-router.ts index 2be5e96..11ce2aa 100644 --- a/apps/eat-backend/src/trpc/routers/competitions-router.ts +++ b/apps/eat-backend/src/trpc/routers/competitions-router.ts @@ -19,10 +19,15 @@ export const competitionsRouter = router({ }), getCurrent: protectedProcedure.query(async ({ ctx }) => { const db = ctx.db; - const current = await db.competitions.findOne({ - startDate: { $lte: dayjs().format('YYYY-MM-DD') }, - endDate: { $gte: dayjs().format('YYYY-MM-DD') }, - }); +const current = await db.competitions.findOne( + { + startDate: { $lte: dayjs().format('YYYY-MM-DD') }, + isActive: true, + }, + { + orderBy: { startDate: 'DESC' }, + } +); return current; }), diff --git a/apps/eat-web/src/components/datepicker.tsx b/apps/eat-web/src/components/datepicker.tsx index b27db19..e24751d 100644 --- a/apps/eat-web/src/components/datepicker.tsx +++ b/apps/eat-web/src/components/datepicker.tsx @@ -11,7 +11,7 @@ import { import { ControllerRenderProps } from 'react-hook-form'; import { useState } from 'react'; -type DatePickerProps = ControllerRenderProps & { maxDate?: Date }; +type DatePickerProps = ControllerRenderProps & { maxDate?: Date, minDate?: Date }; export function DatePicker(field: DatePickerProps) { const [open, setOpen] = useState(false); @@ -35,11 +35,15 @@ export function DatePicker(field: DatePickerProps) { mode="single" selected={field.value} onSelect={(value) => { - field.onChange(value); - setOpen(false); + field.onChange(value); + setOpen(false); }} initialFocus - disabled={(date) => (field.maxDate ? date > field.maxDate : false)} + disabled={(date) => { + const afterMax = field.maxDate ? date > field.maxDate : false; + const beforeMin = field.minDate ? date < field.minDate : false; + return afterMax || beforeMin; + }} /> diff --git a/apps/eat-web/src/components/forms/add-activity-form.tsx b/apps/eat-web/src/components/forms/add-activity-form.tsx index 060a0de..0fd2c9b 100644 --- a/apps/eat-web/src/components/forms/add-activity-form.tsx +++ b/apps/eat-web/src/components/forms/add-activity-form.tsx @@ -15,6 +15,7 @@ import { trpc } from '@/trpc'; import dayjs from 'dayjs'; import { DatePicker } from '../datepicker'; import { ActivityTypeAutocomplete } from '../activity-type-autocomplete'; +import { useState } from 'react'; const formSchema = z.object({ activityType: z.string().min(1, { message: 'Aktivitetstyp krävs' }), @@ -24,14 +25,18 @@ const formSchema = z.object({ type FormInputs = z.infer; type Props = { + dateInterval: { start: Date; end: Date }; onFinish: () => void; }; export function AddActivityForm(props: Props) { const { onFinish } = props; + const [error, setError] = useState(null); + const submitForm = trpc.activities.create.useMutation({ onError: (error) => { console.log(error); + setError('Ett fel uppstod!'); }, onSuccess: () => { onFinish(); @@ -99,13 +104,19 @@ export function AddActivityForm(props: Props) { Datum - + )} /> + {error && ( +
+ {error} +
+ )} +
diff --git a/apps/eat-web/src/components/navigation/register-activity.tsx b/apps/eat-web/src/components/navigation/register-activity.tsx index e5fd893..a198ab3 100644 --- a/apps/eat-web/src/components/navigation/register-activity.tsx +++ b/apps/eat-web/src/components/navigation/register-activity.tsx @@ -6,6 +6,10 @@ import { trpc } from '@/trpc'; export const RegisterActivity = () => { const { openModal, closeModal, modalName } = useModal(); + const currentCompetitionQuery = trpc.competitions.getCurrent.useQuery(); + + if(!currentCompetitionQuery.data) return null; + const utils = trpc.useUtils(); return ( <> @@ -18,6 +22,10 @@ export const RegisterActivity = () => { { closeModal(); void utils.activities.invalidate(); diff --git a/apps/eat-web/src/pages/register-activity.tsx b/apps/eat-web/src/pages/register-activity.tsx index 81e6085..505dad0 100644 --- a/apps/eat-web/src/pages/register-activity.tsx +++ b/apps/eat-web/src/pages/register-activity.tsx @@ -7,6 +7,7 @@ import { trpc } from '@/trpc'; export const AddActivityPage = () => { const { data, refetch } = trpc.competitions.list.useQuery(); + const currentCompetitionQuery = trpc.competitions.getCurrent.useQuery(); const { modalName, openModal, closeModal } = useModal(); if (!data) return null; @@ -14,18 +15,26 @@ export const AddActivityPage = () => {

Aktivitet

- -
- - { - closeModal(); - refetch(); - }} - /> - + {currentCompetitionQuery.data && ( + + )} +
+ {currentCompetitionQuery.data && ( + + { + closeModal(); + refetch(); + }} + /> + + )} ); };