upd: webpush
Deskripsi: - database push notification - update package - memasang webpush NO Issues
This commit is contained in:
28
src/app/makuro/_lib/ButtonKirim.tsx
Normal file
28
src/app/makuro/_lib/ButtonKirim.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Button } from "@mantine/core";
|
||||
import { useState } from "react";
|
||||
|
||||
export function ButtonKirim() {
|
||||
const [loading, setLoading] = useState(false)
|
||||
async function onKirim() {
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await fetch('/makuro/api/kirim', {
|
||||
method: 'POST',
|
||||
})
|
||||
|
||||
const dataText = await res.text()
|
||||
if (!res.ok) {
|
||||
alert(dataText)
|
||||
throw new Error(dataText)
|
||||
}
|
||||
const dataJson = JSON.parse(dataText)
|
||||
console.log(dataJson)
|
||||
alert("berhasil kirim")
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
return <Button loading={loading} onClick={() => onKirim()} >Kirim</Button>
|
||||
}
|
||||
32
src/app/makuro/_lib/ButtonSubscribe.tsx
Normal file
32
src/app/makuro/_lib/ButtonSubscribe.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Button } from "@mantine/core";
|
||||
import { useState } from "react";
|
||||
|
||||
export function ButtonSubscribe({ user, subscription }: { user: string, subscription?: PushSubscription | null }) {
|
||||
const [loading, setLoading] = useState(false)
|
||||
async function subscribe() {
|
||||
if(!subscription) return alert("no subscription")
|
||||
try {
|
||||
setLoading(true)
|
||||
const res = await fetch('/makuro/api/sub', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ user, subscription })
|
||||
})
|
||||
|
||||
const dataText = await res.text()
|
||||
if (!res.ok) {
|
||||
alert(dataText)
|
||||
throw new Error(dataText)
|
||||
}
|
||||
|
||||
console.log(dataText)
|
||||
alert("berhasil subscribe")
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
return <Button disabled={!subscription} onClick={() => subscribe()} loading={loading} variant="outline" radius={"xl"} size={"lg"}>Subscribe</Button>
|
||||
}
|
||||
5
src/app/makuro/_lib/MakuroProvider.tsx
Normal file
5
src/app/makuro/_lib/MakuroProvider.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { WibuPermissionProvider, WibuPushNotificationHandler } from "wibu-pkg";
|
||||
|
||||
export function MakuroProvider() {
|
||||
return null
|
||||
}
|
||||
7
src/app/makuro/_lib/UserSub.ts
Normal file
7
src/app/makuro/_lib/UserSub.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { PushSubscription } from 'web-push';
|
||||
export class UserSub {
|
||||
public static subscription: PushSubscription | null;
|
||||
public static setSub(subscription: PushSubscription) {
|
||||
this.subscription = subscription
|
||||
}
|
||||
}
|
||||
3
src/app/makuro/_lib/state.ts
Normal file
3
src/app/makuro/_lib/state.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { hookstate } from "@hookstate/core";
|
||||
|
||||
export const subState = hookstate<PushSubscription | null>(null)
|
||||
25
src/app/makuro/api/kirim/route.ts
Normal file
25
src/app/makuro/api/kirim/route.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { prisma } from "@/module/_global";
|
||||
import { WibuServerPush } from 'wibu-pkg'
|
||||
|
||||
WibuServerPush.init({
|
||||
NEXT_PUBLIC_VAPID_PUBLIC_KEY: process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY!,
|
||||
VAPID_PRIVATE_KEY: process.env.VAPID_PRIVATE_KEY!,
|
||||
})
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const sub = await prisma.subscribe.findMany()
|
||||
const subs: PushSubscription[] = sub.map((v) => JSON.parse(v.subscription)) as PushSubscription[]
|
||||
|
||||
const kirim = await WibuServerPush.sendMany({
|
||||
subscriptions: subs as any,
|
||||
data: {
|
||||
body: "ini test ",
|
||||
title: "test notif",
|
||||
link: "/",
|
||||
variant: "notification"
|
||||
}
|
||||
})
|
||||
|
||||
return new Response(JSON.stringify(kirim))
|
||||
|
||||
}
|
||||
21
src/app/makuro/api/sub/route.ts
Normal file
21
src/app/makuro/api/sub/route.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { prisma } from "@/module/_global"
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { user, subscription } = await req.json()
|
||||
console.log(user, subscription)
|
||||
const upsert = await prisma.subscribe.upsert({
|
||||
where: {
|
||||
idUser: user
|
||||
},
|
||||
create: {
|
||||
idUser: user,
|
||||
subscription: JSON.stringify(subscription)
|
||||
},
|
||||
update: {
|
||||
subscription: JSON.stringify(subscription)
|
||||
}
|
||||
})
|
||||
|
||||
return new Response(JSON.stringify(upsert))
|
||||
|
||||
}
|
||||
22
src/app/makuro/kirim/page.tsx
Normal file
22
src/app/makuro/kirim/page.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
'use client'
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import { Card, Stack, Text, Title } from "@mantine/core";
|
||||
import { subState } from "../_lib/state";
|
||||
import { ButtonSubscribe } from "../_lib/ButtonSubscribe";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
||||
export default function Page() {
|
||||
const user = useSearchParams().get("user")
|
||||
const { value: sub } = useHookstate(subState)
|
||||
if (!sub) return <Text>loading ...</Text>
|
||||
if (!user) return <Text>masukkan user</Text>
|
||||
return <Stack p={"md"} gap={"lg"}>
|
||||
<Title>Kirim</Title>
|
||||
<Card>
|
||||
<Text>
|
||||
{JSON.stringify(sub)}
|
||||
</Text>
|
||||
</Card>
|
||||
<ButtonSubscribe user={user} subscription={sub} />
|
||||
</Stack>;
|
||||
}
|
||||
17
src/app/makuro/layout.tsx
Normal file
17
src/app/makuro/layout.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
'use client'
|
||||
|
||||
import { useHookstate } from "@hookstate/core"
|
||||
import { WibuPermissionProvider, WibuPushNotificationHandler } from "wibu-pkg"
|
||||
import { subState } from "./_lib/state"
|
||||
|
||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
const { set: setSubcribe } = useHookstate(subState)
|
||||
return <WibuPermissionProvider requiredPermissions={["notifications"]}>
|
||||
<WibuPushNotificationHandler
|
||||
NEXT_PUBLIC_VAPID_PUBLIC_KEY={process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY!}
|
||||
onSubscribe={(sub) => {
|
||||
setSubcribe(sub)
|
||||
}} />
|
||||
{children}
|
||||
</WibuPermissionProvider>
|
||||
}
|
||||
24
src/app/makuro/terima/page.tsx
Normal file
24
src/app/makuro/terima/page.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
'use client'
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import { Card, Stack, Text, Title } from "@mantine/core";
|
||||
import { subState } from "../_lib/state";
|
||||
import { ButtonSubscribe } from "../_lib/ButtonSubscribe";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { ButtonKirim } from "../_lib/ButtonKirim";
|
||||
|
||||
export default function Page() {
|
||||
const user = useSearchParams().get("user")
|
||||
const { value: sub } = useHookstate(subState)
|
||||
if (!sub) return <Text>loading ...</Text>
|
||||
if (!user) return <Text>masukkan user</Text>
|
||||
return <Stack p={"md"} gap={"lg"}>
|
||||
<Title>terima</Title>
|
||||
<Card>
|
||||
<Text>
|
||||
{JSON.stringify(sub)}
|
||||
</Text>
|
||||
</Card>
|
||||
<ButtonSubscribe user={user} subscription={sub} />
|
||||
<ButtonKirim />
|
||||
</Stack>;
|
||||
}
|
||||
Reference in New Issue
Block a user