Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions apps/eat-backend/src/trpc/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
4 changes: 4 additions & 0 deletions apps/eat-backend/src/trpc/routers/activities-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 9 additions & 4 deletions apps/eat-backend/src/trpc/routers/competitions-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}),
Expand Down
12 changes: 8 additions & 4 deletions apps/eat-web/src/components/datepicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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;
}}
/>
</PopoverContent>
</Popover>
Expand Down
13 changes: 12 additions & 1 deletion apps/eat-web/src/components/forms/add-activity-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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' }),
Expand All @@ -24,14 +25,18 @@ const formSchema = z.object({
type FormInputs = z.infer<typeof formSchema>;

type Props = {
dateInterval: { start: Date; end: Date };
onFinish: () => void;
};
export function AddActivityForm(props: Props) {
const { onFinish } = props;

const [error, setError] = useState<string | null>(null);

const submitForm = trpc.activities.create.useMutation({
onError: (error) => {
console.log(error);
setError('Ett fel uppstod!');
},
onSuccess: () => {
onFinish();
Expand Down Expand Up @@ -99,13 +104,19 @@ export function AddActivityForm(props: Props) {
<FormItem className="flex flex-col">
<FormLabel>Datum</FormLabel>
<FormControl>
<DatePicker {...field} maxDate={dayjs().toDate()} />
<DatePicker {...field} maxDate={props.dateInterval.end} minDate={props.dateInterval.start} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>

{error && (
<div className="text-red-500 text-sm mt-2">
{error}
</div>
)}

<div className="flex justify-end pt-4">
<Button type="submit">Lägg till</Button>
</div>
Expand Down
8 changes: 8 additions & 0 deletions apps/eat-web/src/components/navigation/register-activity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<>
Expand All @@ -18,6 +22,10 @@ export const RegisterActivity = () => {

<Modal isOpen={modalName === 'register-activity'}>
<AddActivityForm
dateInterval={{
start: new Date(currentCompetitionQuery.data.startDate),
end: new Date(currentCompetitionQuery.data.endDate),
}}
onFinish={() => {
closeModal();
void utils.activities.invalidate();
Expand Down
33 changes: 21 additions & 12 deletions apps/eat-web/src/pages/register-activity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,34 @@ 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;
return (
<div className="flex-1 flex flex-col gap-2 pt-4">
<div className="flex justify-between items-center">
<h1 className="text-3xl font-semibold">Aktivitet</h1>
<Button className="dark" onClick={() => openModal('comp')}>
Lägg till
</Button>
</div>
<Modal isOpen={modalName === 'comp'}>
<AddActivityForm
onFinish={() => {
closeModal();
refetch();
}}
/>
</Modal>
{currentCompetitionQuery.data && (
<Button className="dark" onClick={() => openModal('comp')}>
Lägg till
</Button>
)}
</div>
{currentCompetitionQuery.data && (
<Modal isOpen={modalName === 'comp'}>
<AddActivityForm
dateInterval={{
start: new Date(currentCompetitionQuery.data.startDate),
end: new Date(currentCompetitionQuery.data.endDate),
}}
onFinish={() => {
closeModal();
refetch();
}}
/>
</Modal>
)}
</div>
);
};