Skip to content

Commit cc6fb26

Browse files
committed
toast and UI adjustments
1 parent bb44e58 commit cc6fb26

8 files changed

Lines changed: 111 additions & 16 deletions

File tree

apps/website/app/(home)/auth/group/page.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import { ListGroups } from "~/components/auth/ListGroups";
22
import { Suspense } from "react";
33

44
const Page = () => (
5-
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
6-
<Suspense fallback={<>Loading</>}>
7-
<ListGroups />
8-
</Suspense>
9-
</div>
5+
<main>
6+
<div className="mx-auto max-w-6xl space-y-12 px-6 py-12">
7+
<Suspense fallback={<>Loading</>}>
8+
<ListGroups />
9+
</Suspense>
10+
</div>
11+
</main>
1012
);
1113

1214
export default Page;

apps/website/app/components/auth/ListGroups.tsx

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { createClient } from "~/utils/supabase/client";
44
import { getSessionUserData } from "~/utils/supabase/dbUtils";
55
import { useState, useEffect } from "react";
66
import { Tables } from "@repo/database/dbTypes";
7+
import useInternalError from "~/utils/internalError";
78

89
type GroupData = Tables<"my_groups">;
910

@@ -12,14 +13,16 @@ export const ListGroups = () => {
1213
const [adminData, setAdminData] = useState<Record<string, boolean>>({});
1314
const [userName, setUserName] = useState<string | null>(null);
1415
const [error, setError] = useState<string | null>(null);
16+
const internalError = useInternalError();
1517

1618
useEffect(() => {
1719
const getGroups = async () => {
1820
try {
1921
const client = createClient();
2022
const userData = await getSessionUserData(client);
2123
if (!userData) {
22-
setError("Not logged in");
24+
const userMessage = "Not logged in.\nPlease log in from application.";
25+
setError(userMessage);
2326
return;
2427
}
2528
const { name, type, id } = userData;
@@ -37,7 +40,12 @@ export const ListGroups = () => {
3740
.select("group_id,admin")
3841
.eq("member_id", id);
3942
if (membershipReq.error) {
40-
setError(membershipReq.error.message);
43+
const userMessage = "Could not access DiscourseGraphs";
44+
setError(userMessage);
45+
internalError({
46+
error: membershipReq.error,
47+
userMessage,
48+
});
4149
return;
4250
}
4351
setAdminData(
@@ -50,17 +58,22 @@ export const ListGroups = () => {
5058
),
5159
);
5260
} catch (error) {
53-
setError(
54-
error instanceof Error ? error.message : "Unknown error occurred",
55-
);
61+
const userMessage = "Unknown error occurred";
62+
setError(userMessage);
63+
internalError({
64+
error,
65+
userMessage,
66+
});
5667
}
5768
};
5869
void getGroups();
59-
}, []);
70+
}, [internalError]);
6071

6172
return (
6273
<div>
63-
<div>{userName ? <p>Logged in as {userName}</p> : ""}</div>
74+
<div className="text-right text-sm">
75+
{userName ? <p>Logged in as {userName}</p> : ""}
76+
</div>
6477
<div>
6578
{error ? (
6679
"Error: " + error
@@ -71,7 +84,7 @@ export const ListGroups = () => {
7184
) : (
7285
<>
7386
<p>Your groups:</p>
74-
<ul>
87+
<ul className="list-inside list-disc space-y-2">
7588
{groupData.map((d) => (
7689
<li key={d.id}>
7790
{adminData[d.id || ""] ? (

apps/website/app/providers.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import posthog from "posthog-js";
44
import { PostHogProvider as PHProvider } from "posthog-js/react";
5+
import { Toaster } from "@repo/ui/components/ui/sonner";
56
import { useEffect } from "react";
67
import PostHogPageView from "./PostHogPageView";
78

@@ -12,7 +13,11 @@ if (
1213
throw new Error("PostHog environment variables are not set");
1314
}
1415

15-
export function PostHogProvider({ children }: { children: React.ReactNode }) {
16+
export const PostHogProvider = ({
17+
children,
18+
}: {
19+
children: React.ReactNode;
20+
}) => {
1621
useEffect(() => {
1722
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
1823
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST!,
@@ -24,6 +29,7 @@ export function PostHogProvider({ children }: { children: React.ReactNode }) {
2429
<PHProvider client={posthog}>
2530
<PostHogPageView />
2631
{children}
32+
<Toaster />
2733
</PHProvider>
2834
);
29-
}
35+
};

apps/website/app/utils/internalError.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useCallback } from "react";
44
import type { Properties } from "posthog-js";
55
import { usePostHog } from "posthog-js/react";
6+
import { toast } from "sonner";
67

78
const NON_WORD = /\W+/g;
89
export const useInternalError = () => {
@@ -11,11 +12,13 @@ export const useInternalError = () => {
1112
({
1213
error,
1314
type,
15+
userMessage,
1416
context,
1517
forceSendInDev = false,
1618
}: {
1719
error: unknown;
1820
type?: string;
21+
userMessage?: string;
1922
context?: Properties;
2023
forceSendInDev?: boolean;
2124
}): void => {
@@ -41,6 +44,9 @@ export const useInternalError = () => {
4144
}
4245
posthog.captureException(error, { ...context, type: slugType });
4346
}
47+
if (userMessage) {
48+
toast(userMessage, { duration: 5000 });
49+
}
4450
},
4551
[posthog],
4652
);

apps/website/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"react": "catalog:",
3131
"react-dom": "catalog:",
3232
"resend": "^4.0.1",
33+
"sonner": "^2.0.7",
3334
"zod": "^3.24.1"
3435
},
3536
"devDependencies": {

packages/ui/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@
3939
"class-variance-authority": "^0.7.1",
4040
"clsx": "^2.1.1",
4141
"lucide-react": "^0.468.0",
42+
"next-themes": "^0.4.6",
4243
"react": "^19",
4344
"react-dom": "^19",
4445
"shadcn": "2.10.0",
46+
"sonner": "^2.0.7",
4547
"tailwind-merge": "^3.3.1",
4648
"tailwindcss": "^3.1.0",
4749
"tailwindcss-animate": "^1.0.7",
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"use client";
2+
3+
import {
4+
CircleCheck,
5+
Info,
6+
LoaderCircle,
7+
OctagonX,
8+
TriangleAlert,
9+
} from "lucide-react";
10+
import { useTheme } from "next-themes";
11+
import { Toaster as Sonner } from "sonner";
12+
13+
type ToasterProps = React.ComponentProps<typeof Sonner>;
14+
15+
const Toaster = ({ ...props }: ToasterProps) => {
16+
const { theme = "system" } = useTheme();
17+
18+
return (
19+
<Sonner
20+
theme={theme as ToasterProps["theme"]}
21+
className="toaster group"
22+
icons={{
23+
success: <CircleCheck className="h-4 w-4" />,
24+
info: <Info className="h-4 w-4" />,
25+
warning: <TriangleAlert className="h-4 w-4" />,
26+
error: <OctagonX className="h-4 w-4" />,
27+
loading: <LoaderCircle className="h-4 w-4 animate-spin" />,
28+
}}
29+
toastOptions={{
30+
classNames: {
31+
toast:
32+
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
33+
description: "group-[.toast]:text-muted-foreground",
34+
actionButton:
35+
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
36+
cancelButton:
37+
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
38+
},
39+
}}
40+
{...props}
41+
/>
42+
);
43+
};
44+
45+
export { Toaster };

pnpm-lock.yaml

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)