Skip to content
This repository has been archived by the owner on Dec 15, 2024. It is now read-only.

Commit

Permalink
chore: add my notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtemSBulgakov committed Nov 23, 2024
1 parent e5e12b8 commit 2a7c1bf
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 27 deletions.
9 changes: 2 additions & 7 deletions frontend/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -712,11 +712,8 @@ export interface components {
endpoint: string;
/** Keys */
keys: Record<string, never>;
/**
* Target Date
* Format: date-time
*/
target_date: string;
/** Event Dates */
event_dates: string[];
/**
* User Id
* @example 5eb7cf5a86d9755df3a6c593
Expand All @@ -738,8 +735,6 @@ export interface components {
NotificationOption: {
/** Endpoint */
endpoint: string;
/** Expiration Time */
expiration_time?: string | null;
keys: components["schemas"]["Keys"];
};
/**
Expand Down
62 changes: 62 additions & 0 deletions frontend/src/components/SportSubscribeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { $api } from "@/api";
import { useMe } from "@/api/me.ts";
import {
receivePushSubscription,
sendNotification,
} from "@/api/notifications.ts";
import { NotificationsDialog } from "@/components/NotificationsDialog.tsx";
import { Button } from "@/components/ui/button.tsx";
import { useNavigate } from "@tanstack/react-router";
import { BellPlus } from "lucide-react";
import { useState } from "react";

export function SportSubscribeButton({ sportId }: { sportId: string }) {
const navigate = useNavigate();

const { data: me } = useMe();
const { mutate } = $api.useMutation("post", "/notify/");
const [dialogOpen, setDialogOpen] = useState(false);

const subscribe = async () => {
if (!me) {
navigate({
to: "/auth/login",
search: { redirectTo: window.location.href },
});
return;
}

const pushSubscription = await receivePushSubscription();
if (!pushSubscription) {
setDialogOpen(true);
return;
}

setDialogOpen(false);
sendNotification();
mutate({
body: {
notification_options: pushSubscription.toJSON() as any,
notification_type: {
type: "sport",
id: sportId,
},
},
});
};

return (
<>
<Button className="w-fit" onClick={() => subscribe()}>
<BellPlus />
Получать уведомления
</Button>

<NotificationsDialog
open={dialogOpen}
setOpen={setDialogOpen}
retry={() => subscribe()}
/>
</>
);
}
68 changes: 54 additions & 14 deletions frontend/src/routes/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { sendNotification } from "@/api/notifications.ts";
import { NotificationsDialog } from "@/components/NotificationsDialog.tsx";
import { Button } from "@/components/ui/button.tsx";
import { Card } from "@/components/ui/card.tsx";
import { createFileRoute } from "@tanstack/react-router";
import { Check, CircleX } from "lucide-react";
import { createFileRoute, Link } from "@tanstack/react-router";
import { Calendar, Check, CircleX } from "lucide-react";
import { useEffect, useState } from "react";

export const Route = createFileRoute("/profile")({
Expand All @@ -14,10 +14,11 @@ export const Route = createFileRoute("/profile")({

function RouteComponent() {
const { data: me } = useMe();
const { data: subscriptions } = $api.useMutation(
const { data: subscriptions } = $api.useQuery(
"post",
"/notify/my-subscriptions",
);
const { data: sports } = $api.useQuery("get", "/sports/");

const [notificationPermission, setNotificationPermission] = useState(false);
const [dialogOpen, setDialogOpen] = useState(false);
Expand Down Expand Up @@ -46,7 +47,7 @@ function RouteComponent() {

<Card className="flex w-full flex-col gap-2 p-4">
<div>
<h2 className="mb-2 text-lg font-semibold">Уведомления</h2>
<h2 className="mb-2 text-2xl font-semibold">Уведомления</h2>
<div className="flex items-center gap-2">
<p>Разрешение:</p>
{notificationPermission ? (
Expand Down Expand Up @@ -79,16 +80,55 @@ function RouteComponent() {
)}
</div>

{subscriptions?.length ? (
subscriptions?.map((v) => (
<div key={v.id} className="flex items-center gap-2">
<p>{v.event_title}</p>
<p>{v.target_date}</p>
</div>
))
) : (
<div className="text-gray-500">Нет настроенных уведомлений</div>
)}
<h2 className="mt-2 text-lg font-semibold">Ближайшие уведомления:</h2>
<div className="flex flex-col gap-2">
{subscriptions?.length ? (
subscriptions?.map((v) => (
<Card
key={v.id}
className="flex max-w-2xl items-center gap-4 p-2"
>
<div className="flex flex-col items-center gap-2 text-xl font-medium">
<Calendar />
<div className="flex flex-col">
{v.event_dates.slice(0, 3).map((d) => (
<div>{new Date(d).toLocaleDateString("ru-RU")}</div>
))}
</div>
</div>

<div>
{v.sport_id ? (
<Link
to="/sports/$sportId"
params={{ sportId: v.sport_id ?? "" }}
className="text-xl"
>
{v.sport_title}
</Link>
) : (
<>
<Link
to="/sports/$sportId"
params={{
sportId:
sports?.find((s) => s.sport === v.sport_title)
?.id ?? "",
}}
className="text-gray-500 underline"
>
{v.sport_title}
</Link>
<div className="text-xl">{v.event_title}</div>
</>
)}
</div>
</Card>
))
) : (
<div className="text-gray-500">Нет настроенных уведомлений</div>
)}
</div>
</div>
</Card>
</div>
Expand Down
16 changes: 10 additions & 6 deletions frontend/src/routes/sports/$sportId.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { $api } from "@/api";
import { ExportSportToCalendar } from "@/components/ExportSportToCalendar.tsx";
import { SportSubscribeButton } from "@/components/SportSubscribeButton.tsx";
import { Button } from "@/components/ui/button.tsx";
import { cn } from "@/lib/utils.ts";
import { createFileRoute, useNavigate } from "@tanstack/react-router";
import SportSVG from "./sport.svg";
import { Separator } from "@/components/ui/separator";
import {
Command,
CommandGroup,
Expand All @@ -17,8 +14,12 @@ import {
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { ChevronsUpDown } from "lucide-react";
import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils.ts";
import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { ChevronsUpDown } from "lucide-react";
import SportSVG from "./sport.svg";

export const Route = createFileRoute("/sports/$sportId")({
component: RouteComponent,
Expand Down Expand Up @@ -128,7 +129,10 @@ function RouteComponent() {
</Popover>
)}

<ExportSportToCalendar sportId={sportId} className="ml-auto w-fit" />
<div className="ml-auto flex flex-wrap gap-2">
<SportSubscribeButton sportId={sportId} />
<ExportSportToCalendar sportId={sportId} className="w-fit" />
</div>
</div>
</div>
</div>
Expand Down

0 comments on commit 2a7c1bf

Please sign in to comment.