WhatsApp/Signal/Formstack/admin updates

This commit is contained in:
Darren Clarke 2025-11-21 14:55:28 +01:00
parent bcecf61a46
commit d0cc5a21de
451 changed files with 16139 additions and 39623 deletions

View file

@ -34,6 +34,8 @@ export const Detail: FC<DetailProps> = ({ service, row }) => {
const { almostBlack } = colors;
const { bodyLarge } = typography;
const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false);
const [showRelinkConfirmation, setShowRelinkConfirmation] = useState(false);
const [isRelinking, setIsRelinking] = useState(false);
const continueDeleteAction = async () => {
await deleteAction?.(id);
@ -41,6 +43,23 @@ export const Detail: FC<DetailProps> = ({ service, row }) => {
router.push(`${getBasePath()}${entity}`);
};
const continueRelinkAction = async () => {
setIsRelinking(true);
try {
const response = await fetch(`/link/api/${entity}/bots/${token}/relink`, {
method: "POST",
});
if (response.ok) {
setShowRelinkConfirmation(false);
router.refresh();
}
} catch (error) {
console.error("Relink failed:", error);
} finally {
setIsRelinking(false);
}
};
return (
<>
<Dialog
@ -57,6 +76,15 @@ export const Detail: FC<DetailProps> = ({ service, row }) => {
onClick={() => setShowDeleteConfirmation(true)}
/>
</Grid>
{service === "whatsapp" && (
<Grid item>
<Button
text="Relink"
kind="secondary"
onClick={() => setShowRelinkConfirmation(true)}
/>
</Grid>
)}
<Grid item>
<Button
text="Edit"
@ -129,6 +157,35 @@ export const Detail: FC<DetailProps> = ({ service, row }) => {
Are you sure you want to delete this record?
</Box>
</Dialog>
<Dialog
open={showRelinkConfirmation}
size="xs"
title="Relink WhatsApp Connection?"
buttons={
<Grid container justifyContent="space-between">
<Grid item>
<Button
text="Cancel"
kind="secondary"
onClick={() => setShowRelinkConfirmation(false)}
disabled={isRelinking}
/>
</Grid>
<Grid item>
<Button
text={isRelinking ? "Relinking..." : "Relink"}
kind="primary"
onClick={continueRelinkAction}
disabled={isRelinking}
/>
</Grid>
</Grid>
}
>
<Box sx={{ ...bodyLarge, color: almostBlack }}>
This will disconnect the current WhatsApp link and generate a new QR code. You will need to scan the new QR code to reconnect. Continue?
</Box>
</Dialog>
</>
);
};

View file

@ -1,4 +1,5 @@
import { FC, useEffect, useState } from "react";
// @ts-ignore - react-qr-code doesn't have React 19 compatible types yet
import QRCodeInternal from "react-qr-code";
import { Box } from "@mui/material";
import { colors } from "../styles/theme";
@ -28,22 +29,30 @@ export const QRCode: FC<QRCodeProps> = ({
useEffect(() => {
if (!verified && getValue && refreshInterval) {
const interval = setInterval(async () => {
// Fetch immediately on mount
const fetchQR = async () => {
const { qr, kind } = await getValue(token);
console.log({ kind });
setValue(qr);
setKind(kind);
}, refreshInterval * 1000);
};
fetchQR();
// Then set up interval for refreshes
const interval = setInterval(fetchQR, refreshInterval * 1000);
return () => clearInterval(interval);
}
}, [getValue, refreshInterval]);
}, [getValue, refreshInterval, token, verified]);
return !verified ? (
<Box sx={{ backgroundColor: white, m: 2 }}>
{kind === "data" ? (
<QRCodeInternal value={value} />
{value ? (
kind === "data" ? (
<QRCodeInternal value={value} />
) : (
<img src={value} alt={name} />
)
) : (
<img src={value} alt={name} />
<Box>Loading QR code...</Box>
)}
<Box>{helperText}</Box>
</Box>

View file

@ -3,18 +3,19 @@ type ServiceLayoutProps = {
detail: any;
edit: any;
create: any;
params: {
params: Promise<{
segment: string[];
};
}>;
};
export const ServiceLayout = ({
export const ServiceLayout = async ({
children,
detail,
edit,
create,
params: { segment },
params,
}: ServiceLayoutProps) => {
const { segment } = await params;
const length = segment?.length ?? 0;
const isCreate = length === 2 && segment[1] === "create";
const isEdit = length === 3 && segment[2] === "edit";