|
1 | 1 | import { useState } from "react"; |
2 | 2 | import { Form, Link } from "react-router"; |
| 3 | +import type { PushSubscription } from "web-push"; |
| 4 | +import { z } from "zod"; |
3 | 5 |
|
| 6 | +import { getAllSubscriptions, getSubscriptionByUserId } from "~/.server/db/pushSubscriptions"; |
| 7 | +import { getUser, getUsers } from "~/.server/db/user"; |
| 8 | +import { sendPushNotification } from "~/.server/services/pushNoticiationService"; |
| 9 | +import { sendMail } from "~/.server/services/sendgrid"; |
4 | 10 | import { Button } from "~/components/ui/button"; |
| 11 | +import { NativeSelect } from "~/components/ui/native-select"; |
| 12 | +import { getRequiredUser } from "~/utils/auth.server"; |
| 13 | +import { RoleName } from "~/utils/roleUtils"; |
5 | 14 |
|
6 | 15 | import type { Route } from "./+types/sentry-test"; |
7 | 16 |
|
8 | | -export const loader = ({ request }: Route.LoaderArgs) => { |
| 17 | +export const loader = async ({ request }: Route.LoaderArgs) => { |
| 18 | + await getRequiredUser(request, [RoleName.Admin]); |
9 | 19 | const search = new URL(request.url).searchParams; |
10 | 20 | if (search.get("error") === "true") { |
11 | 21 | throw new Error("Error in loader..."); |
12 | 22 | } |
13 | | - return {}; |
| 23 | + return { |
| 24 | + users: await getUsers(), |
| 25 | + subscriptions: await getAllSubscriptions(""), |
| 26 | + }; |
14 | 27 | }; |
15 | 28 |
|
16 | | -export const action = () => { |
17 | | - throw new Error("Error in action..."); |
| 29 | +export const action = async ({ request }: Route.ActionArgs) => { |
| 30 | + await getRequiredUser(request, [RoleName.Admin]); |
| 31 | + const formData = await request.formData(); |
| 32 | + const intent = formData.get("intent"); |
| 33 | + if (intent === "sentry-error") { |
| 34 | + throw new Error("Error in action..."); |
| 35 | + } else if (intent === "email-test") { |
| 36 | + const userId = z.string().parse(formData.get("user")); |
| 37 | + const user = await getUser(userId); |
| 38 | + await sendMail({ |
| 39 | + html: ` |
| 40 | + <h1>Dette er en test</h1> |
| 41 | + <p>Hvis du ser denne mail kan du ignorere den!</p> |
| 42 | + `, |
| 43 | + to: [{ email: user.primaryUser.email }], |
| 44 | + subject: "Dette er en test", |
| 45 | + }); |
| 46 | + } else if (intent === "pwa-test") { |
| 47 | + const userId = z.string().parse(formData.get("user")); |
| 48 | + const subscriptions = await getSubscriptionByUserId(userId); |
| 49 | + await sendPushNotification( |
| 50 | + subscriptions.map((s) => s.subscription as PushSubscription), |
| 51 | + { |
| 52 | + body: `📝 Dette er en test`, |
| 53 | + data: { url: `/sentry-test` }, |
| 54 | + icon: "/logo192.png", |
| 55 | + } |
| 56 | + ); |
| 57 | + } |
18 | 58 | }; |
19 | 59 |
|
20 | | -export default function SentryTest() { |
| 60 | +export default function SentryTest({ loaderData: { users, subscriptions } }: Route.ComponentProps) { |
21 | 61 | const [throwError, setThrowError] = useState(false); |
22 | 62 | if (throwError) { |
23 | 63 | throw new Error("Error in client..."); |
24 | 64 | } |
25 | 65 | return ( |
26 | | - <main className="p-8"> |
| 66 | + <main className="p-8 flex flex-col gap-2 items-start"> |
27 | 67 | <Button |
28 | 68 | onClick={() => { |
29 | 69 | setThrowError(true); |
30 | 70 | }} |
31 | 71 | > |
32 | 72 | Trigger error on client |
33 | 73 | </Button> |
34 | | - <Button as={Link} variant="link" to={{ search: "?error=true" }}> |
| 74 | + <Button as={Link} to={{ search: "?error=true" }}> |
35 | 75 | Navigate to error in loader |
36 | 76 | </Button> |
37 | 77 | <Form method="POST"> |
38 | | - <Button variant="outline" type="submit"> |
| 78 | + <Button variant="outline" type="submit" name="intent" value="sentry-error"> |
39 | 79 | Trigger error in action |
40 | 80 | </Button> |
41 | 81 | </Form> |
| 82 | + <Form method="POST" className="flex gap-2"> |
| 83 | + <NativeSelect className="w-fit min-w-60 mb-4" name="user"> |
| 84 | + <option value="">Alle medlemmer</option> |
| 85 | + {users.map((user) => ( |
| 86 | + <option key={user.id} value={user.id}> |
| 87 | + {user.name} |
| 88 | + </option> |
| 89 | + ))} |
| 90 | + </NativeSelect> |
| 91 | + <Button variant="outline" type="submit" name="intent" value="email-test"> |
| 92 | + Send test email |
| 93 | + </Button> |
| 94 | + </Form> |
| 95 | + <Form method="POST" className="flex gap-2"> |
| 96 | + <NativeSelect className="w-fit min-w-60 mb-4" name="user"> |
| 97 | + <option value="">Alle medlemmer</option> |
| 98 | + {users |
| 99 | + .filter((user) => subscriptions.find((s) => s.userId === user.id)) |
| 100 | + .map((user) => ( |
| 101 | + <option key={user.id} value={user.id}> |
| 102 | + {user.name} |
| 103 | + </option> |
| 104 | + ))} |
| 105 | + </NativeSelect> |
| 106 | + <Button variant="outline" type="submit" name="intent" value="pwa-test"> |
| 107 | + Send test notification |
| 108 | + </Button> |
| 109 | + </Form> |
42 | 110 | </main> |
43 | 111 | ); |
44 | 112 | } |
0 commit comments