diff --git a/src/components/card-course-group.tsx b/src/components/card-course-group.tsx index 2813272..bfd21a3 100644 --- a/src/components/card-course-group.tsx +++ b/src/components/card-course-group.tsx @@ -1,7 +1,11 @@ +"use client" + import { cva, type VariantProps } from "class-variance-authority" import type { IconType } from "react-icons" import { FaWhatsapp } from "react-icons/fa" +import { FiFlag } from "react-icons/fi" import { LiaTelegramPlane } from "react-icons/lia" +import { ReportFinderDialog } from "@/components/groups/report/finder-dialog" import { cn } from "@/lib/utils" import { Card, CardAction, CardTitle } from "./ui/card" @@ -23,16 +27,20 @@ export const cardCourseGroupVariants = cva( export function CardCourseGroup({ groupName, waLink, + waGroupId, iconWhatsApp: IconWhatsApp = FaWhatsapp, tgLink, + tgGroupId, iconTelegram: IconTelegram = LiaTelegramPlane, secondary = false, stacked = false, }: { groupName: string waLink?: string + waGroupId?: number iconWhatsApp?: IconType tgLink?: string + tgGroupId?: number iconTelegram?: IconType stacked?: boolean } & VariantProps) { @@ -48,17 +56,64 @@ export function CardCourseGroup({ {groupName}
- {waLink && ( - - - - )} - {tgLink && ( - - - - )} + +
) } + +function PlatformAction({ + platform, + platformLabel, + link, + groupId, + icon, + groupName, + actionClassName, +}: { + platform: "wa" | "tg" + platformLabel: string + link?: string + groupId?: number + icon: IconType + groupName: string + actionClassName: string +}) { + if (!link) return null + + return ( + <> + + + + {groupId !== undefined && ( + + + + } + /> + )} + + ) +} diff --git a/src/components/groups/extra-groups.tsx b/src/components/groups/extra-groups.tsx index 41c93ee..6140f2f 100644 --- a/src/components/groups/extra-groups.tsx +++ b/src/components/groups/extra-groups.tsx @@ -29,7 +29,14 @@ export async function ExtraGroups() { {extraGroups.length > 0 ? (
{extraGroups.map((g) => ( - + ))}
) : ( diff --git a/src/components/groups/groups-result.tsx b/src/components/groups/groups-result.tsx index ba15d7f..62552c5 100644 --- a/src/components/groups/groups-result.tsx +++ b/src/components/groups/groups-result.tsx @@ -16,9 +16,24 @@ import { SITE_LABEL, schoolLabel, } from "@/utils/labels" -import { mergeGroupsByTitle } from "@/utils/merge-groups" +import { type MergedGroup, mergeGroupsByTitle } from "@/utils/merge-groups" import { stepHref } from "../../utils/step-href" +function GroupCard({ group, secondary, stacked }: { group: MergedGroup; secondary?: boolean; stacked?: boolean }) { + return ( + + ) +} + function GroupSection({ title, groups }: { title: string; groups: VisibleGroup[] }) { const merged = mergeGroupsByTitle(groups) if (merged.length === 0) return null @@ -33,7 +48,7 @@ function GroupSection({ title, groups }: { title: string; groups: VisibleGroup[]
{merged.map((g) => ( - + ))}
@@ -116,16 +131,16 @@ export async function GroupsResult({ mergedGeneralCourseGroups.length > 0) && (
{mergedSiteGroups.map((g) => ( - + ))} {mergedSchoolGroups.map((g) => ( - + ))} {mergedLevelGroups.map((g) => ( - + ))} {mergedGeneralCourseGroups.map((g) => ( - + ))}
)} diff --git a/src/components/groups/report/fab.tsx b/src/components/groups/report/fab.tsx index 32dbc07..08d238e 100644 --- a/src/components/groups/report/fab.tsx +++ b/src/components/groups/report/fab.tsx @@ -1,12 +1,17 @@ "use client" +import { usePathname } from "next/navigation" import { FiFlag } from "react-icons/fi" import { ButtonIcon } from "@/components/button-icon" import { ReportFinderDialog } from "@/components/groups/report/finder-dialog" +import { missingLinkTargetFromPath } from "@/utils/missing-link-target" export function ReportFab() { + const missingLinkTarget = missingLinkTargetFromPath(usePathname()) + return ( ("problem") const [report, setReport] = useState(null) @@ -41,7 +52,13 @@ export function ReportFinderDialog({ trigger }: { trigger: ReactNode }) { function handleOpenChange(next: boolean) { setOpen(next) - if (!next) reset() + if (!next) { + reset() + } else if (selectedReport && selectedGroupName) { + setReport(selectedReport) + setGroupName(selectedGroupName) + setView("confirmation") + } } async function submit(input: BrokenGroupLinkReportInput | MissingGroupLinkReportInput) { @@ -123,6 +140,7 @@ export function ReportFinderDialog({ trigger }: { trigger: ReactNode }) { onBack={reset} onSubmit={(missingReport) => void submit(missingReport)} status={status} + target={missingLinkTarget} /> ) : ( <> diff --git a/src/components/groups/report/missing-link/index.tsx b/src/components/groups/report/missing-link/index.tsx index 101d6a2..47da61f 100644 --- a/src/components/groups/report/missing-link/index.tsx +++ b/src/components/groups/report/missing-link/index.tsx @@ -10,19 +10,26 @@ import { CourseStep } from "./course-step" import { DetailsStep } from "./details-step" import { LevelStep } from "./level-step" import { SchoolStep } from "./school-step" -import type { ReportMissingLinkCategory, ReportMissingLinkSelection, ReportMissingLinkStep } from "./types" +import type { + MissingLinkTarget, + ReportMissingLinkCategory, + ReportMissingLinkSelection, + ReportMissingLinkStep, +} from "./types" export function ReportMissingLinkFlow({ onBack, onSubmit, status, + target, }: { onBack: () => void onSubmit: (report: MissingGroupLinkReportInput) => void status: "idle" | "submitting" | "error" + target?: MissingLinkTarget }) { - const [step, setStep] = useState("category") - const [category, setCategory] = useState(null) + const [step, setStep] = useState(target ? "details" : "category") + const [category, setCategory] = useState(target?.category ?? null) const [selection, setSelection] = useState({ school: null, level: null, course: null }) const [courses, setCourses] = useState(null) const [details, setDetails] = useState("") @@ -45,12 +52,13 @@ export function ReportMissingLinkFlow({ const school = selection.school ? getSchool(selection.school) : undefined const level = selection.school && selection.level ? getLevel(selection.school, selection.level) : undefined - const path = + const selectedPath = category === "extra" ? "Gruppi Extra" : [school?.name, level?.name, selection.course ? humanizeSlug(selection.course) : undefined] .filter(Boolean) .join(" · ") + const path = target?.path ?? selectedPath function selectCategory(next: ReportMissingLinkCategory) { setCategory(next) @@ -109,14 +117,19 @@ export function ReportMissingLinkFlow({ } // step === "details" - setStep(detailsFrom ?? "category") + if (target) { + onBack() + } else { + setStep(detailsFrom ?? "category") + } } function submit() { if (!details.trim() || status === "submitting") return const label = - category === "extra" + target?.label ?? + (category === "extra" ? "Gruppi Extra" : selection.school && selection.course && selection.level ? courseLabel(selection.school, selection.level, selection.course) @@ -124,7 +137,7 @@ export function ReportMissingLinkFlow({ ? levelLabel(selection.school, selection.level) : selection.school ? schoolLabel(selection.school) - : null + : null) if (label === null) return diff --git a/src/components/groups/report/missing-link/types.ts b/src/components/groups/report/missing-link/types.ts index 3f50aab..ea36a12 100644 --- a/src/components/groups/report/missing-link/types.ts +++ b/src/components/groups/report/missing-link/types.ts @@ -7,3 +7,9 @@ export type ReportMissingLinkSelection = { level: string | null course: string | null } + +export type MissingLinkTarget = { + category: ReportMissingLinkCategory + label: string + path: string +} diff --git a/src/utils/merge-groups.ts b/src/utils/merge-groups.ts index f296591..1bbbd16 100644 --- a/src/utils/merge-groups.ts +++ b/src/utils/merge-groups.ts @@ -5,7 +5,9 @@ export type MergedGroup = { key: string title: string waLink?: string + waGroupId?: number tgLink?: string + tgGroupId?: number } /** @@ -18,12 +20,19 @@ export function mergeGroupsByTitle(groups: VisibleGroup[]): MergedGroup[] { const result: MergedGroup[] = [] for (const g of groups) { const linkField = g.type === "wa" ? "waLink" : "tgLink" + const groupIdField = g.type === "wa" ? "waGroupId" : "tgGroupId" const candidates = openByTitle.get(g.title) ?? [] const openEntry = candidates.find((m) => !m[linkField]) if (openEntry) { openEntry[linkField] = g.link + openEntry[groupIdField] = g.id } else { - const merged: MergedGroup = { key: `${g.type}:${g.id}`, title: g.title, [linkField]: g.link } + const merged: MergedGroup = { + key: `${g.type}:${g.id}`, + title: g.title, + [linkField]: g.link, + [groupIdField]: g.id, + } candidates.push(merged) openByTitle.set(g.title, candidates) result.push(merged) diff --git a/src/utils/missing-link-target.ts b/src/utils/missing-link-target.ts new file mode 100644 index 0000000..9fa29f8 --- /dev/null +++ b/src/utils/missing-link-target.ts @@ -0,0 +1,34 @@ +import { getLevel, getSchool } from "@/components/groups/constants" +import type { MissingLinkTarget } from "@/components/groups/report/missing-link/types" +import { courseLabel, humanizeSlug, levelLabel, schoolLabel } from "@/utils/labels" + +export function missingLinkTargetFromPath(pathname: string): MissingLinkTarget | undefined { + if (pathname === "/groups/extra") { + return { category: "extra", label: "Gruppi Extra", path: "Gruppi Extra" } + } + + const [, groups, category, schoolSlug, levelSlug, course] = pathname.split("/") + if (groups !== "groups" || category !== "didattica" || !schoolSlug) return undefined + + const school = getSchool(schoolSlug) + if (!school) return undefined + if (!levelSlug) { + return { category: "didattica", label: schoolLabel(schoolSlug), path: school.name } + } + + const level = getLevel(schoolSlug, levelSlug) + if (!level) return undefined + if (!course) { + return { + category: "didattica", + label: levelLabel(schoolSlug, levelSlug), + path: `${school.name} · ${level.name}`, + } + } + + return { + category: "didattica", + label: courseLabel(schoolSlug, levelSlug, course), + path: `${school.name} · ${level.name} · ${humanizeSlug(course)}`, + } +}