Skip to content

Commit 675a7d1

Browse files
committed
Merge remote-tracking branch 'origin/dev' into cf-stable
2 parents e3eb426 + d891e7c commit 675a7d1

23 files changed

+567
-285
lines changed

apps/web/next-env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
/// <reference types="next/image-types/global" />
33

44
// NOTE: This file should not be edited
5-
// see https://nextjs.org/docs/basic-features/typescript for more information.
5+
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@radix-ui/react-checkbox": "^1.0.4",
2626
"@radix-ui/react-dialog": "^1.0.5",
2727
"@radix-ui/react-dropdown-menu": "^2.0.6",
28+
"@radix-ui/react-hover-card": "^1.1.6",
2829
"@radix-ui/react-label": "^2.0.2",
2930
"@radix-ui/react-popover": "^1.0.7",
3031
"@radix-ui/react-progress": "^1.1.2",

apps/web/src/actions/checkin.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,43 @@ import { UNIQUE_KEY_CONSTRAINT_VIOLATION_CODE } from "@/lib/constants/";
66
import { checkInUserClient, checkInUserList } from "@/lib/queries/checkins";
77
import { adminCheckinSchema, universityIDSplitter } from "db/zod";
88
import { CheckinResult } from "@/lib/types/events";
9-
import { revalidatePath } from "next/cache";
109
import { headers } from "next/headers";
10+
import { getEventById } from "@/lib/queries/events";
11+
import { returnValidationErrors } from "next-safe-action";
12+
import z from "zod";
13+
import { isWithinInterval } from "date-fns";
1114

12-
const { ALREADY_CHECKED_IN, SUCCESS, FAILED, SOME_FAILED } = CheckinResult;
15+
const {
16+
ALREADY_CHECKED_IN,
17+
SUCCESS,
18+
FAILED,
19+
SOME_FAILED,
20+
EVENT_NOT_FOUND,
21+
CHECKIN_NOT_AVAILABLE,
22+
} = CheckinResult;
1323

1424
export const checkInUserAction = userAction
1525
.schema(userCheckinSchemaFormified)
1626
.action(async ({ parsedInput }) => {
27+
const { eventID } = parsedInput;
28+
const event = await getEventById(eventID);
29+
if (!event) {
30+
returnValidationErrors(z.null(), {
31+
_errors: [EVENT_NOT_FOUND],
32+
});
33+
}
34+
35+
const currentDateUTC = new Date();
36+
const isCheckinAvailable = isWithinInterval(currentDateUTC, {
37+
start: event.checkinStart,
38+
end: event.checkinEnd,
39+
});
40+
if (!isCheckinAvailable) {
41+
returnValidationErrors(z.null(), {
42+
_errors: [CHECKIN_NOT_AVAILABLE],
43+
});
44+
}
45+
1746
try {
1847
await checkInUserClient(parsedInput);
1948
} catch (e) {

apps/web/src/app/settings/page.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,6 @@ export default async function UserSettingsProfilePage() {
3636
const authClient = await clerkClient();
3737
const user = await authClient.users.getUser(userId);
3838

39-
const params = new URLSearchParams({
40-
height: "112",
41-
width: "112",
42-
quality: "100",
43-
fit: "crop",
44-
});
45-
4639
return (
4740
<div className="flex flex-col gap-10">
4841
<Card id="account">
@@ -80,9 +73,7 @@ export default async function UserSettingsProfilePage() {
8073
<Separator />
8174
</div>
8275
<CardContent className="space-y-12">
83-
<ChangeProfilePictureForm
84-
profilePicture={`${user.imageUrl}?${params.toString()}`}
85-
/>
76+
<ChangeProfilePictureForm profilePicture={user.imageUrl} />
8677
<ChangeResumeForm
8778
resume={userSettings.data.resume ?? undefined}
8879
/>

apps/web/src/components/dash/UserDash.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export default async function UserDash({
140140
<GraduationCapIcon className="mr-2 h-4 w-4" />
141141
{`${userData.major}, ${userData.graduationYear}`}
142142
</p>
143-
<p className="mt-2 flex items-center text-balance text-base text-muted-foreground">
143+
<p className="text-balance mt-2 flex items-center text-base text-muted-foreground">
144144
{`Member since ${joinedDate}`}
145145
</p>
146146
{/* come back and configure wrangler json */}

apps/web/src/components/dash/admin/events/EditEventForm.tsx

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ import {
2929
} from "@/components/ui/alert-dialog";
3030
import { Switch } from "@/components/ui/switch";
3131
import { useState, useEffect } from "react";
32-
import { cn } from "@/lib/utils";
33-
import { format } from "date-fns";
32+
import { isAfter, addHours, isBefore } from "date-fns";
3433
import { getLocalTimeZone, parseAbsolute } from "@internationalized/date";
3534
import { Button } from "@/components/ui/button";
3635
import { Input } from "@/components/ui/input";
@@ -126,6 +125,30 @@ export default function EditEventForm({
126125
return true;
127126
}
128127

128+
const eventStartTime = form.watch("start");
129+
const eventEndTime = form.watch("end");
130+
const checkinStartTime = form.watch("checkinStart");
131+
const checkinEndTime = form.watch("checkinEnd");
132+
133+
useEffect(() => {
134+
if (isAfter(eventStartTime, eventEndTime)) {
135+
form.setValue("end", addHours(eventStartTime, 1));
136+
}
137+
}, [eventStartTime]);
138+
139+
useEffect(() => {
140+
if (isAfter(checkinStartTime, checkinEndTime)) {
141+
form.setValue("checkinEnd", addHours(checkinStartTime, 1));
142+
}
143+
}, [checkinStartTime]);
144+
145+
useEffect(() => {
146+
if (isBefore(checkinEndTime, eventEndTime)) {
147+
form.setValue("checkinStart", eventStartTime);
148+
form.setValue("checkinEnd", eventEndTime);
149+
}
150+
}, [eventEndTime]);
151+
129152
useEffect(() => {
130153
if (Object.keys(form.formState.errors).length > 0) {
131154
console.log("Errors: ", form.formState.errors);

apps/web/src/components/dash/admin/events/NewEventForm.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import { useAction } from "next-safe-action/hooks";
4545
import { put } from "@/lib/client/file-upload";
4646
import { createEvent } from "@/actions/events/createNewEvent";
4747
import { ONE_HOUR_IN_MILLISECONDS } from "@/lib/constants";
48-
import { bucketEventThumbnailBaseUrl } from "config";
4948
import type { NewEventFormProps } from "@/lib/types/events";
5049
import {
5150
Select,
@@ -54,6 +53,7 @@ import {
5453
SelectTrigger,
5554
SelectValue,
5655
} from "@/components/ui/select";
56+
import { isAfter, isBefore, addHours } from "date-fns";
5757

5858
const formSchema = insertEventSchemaFormified;
5959

@@ -116,6 +116,33 @@ export default function NewEventForm({
116116
return true;
117117
}
118118

119+
const eventStartTime = form.watch("start");
120+
const eventEndTime = form.watch("end");
121+
const checkinStartTime = form.watch("checkinStart");
122+
const checkinEndTime = form.watch("checkinEnd");
123+
124+
useEffect(() => {
125+
if (isAfter(eventStartTime, eventEndTime)) {
126+
form.setValue("end", addHours(eventStartTime, 1));
127+
}
128+
}, [eventStartTime]);
129+
130+
useEffect(() => {
131+
if (
132+
isAfter(checkinStartTime, checkinEndTime) &&
133+
hasDifferentCheckinTime
134+
) {
135+
form.setValue("checkinEnd", addHours(checkinStartTime, 1));
136+
}
137+
}, [checkinStartTime]);
138+
139+
useEffect(() => {
140+
if (isBefore(checkinEndTime, eventEndTime) && hasDifferentCheckinTime) {
141+
form.setValue("checkinStart", eventStartTime);
142+
form.setValue("checkinEnd", eventEndTime);
143+
}
144+
}, [eventEndTime]);
145+
119146
const {
120147
execute: runCreateEvent,
121148
status: actionStatus,

apps/web/src/components/dash/admin/members/MemberStatsSheet.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ async function MemberStatsSheet({}: Props) {
1616
{
1717
label: "Active Members",
1818
value: stats.activeMembers,
19+
description:
20+
"An active member is defined as a member who has checked in at least once this semester.",
1921
},
2022
];
2123

apps/web/src/components/dash/admin/overview/KeyMetrics.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
CheckCircleIcon,
1111
BarChart,
1212
ArrowUpIcon,
13+
ArrowDownIcon,
1314
UsersIcon,
1415
TrendingUpIcon,
1516
} from "lucide-react";
@@ -117,7 +118,11 @@ export default async function KeyMetrics() {
117118
<div className="text-xl font-bold sm:text-2xl">
118119
{growthRate}%
119120
</div>
120-
<ArrowUpIcon className="h-3 w-3 text-green-500 sm:h-4 sm:w-4" />
121+
{growthRate > 0 ? (
122+
<ArrowUpIcon className="h-4 w-4 text-green-500" />
123+
) : growthRate < 0 ? (
124+
<ArrowDownIcon className="h-4 w-4 text-red-500" />
125+
) : null}
121126
</div>
122127
<p className="text-xs text-muted-foreground">
123128
vs last month

apps/web/src/components/dash/shared/StatItem.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
11
import React from "react";
2-
2+
import {
3+
HoverCard,
4+
HoverCardContent,
5+
HoverCardTrigger,
6+
} from "@/components/ui/hover-card";
7+
import { Info } from "lucide-react";
38
export type StatItemProps = {
49
label: string;
510
value: number | string;
11+
description?: string;
612
};
713

814
/**
915
* Reusable component for displaying a single statistic with a label and value
1016
*/
11-
function StatItem({ label, value }: StatItemProps) {
17+
function StatItem({ label, value, description }: StatItemProps) {
1218
return (
1319
<div className="flex flex-col p-1">
14-
<span className="text-xs text-muted-foreground">{label}</span>
20+
<div className="flex flex-row items-center space-x-1">
21+
<span className="text-xs text-muted-foreground">{label}</span>
22+
{description && (
23+
<HoverCard>
24+
<HoverCardTrigger className="">
25+
<Info className="h-3 w-3" />
26+
</HoverCardTrigger>
27+
<HoverCardContent className="text-xs">
28+
{description}
29+
</HoverCardContent>
30+
</HoverCard>
31+
)}
32+
</div>
1533
<span className="text-lg font-semibold">{value}</span>
1634
</div>
1735
);

0 commit comments

Comments
 (0)