bid-tool/auto-bid-admin/src/components/config/mails-config.tsx

162 lines
3.8 KiB
TypeScript

import {
ActionIcon,
Box,
Card,
Group,
LoadingOverlay,
Text,
TextInput,
} from "@mantine/core";
import { useForm, zodResolver } from "@mantine/form";
import { IconAt, IconMinus, IconPlus } from "@tabler/icons-react";
import { useEffect, useMemo, useState } from "react";
import { z } from "zod";
import { getConfig, upsertConfig } from "../../apis/config";
import { IConfig } from "../../system/type";
import { useConfirmStore } from "../../lib/zustand/use-confirm";
import { useDisclosure } from "@mantine/hooks";
const schema = z.object({
email: z
.string({ message: "Email is required" })
.email({ message: "Invalid email address" }),
});
const MailInput = ({
initValue,
onDelete,
onAdd,
}: {
initValue?: string;
onDelete?: (data: string) => void;
onAdd?: (data: string) => Promise<void>;
}) => {
const form = useForm({
initialValues: {
email: initValue || "",
},
validate: zodResolver(schema),
});
return (
<form
onSubmit={form.onSubmit(
onAdd
? async (values) => {
await onAdd(values.email);
form.reset();
}
: () => {}
)}
className="flex items-start gap-2 w-full"
>
<TextInput
{...form.getInputProps("email")}
leftSection={<IconAt size={14} />}
placeholder="Enter email"
className="flex-1"
size="xs"
/>
<ActionIcon
onClick={initValue && onDelete ? () => onDelete(initValue) : undefined}
type={!initValue ? "submit" : "button"}
color={initValue ? "red" : "blue"}
variant="light"
>
{initValue ? <IconMinus size={14} /> : <IconPlus size={14} />}
</ActionIcon>
</form>
);
};
export default function MailsConfig() {
const [config, setConfig] = useState<null | IConfig>(null);
const { setConfirm } = useConfirmStore();
const [opened, { open, close }] = useDisclosure(false);
useEffect(() => {
fetchConfig();
}, []);
const mails = useMemo(() => {
if (!config) return [];
return config?.value?.split(", ").length > 0
? config?.value.split(",")
: [];
}, [config]);
const fetchConfig = async () => {
const response = await getConfig("MAIL_SCRAP_REPORT");
if (!response || ![200, 201].includes(response.data?.status_code)) return;
setConfig(response.data.data);
};
const handleDelete = (mail: string) => {
setConfirm({
message: "Are you want to delete: " + mail,
title: "Delete",
handleOk: async () => {
open();
const newMails = mails.filter((item) => item !== mail);
if (!config) return;
const response = await upsertConfig({
...(config as IConfig),
value: newMails.join(", "),
});
if (response) {
fetchConfig();
}
close();
},
});
};
const handleAdd = async (mail: string) => {
const newMails = [...mails, mail];
open();
const response = await upsertConfig({
...(config as IConfig),
value: newMails.join(", "),
});
if (response) {
fetchConfig();
}
close();
};
return (
<Card withBorder shadow="sm" radius="md" w={400}>
<Card.Section withBorder inheritPadding py="xs">
<Group justify="space-between">
<Text fw={500}>Mails</Text>
</Group>
</Card.Section>
<Card.Section p="md">
<Box className="flex flex-col gap-2">
{mails.length > 0 &&
mails.map((mail) => {
return (
<MailInput
onDelete={handleDelete}
key={mail}
initValue={mail}
/>
);
})}
<MailInput onAdd={handleAdd} />
</Box>
</Card.Section>
<LoadingOverlay visible={opened} />
</Card>
);
}