diff --git a/src/actions/admin.ts b/src/actions/admin.ts index 974d49d..e3f82a6 100644 --- a/src/actions/admin.ts +++ b/src/actions/admin.ts @@ -3,7 +3,7 @@ import { adminAction } from "@/lib/server/safe-action"; import { z } from "zod"; import { db } from "@/db"; -import { suborgs, cohorts } from "@/db/schema"; +import { suborgs, teams } from "@/db/schema"; import { eq } from "drizzle-orm"; import { nanoid } from "nanoid"; @@ -29,7 +29,7 @@ export const createSuborg = adminAction return suborg[0]; }); -export const createCohort = adminAction +export const createTeam = adminAction .schema( z.object({ suborgSlug: z.string().min(1), @@ -49,8 +49,8 @@ export const createCohort = adminAction throw new Error("Suborg not found"); } - const cohort = await db - .insert(cohorts) + const team = await db + .insert(teams) .values({ id: nanoid(8), name, @@ -60,5 +60,5 @@ export const createCohort = adminAction }) .returning(); - return cohort[0]; + return team[0]; }); diff --git a/src/actions/settings.ts b/src/actions/settings.ts index 20ee12a..3cba608 100644 --- a/src/actions/settings.ts +++ b/src/actions/settings.ts @@ -2,7 +2,7 @@ "use server"; import { z } from "zod"; -import { userToCohorts } from "@/db/schema"; +import { userToTeams } from "@/db/schema"; import { revalidatePath } from "next/cache"; import { authedAction } from "@/lib/server/safe-action"; import { and, eq } from "drizzle-orm"; @@ -11,91 +11,91 @@ import { UserSettingsSchema } from "@/lib/zod"; import { user } from "@/db/schema"; -// Schema for joining a cohort -const joinCohortSchema = z.object({ - cohortId: z.string(), +// Schema for joining a team +const joinTeamSchema = z.object({ + teamId: z.string(), }); -// Action to join a cohort -export const joinCohort = authedAction - .schema(joinCohortSchema) +// Action to join a team +export const joinTeam = authedAction + .schema(joinTeamSchema) .action(async ({ ctx, parsedInput }) => { - const { cohortId } = parsedInput; + const { teamId } = parsedInput; const userId = ctx.session.user.id; try { - // Check if user is already in the cohort - const existingLink = await db.query.userToCohorts.findFirst({ + // Check if user is already in the team + const existingLink = await db.query.userToTeams.findFirst({ where: (link, { eq, and }) => - and(eq(link.userId, userId), eq(link.cohortId, cohortId)), + and(eq(link.userId, userId), eq(link.teamId, teamId)), }); if (existingLink) { return { success: false, - message: "Already a member of this cohort", + message: "Already a member of this team", }; } - // Add user to cohort - await db.insert(userToCohorts).values({ + // Add user to team + await db.insert(userToTeams).values({ userId, - cohortId, + teamId, }); // Revalidate the settings page to reflect the changes revalidatePath("/settings"); - return { success: true, message: "Successfully joined cohort" }; + return { success: true, message: "Successfully joined team" }; } catch (error) { - console.error("Error joining cohort:", error); - return { success: false, message: "Failed to join cohort" }; + console.error("Error joining team:", error); + return { success: false, message: "Failed to join team" }; } }); -// Schema for leaving a cohort -const leaveCohortSchema = z.object({ - cohortId: z.string(), +// Schema for leaving a team +const leaveTeamSchema = z.object({ + teamId: z.string(), }); -// Action to leave a cohort -export const leaveCohort = authedAction - .schema(leaveCohortSchema) +// Action to leave a team +export const leaveTeam = authedAction + .schema(leaveTeamSchema) .action(async ({ ctx, parsedInput }) => { - const { cohortId } = parsedInput; + const { teamId } = parsedInput; const userId = ctx.session.user.id; try { - // Check if user is in the cohort - const existingLink = await db.query.userToCohorts.findFirst({ + // Check if user is in the team + const existingLink = await db.query.userToTeams.findFirst({ where: (link, { eq, and }) => - and(eq(link.userId, userId), eq(link.cohortId, cohortId)), + and(eq(link.userId, userId), eq(link.teamId, teamId)), }); if (!existingLink) { return { success: false, - message: "Not a member of this cohort", + message: "Not a member of this team", }; } - // Remove user from cohort + // Remove user from team await db - .delete(userToCohorts) + .delete(userToTeams) .where( and( - eq(userToCohorts.userId, userId), - eq(userToCohorts.cohortId, cohortId), + eq(userToTeams.userId, userId), + eq(userToTeams.teamId, teamId), ), ); // Revalidate the settings page to reflect the changes revalidatePath("/settings"); - return { success: true, message: "Successfully left cohort" }; + return { success: true, message: "Successfully left team" }; } catch (error) { - console.error("Error leaving cohort:", error); - return { success: false, message: "Failed to leave cohort" }; + console.error("Error leaving team:", error); + return { success: false, message: "Failed to leave team" }; } }); diff --git a/src/app/(core)/admin/teams/client.tsx b/src/app/(core)/admin/teams/client.tsx index 665ed24..0010955 100644 --- a/src/app/(core)/admin/teams/client.tsx +++ b/src/app/(core)/admin/teams/client.tsx @@ -15,7 +15,7 @@ import { } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { Plus } from "lucide-react"; -import { createSuborg, createCohort } from "@/actions/admin"; +import { createSuborg, createTeam } from "@/actions/admin"; import { toast } from "sonner"; import { useAction } from "next-safe-action/hooks"; @@ -66,7 +66,7 @@ export function CreateSuborgDialog() { Create new suborg Create a new suborg below! Note that this is not the - same as making a cohort. + same as making a team.
@@ -107,7 +107,7 @@ interface Suborg { shortname: string; } -export function CreateCohortDialog({ suborgs }: { suborgs: Suborg[] }) { +export function CreateTeamDialog({ suborgs }: { suborgs: Suborg[] }) { const [open, setOpen] = useState(false); const [suborgSlug, setSuborgSlug] = useState(""); const [name, setName] = useState(""); @@ -116,7 +116,7 @@ export function CreateCohortDialog({ suborgs }: { suborgs: Suborg[] }) { const [isSubmitting, setIsSubmitting] = useState(false); const router = useRouter(); - const { executeAsync } = useAction(createCohort); + const { executeAsync } = useAction(createTeam); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); @@ -131,7 +131,7 @@ export function CreateCohortDialog({ suborgs }: { suborgs: Suborg[] }) { }); if (result && result.data) { - toast.success("Cohort created successfully!"); + toast.success("Team created successfully!"); setOpen(false); setSuborgSlug(""); setName(""); @@ -152,14 +152,14 @@ export function CreateCohortDialog({ suborgs }: { suborgs: Suborg[] }) { - Create new cohort + Create new team - Create a new cohort for a suborg. + Create a new team for a suborg. @@ -183,7 +183,7 @@ export function CreateCohortDialog({ suborgs }: { suborgs: Suborg[] }) {
- + diff --git a/src/app/(core)/admin/teams/page.tsx b/src/app/(core)/admin/teams/page.tsx index 1853a98..3c42d3e 100644 --- a/src/app/(core)/admin/teams/page.tsx +++ b/src/app/(core)/admin/teams/page.tsx @@ -9,7 +9,7 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; -import { CreateSuborgDialog, CreateCohortDialog } from "./client"; +import { CreateSuborgDialog, CreateTeamDialog } from "./client"; export default async function Page() { const session = await getSession(); @@ -35,11 +35,11 @@ export default async function Page() {

- Cohorts + Teams

- +
- +
); @@ -70,8 +70,8 @@ async function SuborgShowcase() { ); } -async function CohortShowcase() { - const cohorts = await db.query.cohorts.findMany(); +async function TeamShowcase() { + const teams = await db.query.teams.findMany(); return (
@@ -84,18 +84,18 @@ async function CohortShowcase() { - {cohorts && cohorts.length > 0 ? ( - cohorts.map((cohort) => ( - - {cohort.name} - {cohort.suborgSlug} + {teams && teams.length > 0 ? ( + teams.map((team) => ( + + {team.name} + {team.suborgSlug} {new Date( - cohort.startDate, + team.startDate, ).toLocaleDateString()}{" "} -{" "} {new Date( - cohort.endDate, + team.endDate, ).toLocaleDateString()} @@ -103,7 +103,7 @@ async function CohortShowcase() { ) : ( - No cohorts found + No team found )} diff --git a/src/app/(core)/settings/client.tsx b/src/app/(core)/settings/client.tsx index 1ea05fa..291d5eb 100644 --- a/src/app/(core)/settings/client.tsx +++ b/src/app/(core)/settings/client.tsx @@ -16,53 +16,53 @@ import { import { Button } from "@/components/ui/button"; import { ChevronsUpDown, Check } from "lucide-react"; import { cn } from "@/lib/shared/utils"; -import { joinCohort } from "@/actions/settings"; +import { joinTeam } from "@/actions/settings"; import { toast } from "sonner"; import { useOptimisticAction } from "next-safe-action/hooks"; -export function AddCohortCombobox({ - cohorts, - userCohorts, +export function AddTeamCombobox({ + teams, + userTeams, }: { - cohorts: { id: string; name: string }[]; - userCohorts: { id: string; name: string }[]; + teams: { id: string; name: string }[]; + userTeams: { id: string; name: string }[]; }) { const [open, setOpen] = useState(false); const [value, setValue] = useState(""); - // Use optimistic action to instantly show the user in the new cohort - const { execute, isPending } = useOptimisticAction(joinCohort, { - // Pass current cohort state - currentState: { userCohorts }, + // Use optimistic action to instantly show the user in the new team + const { execute, isPending } = useOptimisticAction(joinTeam, { + // Pass current team state + currentState: { userTeams }, // Update optimistically before server responds updateFn: (state, input) => { - const selectedCohort = cohorts.find((c) => c.id === input.cohortId); - if (!selectedCohort) return state; + const selectedTeam = teams.find((c) => c.id === input.teamId); + if (!selectedTeam) return state; - // Add the selected cohort to user's cohorts + // Add the selected team to user's teams return { - userCohorts: [...state.userCohorts, selectedCohort], + userTeams: [...state.userTeams, selectedTeam], }; }, // Handle successful action onSuccess: (result) => { if (result.data?.success) { toast.success( - result.data.message || "Successfully joined cohort", + result.data.message || "Successfully joined team", ); } else { - toast.error(result.data?.message || "Failed to join cohort"); + toast.error(result.data?.message || "Failed to join team"); } }, // Handle errors onError: (error) => { - console.error("Error joining cohort:", error); + console.error("Error joining team:", error); toast.error("An unexpected error occurred"); }, }); - const handleJoinCohort = (cohortId: string) => { - execute({ cohortId }); + const handleJoinTeam = (teamId: string) => { + execute({ teamId }); }; return ( @@ -76,21 +76,21 @@ export function AddCohortCombobox({ disabled={isPending} > {value - ? cohorts.find((c) => c.id === value)?.name - : "Add to cohort..."} + ? teams.find((c) => c.id === value)?.name + : "Add to team..."} - + - No cohorts found. + No teams found. - {cohorts.map((cohort) => ( + {teams.map((team) => ( { setValue( currentValue === value @@ -99,9 +99,9 @@ export function AddCohortCombobox({ ); setOpen(false); - // Join the selected cohort + // Join the selected team if (currentValue !== value) { - handleJoinCohort(currentValue); + handleJoinTeam(currentValue); } }} disabled={isPending} @@ -109,12 +109,12 @@ export function AddCohortCombobox({ - {cohort.name} + {team.name} ))} @@ -125,4 +125,4 @@ export function AddCohortCombobox({ ); } -export default AddCohortCombobox; +export default AddTeamCombobox; diff --git a/src/app/(core)/settings/page.tsx b/src/app/(core)/settings/page.tsx index beeccc9..6f1d0f7 100644 --- a/src/app/(core)/settings/page.tsx +++ b/src/app/(core)/settings/page.tsx @@ -2,10 +2,10 @@ import { getSession } from "@/lib/server/auth"; import { db } from "@/db"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Badge } from "@/components/ui/badge"; -import AddCohortCombobox from "./client"; +import AddTeamCombobox from "./client"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Separator } from "@/components/ui/separator"; -import { CohortBadge } from "./cohort-badge"; +import { TeamBadge } from "./team-badge"; import SettingsForm from "@/components/settings/SettingsForm"; import { Button } from "@/components/ui/button"; import { @@ -18,27 +18,27 @@ import { DialogTrigger, } from "@/components/ui/dialog"; -// Helper to get user's cohorts and all cohorts -async function getUserAndCohorts(userId: string) { - // Get all cohorts - const allCohorts = await db.query.cohorts.findMany(); - // Get user's cohort IDs - const userCohortLinks = await db.query.userToCohorts.findMany({ +// Helper to get user's teamss and all teams +async function getUserAndTeams(userId: string) { + // Get all teams + const allTeams = await db.query.teams.findMany(); + // Get user's team IDs + const userTeamLinks = await db.query.userToTeams.findMany({ where: (link, { eq }) => eq(link.userId, userId), }); - const userCohortIds = userCohortLinks.map((link) => link.cohortId); - const userCohorts = allCohorts.filter((c) => userCohortIds.includes(c.id)); - const addableCohorts = allCohorts.filter( - (c) => !userCohortIds.includes(c.id), + const userTeamIds = userTeamLinks.map((link) => link.teamId); + const userTeams= allTeams.filter((c) => userTeamIds.includes(c.id)); + const addableTeams = allTeams.filter( + (c) => !userTeamIds.includes(c.id), ); - return { userCohorts, addableCohorts }; + return { userTeams, addableTeams }; } export default async function Page() { const session = await getSession(); if (!session) return null; const user = session.user; - const { userCohorts, addableCohorts } = await getUserAndCohorts(user.id); + const { userTeams, addableTeams } = await getUserAndTeams(user.id); return (
@@ -92,27 +92,27 @@ export default async function Page() { - {/* Cohorts */} + {/* Teams */} - Cohorts + Teams
- Your current cohorts + Your current teams
- {userCohorts.length === 0 && ( + {userTeams.length === 0 && ( - You are not in any cohorts. + You are not in any teams. )} - {userCohorts.map((cohort) => ( - ( + ({ id, name }), )} /> @@ -124,14 +124,14 @@ export default async function Page() {
- Join a new cohort + Join a new team
- ({ + ({ id, name, }))} - userCohorts={userCohorts.map( + userTeams={userTeams.map( ({ id, name }) => ({ id, name, diff --git a/src/app/(core)/settings/cohort-badge.tsx b/src/app/(core)/settings/team-badge.tsx similarity index 70% rename from src/app/(core)/settings/cohort-badge.tsx rename to src/app/(core)/settings/team-badge.tsx index 58280fc..2ad8cec 100644 --- a/src/app/(core)/settings/cohort-badge.tsx +++ b/src/app/(core)/settings/team-badge.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import { Badge } from "@/components/ui/badge"; import { X } from "lucide-react"; import { cn } from "@/lib/shared/utils"; -import { leaveCohort } from "@/actions/settings"; +import { leaveTeam } from "@/actions/settings"; import { toast } from "sonner"; import { useOptimisticAction } from "next-safe-action/hooks"; import { @@ -17,25 +17,25 @@ import { } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; -interface CohortBadgeProps { - cohort: { id: string; name: string }; - userCohorts: { id: string; name: string }[]; +interface TeamBadgeProps { + team: { id: string; name: string }; + userTeams: { id: string; name: string }[]; } -export function CohortBadge({ cohort, userCohorts }: CohortBadgeProps) { +export function TeamBadge({ team, userTeams }: TeamBadgeProps) { const [hover, setHover] = useState(false); const [confirmOpen, setConfirmOpen] = useState(false); - // Use optimistic action to instantly remove the cohort from UI - const { execute, isPending } = useOptimisticAction(leaveCohort, { - // Pass current cohort state - currentState: { userCohorts }, + // Use optimistic action to instantly remove the team from UI + const { execute, isPending } = useOptimisticAction(leaveTeam, { + // Pass current team state + currentState: { userTeams }, // Update optimistically before server responds updateFn: (state, input) => { - // Remove the cohort from user's cohorts + // Remove the team from user's teams return { - userCohorts: state.userCohorts.filter( - (c) => c.id !== input.cohortId, + userTeams: state.userTeams.filter( + (c) => c.id !== input.teamId, ), }; }, @@ -43,21 +43,21 @@ export function CohortBadge({ cohort, userCohorts }: CohortBadgeProps) { onSuccess: (result) => { if (result.data?.success) { toast.success( - result.data.message || "Successfully left cohort", + result.data.message || "Successfully left team", ); } else { - toast.error(result.data?.message || "Failed to leave cohort"); + toast.error(result.data?.message || "Failed to leave team"); } }, // Handle errors onError: (error) => { - console.error("Error leaving cohort:", error); + console.error("Error leaving team:", error); toast.error("An unexpected error occurred"); }, }); - const handleLeaveCohort = () => { - execute({ cohortId: cohort.id }); + const handleLeaveTeam = () => { + execute({ teamId: team.id }); setConfirmOpen(false); }; @@ -75,7 +75,7 @@ export function CohortBadge({ cohort, userCohorts }: CohortBadgeProps) { hover ? "pr-6" : "pr-3", )} > - {cohort.name} + {team.name} @@ -97,10 +97,10 @@ export function CohortBadge({ cohort, userCohorts }: CohortBadgeProps) { - Leave Cohort + Leave Team Are you sure you want to leave the{" "} - {cohort.name} cohort? + {team.name} team? @@ -113,7 +113,7 @@ export function CohortBadge({ cohort, userCohorts }: CohortBadgeProps) {