Skip to content

Commit

Permalink
Show registrations (#2440)
Browse files Browse the repository at this point in the history
  • Loading branch information
omfj authored Jan 29, 2025
1 parent c5e1cf9 commit 06259fe
Show file tree
Hide file tree
Showing 11 changed files with 848 additions and 1,459 deletions.
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@radix-ui/react-switch": "1.1.2",
"@radix-ui/react-tabs": "1.1.2",
"@radix-ui/react-toast": "1.2.5",
"@radix-ui/react-tooltip": "^1.1.7",
"@sanity/client": "6.22.5",
"@sanity/image-url": "1.1.0",
"@tanstack/react-query": "5.65.1",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/(default)/arrangement/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { cache } from "react";
import { notFound } from "next/navigation";

import { EventPage } from "@/components/event-page";
import { EventPage } from "@/components/happening/event-page";
import { fetchHappeningBySlug } from "@/sanity/happening";
import { fetchRepeatingHappening } from "@/sanity/repeating-happening";

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/(default)/bedpres/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { cache } from "react";
import { notFound } from "next/navigation";

import { EventPage } from "@/components/event-page";
import { EventPage } from "@/components/happening/event-page";
import { fetchHappeningBySlug } from "@/sanity/happening";
import { norwegianDateString } from "@/utils/date";

Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/events-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { subMinutes } from "date-fns";

import { fetchFilteredHappening } from "@/sanity/happening";
import { startOfNextWeek, startOfTheWeekAfterNext } from "@/utils/date";
import { CombinedHappeningPreview } from "./happening-preview-box";
import { CombinedHappeningPreview } from "./happening/happening-preview-box";
import { Callout } from "./typography/callout";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import Image from "next/image";

import { type fetchHappeningBySlug } from "@/sanity/happening";
import { type fetchRepeatingHappening } from "@/sanity/repeating-happening";
import { CommentSection } from "./comments/comment-section";
import { CompanyLeagueBanner } from "./company-league-banner";
import { Container } from "./container";
import { CommentSection } from "../comments/comment-section";
import { CompanyLeagueBanner } from "../company-league-banner";
import { Container } from "../container";
import { Markdown } from "../markdown";
import { RepeatingHappeningSidebar } from "../repeating-happening-sidebar";
import { Heading } from "../typography/heading";
import { HappeningSidebar } from "./happening-sidebar";
import { Markdown } from "./markdown";
import { RepeatingHappeningSidebar } from "./repeating-happening-sidebar";
import { Heading } from "./typography/heading";

const FOOTBALL_KEYWORDS = ["fotball", "databrus fc", "futsal"];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ import {
} from "@/utils/date";
import { doesIntersect } from "@/utils/list";
import { mailTo } from "@/utils/prefixes";
import { ReactionButtonGroup } from "./reaction-button-group";
import { RegistrationCount } from "./registration-count";
import { ReactionButtonGroup } from "../reaction-button-group";
import { RegistrationCount } from "../registration-count";
import { RegistrationsPreview } from "./registrations-preview";

type EventSidebarProps = {
event: Exclude<Awaited<ReturnType<typeof fetchHappeningBySlug>>, null>;
Expand Down Expand Up @@ -486,6 +487,9 @@ export const HappeningSidebar = async ({ event }: EventSidebarProps) => {
)}
</div>
</Sidebar>

{Boolean(user) && <RegistrationsPreview registrations={registrations} />}

{/**
* Show link to admin dashbord if:
* - User is host
Expand Down
100 changes: 100 additions & 0 deletions apps/web/src/components/happening/registrations-preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { type Registration, type User } from "@echo-webkom/db/schemas";

import { ellipsis, initials } from "@/utils/string";
import { Text } from "../typography/text";
import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "../ui/dialog";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip";

type ProfilePreviewProps = {
user: User;
};

const ProfilePreview = ({ user }: ProfilePreviewProps) => {
const fallback = initials(user.name ?? "BO");

return (
<Avatar className="size-8">
<AvatarImage src={user.image ?? ""} />
<AvatarFallback>{fallback}</AvatarFallback>
</Avatar>
);
};

type RegistrationsPreviewProps = {
registrations: Array<
Registration & {
user: User;
}
>;
};

const MAX = 7;

export const RegistrationsPreview = ({ registrations }: RegistrationsPreviewProps) => {
const sorted = registrations
.filter((registration) => registration.status === "registered")
.sort((a, b) => {
if (a.user.image && !b.user.image) {
return -1;
} else if (!a.user.image && b.user.image) {
return 1;
}
return 0;
})
.slice(0, MAX);

if (sorted.length < 3) {
return null;
}

const extra = registrations.length - MAX;
const names = `${sorted.map((registration) => ellipsis(registration.user?.name ?? "", 7)).join(", ")}${
extra > 0 ? ` +${extra}` : ""
}`;

return (
<Dialog>
<DialogTrigger className="group flex w-fit items-start">
<TooltipProvider>
<Tooltip>
<div>
<TooltipTrigger>
<div className="flex items-center">
<div className="flex items-center -space-x-4">
{sorted.map((registration) => (
<ProfilePreview key={registration.user.id} user={registration.user} />
))}
</div>
{extra > 0 && (
<div className="ml-2 text-sm font-medium text-gray-600 group-hover:underline">
+{extra}
</div>
)}
</div>
</TooltipTrigger>
</div>
<TooltipContent>
<p>{names}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Påmeldte brukere</DialogTitle>
</DialogHeader>
<div className="px-4 pb-4">
{registrations
.filter((registration) => registration.status === "registered")
.map((registration) => (
<div key={registration.userId} className="flex items-center space-x-4">
<ProfilePreview user={registration.user} />
<Text className="text-muted-foreground">{registration.user.name}</Text>
</div>
))}
</div>
</DialogContent>
</Dialog>
);
};
32 changes: 32 additions & 0 deletions apps/web/src/components/ui/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use client";

import * as React from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";

import { cn } from "@/utils/cn";

const TooltipProvider = TooltipPrimitive.Provider;

const Tooltip = TooltipPrimitive.Root;

const TooltipTrigger = TooltipPrimitive.Trigger;

const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
/>
</TooltipPrimitive.Portal>
));
TooltipContent.displayName = TooltipPrimitive.Content.displayName;

export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
8 changes: 8 additions & 0 deletions apps/web/src/utils/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,11 @@ export const initials = (name: string): string => {

return `${first![0]}${second![0]}`.toUpperCase();
};

export const ellipsis = (str: string, maxLength: number) => {
if (str.length <= maxLength) {
return str;
}

return `${str.slice(0, maxLength)}...`;
};
Loading

0 comments on commit 06259fe

Please sign in to comment.