tambahan
This commit is contained in:
@@ -1,66 +1,185 @@
|
||||
import apiFetch from "@/lib/apiFetch";
|
||||
import { Button, Card, Group, Pagination, Skeleton, Stack, Text, Title } from "@mantine/core";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Container,
|
||||
Group,
|
||||
Pagination,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
Badge,
|
||||
ScrollArea,
|
||||
Tooltip,
|
||||
} from "@mantine/core";
|
||||
import { useLocalStorage, useShallowEffect } from "@mantine/hooks";
|
||||
import { showNotification } from "@mantine/notifications";
|
||||
import { IconRefresh, IconMessageCircle, IconUser, IconCalendar, IconHash, IconCode } from "@tabler/icons-react";
|
||||
import dayjs from "dayjs";
|
||||
import useSWR from "swr";
|
||||
import { showNotification } from "@mantine/notifications";
|
||||
|
||||
export default function WaHookHome() {
|
||||
const [page, setPage] = useLocalStorage({
|
||||
key: "wa-hook-page",
|
||||
defaultValue: 1,
|
||||
})
|
||||
const { data, error, isLoading, mutate } = useSWR("/wa-hook", () => apiFetch["wa-hook"].list.get({ query: { page, limit: 10 } }), {
|
||||
refreshInterval: 3000,
|
||||
revalidateOnFocus: true,
|
||||
revalidateOnReconnect: true,
|
||||
revalidateIfStale: true,
|
||||
refreshWhenHidden: true,
|
||||
refreshWhenOffline: true,
|
||||
dedupingInterval: 3000,
|
||||
})
|
||||
const [page, setPage] = useLocalStorage({ key: "wa-hook-page", defaultValue: 1 });
|
||||
const { data, error, isLoading, mutate } = useSWR(
|
||||
"/wa-hook",
|
||||
() => apiFetch["wa-hook"].list.get({ query: { page, limit: 10 } }),
|
||||
{
|
||||
refreshInterval: 4000,
|
||||
revalidateOnFocus: true,
|
||||
revalidateOnReconnect: true,
|
||||
dedupingInterval: 3000,
|
||||
}
|
||||
);
|
||||
|
||||
useShallowEffect(() => {
|
||||
mutate()
|
||||
setPage(data?.data?.list?.length || 1)
|
||||
}, [])
|
||||
mutate();
|
||||
setPage(data?.data?.list?.length || 1);
|
||||
}, []);
|
||||
|
||||
async function reset() {
|
||||
await apiFetch["wa-hook"].reset.post()
|
||||
mutate()
|
||||
showNotification({ title: "Success", message: "WhatsApp Hook reset", color: "green" })
|
||||
async function handleReset() {
|
||||
await apiFetch["wa-hook"].reset.post();
|
||||
mutate();
|
||||
showNotification({
|
||||
title: "Reset Completed",
|
||||
message: "WhatsApp Hook data has been successfully reset.",
|
||||
color: "teal",
|
||||
});
|
||||
}
|
||||
|
||||
if (isLoading) return <Skeleton height={500} />
|
||||
if (error) return <div>Error: {error.message}</div>
|
||||
if (isLoading) return <Skeleton height={500} radius="lg" />;
|
||||
if (error)
|
||||
return (
|
||||
<Container p="xl">
|
||||
<Text c="red.5" ta="center" fz="lg" fw={500}>
|
||||
Failed to load data: {error.message}
|
||||
</Text>
|
||||
</Container>
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Title order={2}>WaHookHome</Title>
|
||||
<Group justify="flex-end">
|
||||
<Button onClick={reset}>Reset</Button>
|
||||
</Group>
|
||||
{data?.data?.list.map((item) => (
|
||||
<Card key={item.id}>
|
||||
<Stack>
|
||||
<Text>Name: {item.data?.entry?.[0]?.changes?.[0]?.value?.contacts?.[0]?.profile?.name}</Text>
|
||||
<Text>From: {item.data?.entry?.[0]?.changes?.[0]?.value?.messages?.[0]?.from}</Text>
|
||||
<Text>ID: {item.data?.entry?.[0]?.changes?.[0]?.value?.messages?.[0]?.id}</Text>
|
||||
<Text>Timestamp: {dayjs(item.data?.entry?.[0]?.changes?.[0]?.value?.messages?.[0]?.timestamp).format("YYYY-MM-DD HH:mm:ss")}</Text>
|
||||
<Text>Type: {item.data?.entry?.[0]?.changes?.[0]?.value?.messages?.[0]?.type}</Text>
|
||||
<Text>Body: {item.data?.entry?.[0]?.changes?.[0]?.value?.messages?.[0]?.text?.body}</Text>
|
||||
{JSON.stringify((item.data as any)?.answer)}
|
||||
<Container size="lg" p="lg" style={{ backgroundColor: "#191919", borderRadius: 20 }}>
|
||||
<Stack gap="xl">
|
||||
<Group justify="space-between" align="center">
|
||||
<Title order={2} c="#EAEAEA" fw={700} style={{ letterSpacing: 0.5 }}>
|
||||
WhatsApp Hook Monitor
|
||||
</Title>
|
||||
<Tooltip label="Reset all webhook data" withArrow color="teal">
|
||||
<Button
|
||||
onClick={handleReset}
|
||||
leftSection={<IconRefresh size={18} />}
|
||||
variant="gradient"
|
||||
gradient={{ from: "#00FFC8", to: "#00FFFF", deg: 45 }}
|
||||
radius="xl"
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
|
||||
<ScrollArea style={{ height: 600 }}>
|
||||
<Stack gap="md">
|
||||
{data?.data?.list?.length ? (
|
||||
data.data.list.map((item) => {
|
||||
const msg = item.data?.entry?.[0]?.changes?.[0]?.value?.messages?.[0];
|
||||
const contact = item.data?.entry?.[0]?.changes?.[0]?.value?.contacts?.[0];
|
||||
const answer = (item.data as any)?.answer;
|
||||
return (
|
||||
<Card
|
||||
key={item.id}
|
||||
radius="lg"
|
||||
style={{
|
||||
background:
|
||||
"linear-gradient(145deg, rgba(45,45,45,0.8) 0%, rgba(25,25,25,0.95) 100%)",
|
||||
backdropFilter: "blur(12px)",
|
||||
border: "1px solid rgba(0,255,200,0.2)",
|
||||
boxShadow: "0 0 10px rgba(0,255,200,0.15)",
|
||||
}}
|
||||
>
|
||||
<Stack gap={6}>
|
||||
<Group gap="xs">
|
||||
<IconUser size={16} color="#00FFC8" />
|
||||
<Text c="#EAEAEA" fw={500}>
|
||||
{contact?.profile?.name || "Unknown"}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
<Group gap="xs">
|
||||
<IconMessageCircle size={16} color="#00FFFF" />
|
||||
<Text c="#9A9A9A">{msg?.text?.body || "(No message body)"}</Text>
|
||||
</Group>
|
||||
|
||||
<Group gap="xs">
|
||||
<IconHash size={16} color="#00FFC8" />
|
||||
<Text c="#9A9A9A" fz="sm">
|
||||
{msg?.id}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
<Group gap="xs">
|
||||
<IconCalendar size={16} color="#00FFFF" />
|
||||
<Text c="#9A9A9A" fz="sm">
|
||||
{dayjs(Number(msg?.timestamp) * 1000).format("YYYY-MM-DD HH:mm:ss")}
|
||||
</Text>
|
||||
</Group>
|
||||
|
||||
<Group gap="xs">
|
||||
<IconCode size={16} color="#B554FF" />
|
||||
<Badge color="grape" radius="sm" variant="light">
|
||||
{msg?.type || "Unknown"}
|
||||
</Badge>
|
||||
</Group>
|
||||
|
||||
{answer && (
|
||||
<Card
|
||||
p="sm"
|
||||
radius="md"
|
||||
style={{
|
||||
backgroundColor: "#2D2D2D",
|
||||
border: "1px solid rgba(0,255,255,0.1)",
|
||||
}}
|
||||
>
|
||||
<Text c="#EAEAEA" fz="sm">
|
||||
{JSON.stringify(answer, null, 2)}
|
||||
</Text>
|
||||
</Card>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<Card
|
||||
radius="lg"
|
||||
style={{
|
||||
backgroundColor: "#2D2D2D",
|
||||
border: "1px solid rgba(0,255,255,0.1)",
|
||||
textAlign: "center",
|
||||
padding: 40,
|
||||
}}
|
||||
>
|
||||
<Text c="#9A9A9A" fz="lg">
|
||||
No webhook data available yet.
|
||||
</Text>
|
||||
</Card>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
))}
|
||||
<Pagination
|
||||
value={page}
|
||||
total={data?.data?.count || 1}
|
||||
onChange={(value) => {
|
||||
setPage(value)
|
||||
mutate()
|
||||
}}
|
||||
withEdges
|
||||
/>
|
||||
</Stack>
|
||||
</ScrollArea>
|
||||
|
||||
<Group justify="center" mt="md">
|
||||
<Pagination
|
||||
value={page}
|
||||
total={data?.data?.count || 1}
|
||||
onChange={(value) => {
|
||||
setPage(value);
|
||||
mutate();
|
||||
}}
|
||||
radius="xl"
|
||||
withEdges
|
||||
color="teal"
|
||||
/>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user