mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-29 15:49:56 +00:00
refactor(ui): refactor emails state using zustand store
This commit is contained in:
parent
83ba3d4450
commit
b744363736
@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
@ -10,10 +10,8 @@ import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { PbErrorData } from "@/domain/base";
|
||||
import { EmailsSetting } from "@/domain/settings";
|
||||
import { update } from "@/repository/settings";
|
||||
import { useConfigContext } from "@/providers/config";
|
||||
import { type PbErrorData } from "@/domain/base";
|
||||
import { useContactStore } from "@/stores/contact";
|
||||
|
||||
type EmailsEditProps = {
|
||||
className?: string;
|
||||
@ -21,10 +19,7 @@ type EmailsEditProps = {
|
||||
};
|
||||
|
||||
const EmailsEdit = ({ className, trigger }: EmailsEditProps) => {
|
||||
const {
|
||||
config: { emails },
|
||||
setEmails,
|
||||
} = useConfigContext();
|
||||
const { emails, setEmails, fetchEmails } = useContactStore();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
@ -40,30 +35,21 @@ const EmailsEdit = ({ className, trigger }: EmailsEditProps) => {
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
fetchEmails();
|
||||
}, []);
|
||||
|
||||
const onSubmit = async (data: z.infer<typeof formSchema>) => {
|
||||
if ((emails.content as EmailsSetting).emails.includes(data.email)) {
|
||||
if (emails.includes(data.email)) {
|
||||
form.setError("email", {
|
||||
message: "common.errmsg.email_duplicate",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存到 config
|
||||
const newEmails = [...(emails.content as EmailsSetting).emails, data.email];
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
...emails,
|
||||
name: "emails",
|
||||
content: {
|
||||
emails: newEmails,
|
||||
},
|
||||
});
|
||||
await setEmails([...emails, data.email]);
|
||||
|
||||
// 更新本地状态
|
||||
setEmails(resp);
|
||||
|
||||
// 关闭弹窗
|
||||
form.reset();
|
||||
form.clearErrors();
|
||||
|
||||
|
@ -8,7 +8,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
import { NotifyChannels, NotifyChannelBark } from "@/domain/settings";
|
||||
import { update } from "@/repository/settings";
|
||||
import { save } from "@/repository/settings";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
import Show from "@/components/Show";
|
||||
@ -96,7 +96,7 @@ const Bark = () => {
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
@ -160,7 +160,7 @@ const Bark = () => {
|
||||
setBark(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
|
@ -9,7 +9,7 @@ import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
import { NotifyChannelDingTalk, NotifyChannels } from "@/domain/settings";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { update } from "@/repository/settings";
|
||||
import { save } from "@/repository/settings";
|
||||
import Show from "@/components/Show";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
|
||||
@ -96,7 +96,7 @@ const DingTalk = () => {
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
@ -160,7 +160,7 @@ const DingTalk = () => {
|
||||
setDingtalk(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
|
@ -9,7 +9,7 @@ import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
import { NotifyChannelEmail, NotifyChannels } from "@/domain/settings";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { update } from "@/repository/settings";
|
||||
import { save } from "@/repository/settings";
|
||||
import Show from "@/components/Show";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
|
||||
@ -119,7 +119,7 @@ const Mail = () => {
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
@ -183,7 +183,7 @@ const Mail = () => {
|
||||
setMail(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
|
@ -5,7 +5,7 @@ import { Label } from "@/components/ui/label";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { NotifyChannelLark, NotifyChannels } from "@/domain/settings";
|
||||
import { useEffect, useState } from "react";
|
||||
import { update } from "@/repository/settings";
|
||||
import { save } from "@/repository/settings";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@ -92,7 +92,7 @@ const Lark = () => {
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
@ -156,7 +156,7 @@ const Lark = () => {
|
||||
setLark(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
|
@ -6,7 +6,7 @@ import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { defaultNotifyTemplate, NotifyTemplates, NotifyTemplate as NotifyTemplateT } from "@/domain/settings";
|
||||
import { getSetting, update } from "@/repository/settings";
|
||||
import { get, save } from "@/repository/settings";
|
||||
|
||||
const NotifyTemplate = () => {
|
||||
const [id, setId] = useState("");
|
||||
@ -17,7 +17,7 @@ const NotifyTemplate = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const featchData = async () => {
|
||||
const resp = await getSetting("templates");
|
||||
const resp = await get("templates");
|
||||
|
||||
if (resp.content) {
|
||||
setTemplates((resp.content as NotifyTemplates).notifyTemplates);
|
||||
@ -50,7 +50,7 @@ const NotifyTemplate = () => {
|
||||
};
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
id: id,
|
||||
content: {
|
||||
notifyTemplates: templates,
|
||||
|
@ -9,7 +9,7 @@ import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
import { isValidURL } from "@/utils/url";
|
||||
import { NotifyChannels, NotifyChannelServerChan } from "@/domain/settings";
|
||||
import { update } from "@/repository/settings";
|
||||
import { save } from "@/repository/settings";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
import Show from "@/components/Show";
|
||||
@ -103,7 +103,7 @@ const ServerChan = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
@ -167,7 +167,7 @@ const ServerChan = () => {
|
||||
setServerChan(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
|
@ -8,7 +8,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
import { NotifyChannels, NotifyChannelTelegram } from "@/domain/settings";
|
||||
import { update } from "@/repository/settings";
|
||||
import { save } from "@/repository/settings";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
import Show from "@/components/Show";
|
||||
@ -96,7 +96,7 @@ const Telegram = () => {
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
@ -160,7 +160,7 @@ const Telegram = () => {
|
||||
setTelegram(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
|
@ -9,7 +9,7 @@ import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
import { isValidURL } from "@/utils/url";
|
||||
import { NotifyChannels, NotifyChannelWebhook } from "@/domain/settings";
|
||||
import { update } from "@/repository/settings";
|
||||
import { save } from "@/repository/settings";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
import Show from "@/components/Show";
|
||||
@ -103,7 +103,7 @@ const Webhook = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
@ -167,7 +167,7 @@ const Webhook = () => {
|
||||
setWebhook(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
const resp = await save({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { memo } from "react";
|
||||
|
||||
import { memo, useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import z from "zod";
|
||||
@ -16,8 +15,7 @@ import EmailsEdit from "@/components/certimate/EmailsEdit";
|
||||
import StringList from "@/components/certimate/StringList";
|
||||
|
||||
import { accessProvidersMap } from "@/domain/access";
|
||||
import { EmailsSetting } from "@/domain/settings";
|
||||
|
||||
import { useContactStore } from "@/stores/contact";
|
||||
import { useConfigContext } from "@/providers/config";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { TooltipFast } from "@/components/ui/tooltip";
|
||||
@ -36,8 +34,13 @@ const ApplyForm = ({ data }: ApplyFormProps) => {
|
||||
const { updateNode } = useWorkflowStore(useShallow(selectState));
|
||||
|
||||
const {
|
||||
config: { accesses, emails },
|
||||
config: { accesses },
|
||||
} = useConfigContext();
|
||||
const { emails, fetchEmails } = useContactStore();
|
||||
|
||||
useEffect(() => {
|
||||
fetchEmails();
|
||||
}, []);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -141,7 +144,7 @@ const ApplyForm = ({ data }: ApplyFormProps) => {
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>{t("domain.application.form.email.list")}</SelectLabel>
|
||||
{(emails.content as EmailsSetting).emails.map((item) => (
|
||||
{emails.map((item) => (
|
||||
<SelectItem key={item} value={item}>
|
||||
<div>{item}</div>
|
||||
</SelectItem>
|
||||
|
@ -1,10 +1,11 @@
|
||||
export type Setting<T> = {
|
||||
id?: string;
|
||||
name?: string;
|
||||
content?: T;
|
||||
};
|
||||
import { type BaseModel } from "pocketbase";
|
||||
|
||||
export type EmailsSetting = {
|
||||
export interface Settings<T> extends BaseModel {
|
||||
name: string;
|
||||
content: T;
|
||||
}
|
||||
|
||||
export type EmailsSettingsContent = {
|
||||
emails: string[];
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"access.page.title": "授权管理",
|
||||
|
||||
"access.nodata": "暂无授权信息,请先新建",
|
||||
"access.nodata": "暂无授权信息,请先新建授权",
|
||||
|
||||
"access.action.add": "新建授权",
|
||||
"access.action.edit": "编辑授权",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"workflow.page.title": "工作流",
|
||||
|
||||
"workflow.nodata": "暂无工作流,请先新建",
|
||||
"workflow.nodata": "暂无工作流,请先新建工作流",
|
||||
|
||||
"workflow.action.create": "新建工作流",
|
||||
"workflow.action.edit": "编辑工作流",
|
||||
|
@ -7,7 +7,7 @@ import dayjs from "dayjs";
|
||||
import { ClientResponseError } from "pocketbase";
|
||||
|
||||
import AccessEditDialog from "@/components/certimate/AccessEditDialog";
|
||||
import { Access as AccessType, accessProvidersMap } from "@/domain/access";
|
||||
import { accessProvidersMap, type Access as AccessType } from "@/domain/access";
|
||||
import { remove as removeAccess } from "@/repository/access";
|
||||
import { useConfigContext } from "@/providers/config";
|
||||
|
||||
@ -120,10 +120,10 @@ const AccessList = () => {
|
||||
try {
|
||||
const startIndex = (page - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
const items = configContext.config.accesses.slice(startIndex, endIndex);
|
||||
const items = configContext.config?.accesses?.slice(startIndex, endIndex) ?? [];
|
||||
|
||||
setTableData(items);
|
||||
setTableTotal(configContext.config.accesses.length);
|
||||
setTableTotal(configContext.config?.accesses?.length ?? 0);
|
||||
} catch (err) {
|
||||
if (err instanceof ClientResponseError && err.isAbort) {
|
||||
return;
|
||||
|
@ -12,14 +12,14 @@ import { Label } from "@/components/ui/label";
|
||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
import { SSLProvider as SSLProviderType, SSLProviderSetting, Setting } from "@/domain/settings";
|
||||
import { getSetting, update } from "@/repository/settings";
|
||||
import { SSLProvider as SSLProviderType, SSLProviderSetting, Settings } from "@/domain/settings";
|
||||
import { get, save } from "@/repository/settings";
|
||||
import { produce } from "immer";
|
||||
|
||||
type SSLProviderContext = {
|
||||
setting: Setting<SSLProviderSetting>;
|
||||
onSubmit: (data: Setting<SSLProviderSetting>) => void;
|
||||
setConfig: (config: Setting<SSLProviderSetting>) => void;
|
||||
setting: Settings<SSLProviderSetting>;
|
||||
onSubmit: (data: Settings<SSLProviderSetting>) => void;
|
||||
setConfig: (config: Settings<SSLProviderSetting>) => void;
|
||||
};
|
||||
|
||||
const Context = createContext({} as SSLProviderContext);
|
||||
@ -31,19 +31,18 @@ export const useSSLProviderContext = () => {
|
||||
const SSLProvider = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [config, setConfig] = useState<Setting<SSLProviderSetting>>({
|
||||
id: "",
|
||||
const [config, setConfig] = useState<Settings<SSLProviderSetting>>({
|
||||
content: {
|
||||
provider: "letsencrypt",
|
||||
config: {},
|
||||
},
|
||||
});
|
||||
} as Settings<SSLProviderSetting>);
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const setting = await getSetting<SSLProviderSetting>("ssl-provider");
|
||||
const setting = await get<SSLProviderSetting>("ssl-provider");
|
||||
|
||||
if (setting) {
|
||||
setConfig(setting);
|
||||
@ -74,10 +73,10 @@ const SSLProvider = () => {
|
||||
return "";
|
||||
};
|
||||
|
||||
const onSubmit = async (data: Setting<SSLProviderSetting>) => {
|
||||
const onSubmit = async (data: Settings<SSLProviderSetting>) => {
|
||||
try {
|
||||
console.log(data);
|
||||
const resp = await update({ ...data });
|
||||
const resp = await save({ ...data });
|
||||
setConfig(resp);
|
||||
toast({
|
||||
title: t("common.text.operation_succeeded"),
|
||||
|
@ -1,22 +1,17 @@
|
||||
import { createContext, ReactNode, useCallback, useContext, useEffect, useReducer } from "react";
|
||||
import { createContext, useCallback, useContext, useEffect, useReducer, type ReactNode } from "react";
|
||||
|
||||
import { Access } from "@/domain/access";
|
||||
import { EmailsSetting, Setting } from "@/domain/settings";
|
||||
import { list } from "@/repository/access";
|
||||
|
||||
import { getEmails } from "@/repository/settings";
|
||||
import { type Access as AccessType } from "@/domain/access";
|
||||
import { list as listAccess } from "@/repository/access";
|
||||
import { configReducer } from "./reducer";
|
||||
|
||||
export type ConfigData = {
|
||||
accesses: Access[];
|
||||
emails: Setting<EmailsSetting>;
|
||||
accesses: AccessType[];
|
||||
};
|
||||
|
||||
export type ConfigContext = {
|
||||
config: ConfigData;
|
||||
setEmails: (email: Setting<EmailsSetting>) => void;
|
||||
addAccess: (access: Access) => void;
|
||||
updateAccess: (access: Access) => void;
|
||||
addAccess: (access: AccessType) => void;
|
||||
updateAccess: (access: AccessType) => void;
|
||||
deleteAccess: (id: string) => void;
|
||||
};
|
||||
|
||||
@ -24,45 +19,28 @@ const Context = createContext({} as ConfigContext);
|
||||
|
||||
export const useConfigContext = () => useContext(Context);
|
||||
|
||||
interface ConfigProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export const ConfigProvider = ({ children }: ConfigProviderProps) => {
|
||||
export const ConfigProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [config, dispatchConfig] = useReducer(configReducer, {
|
||||
accesses: [],
|
||||
emails: { content: { emails: [] } },
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const featchData = async () => {
|
||||
const data = await list();
|
||||
const data = await listAccess();
|
||||
dispatchConfig({ type: "SET_ACCESSES", payload: data });
|
||||
};
|
||||
featchData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const featchEmails = async () => {
|
||||
const emails = await getEmails();
|
||||
dispatchConfig({ type: "SET_EMAILS", payload: emails });
|
||||
};
|
||||
featchEmails();
|
||||
}, []);
|
||||
|
||||
const setEmails = useCallback((emails: Setting<EmailsSetting>) => {
|
||||
dispatchConfig({ type: "SET_EMAILS", payload: emails });
|
||||
}, []);
|
||||
|
||||
const deleteAccess = useCallback((id: string) => {
|
||||
dispatchConfig({ type: "DELETE_ACCESS", payload: id });
|
||||
}, []);
|
||||
|
||||
const addAccess = useCallback((access: Access) => {
|
||||
const addAccess = useCallback((access: AccessType) => {
|
||||
dispatchConfig({ type: "ADD_ACCESS", payload: access });
|
||||
}, []);
|
||||
|
||||
const updateAccess = useCallback((access: Access) => {
|
||||
const updateAccess = useCallback((access: AccessType) => {
|
||||
dispatchConfig({ type: "UPDATE_ACCESS", payload: access });
|
||||
}, []);
|
||||
|
||||
@ -71,15 +49,13 @@ export const ConfigProvider = ({ children }: ConfigProviderProps) => {
|
||||
value={{
|
||||
config: {
|
||||
accesses: config.accesses,
|
||||
emails: config.emails,
|
||||
},
|
||||
setEmails,
|
||||
addAccess,
|
||||
updateAccess,
|
||||
deleteAccess,
|
||||
}}
|
||||
>
|
||||
{children && children}
|
||||
{children}
|
||||
</Context.Provider>
|
||||
);
|
||||
};
|
||||
|
@ -1,14 +1,11 @@
|
||||
import { Access } from "@/domain/access";
|
||||
import { EmailsSetting, Setting } from "@/domain/settings";
|
||||
import { ConfigData } from "./";
|
||||
|
||||
type Action =
|
||||
| { type: "ADD_ACCESS"; payload: Access }
|
||||
| { type: "DELETE_ACCESS"; payload: string }
|
||||
| { type: "UPDATE_ACCESS"; payload: Access }
|
||||
| { type: "SET_ACCESSES"; payload: Access[] }
|
||||
| { type: "SET_EMAILS"; payload: Setting<EmailsSetting> }
|
||||
| { type: "ADD_EMAIL"; payload: string };
|
||||
| { type: "SET_ACCESSES"; payload: Access[] };
|
||||
|
||||
export const configReducer = (state: ConfigData, action: Action): ConfigData => {
|
||||
switch (action.type) {
|
||||
@ -36,23 +33,6 @@ export const configReducer = (state: ConfigData, action: Action): ConfigData =>
|
||||
accesses: state.accesses.map((access) => (access.id === action.payload.id ? action.payload : access)),
|
||||
};
|
||||
}
|
||||
case "SET_EMAILS": {
|
||||
return {
|
||||
...state,
|
||||
emails: action.payload,
|
||||
};
|
||||
}
|
||||
case "ADD_EMAIL": {
|
||||
return {
|
||||
...state,
|
||||
emails: {
|
||||
...state.emails,
|
||||
content: {
|
||||
emails: [...(state.emails.content as EmailsSetting).emails, action.payload],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { ReactNode, useContext, createContext, useEffect, useReducer, useCallback } from "react";
|
||||
|
||||
import { NotifyChannel, NotifyChannels, Setting } from "@/domain/settings";
|
||||
import { getSetting } from "@/repository/settings";
|
||||
import { NotifyChannel, NotifyChannels, Settings } from "@/domain/settings";
|
||||
import { get } from "@/repository/settings";
|
||||
import { notifyReducer } from "./reducer";
|
||||
|
||||
export type NotifyContext = {
|
||||
config: Setting<NotifyChannels>;
|
||||
config: Settings<NotifyChannels>;
|
||||
setChannel: (data: { channel: string; data: NotifyChannel }) => void;
|
||||
setChannels: (data: Setting<NotifyChannels>) => void;
|
||||
setChannels: (data: Settings<NotifyChannels>) => void;
|
||||
initChannels: () => void;
|
||||
};
|
||||
|
||||
@ -27,7 +27,7 @@ export const NotifyProvider = ({ children }: NotifyProviderProps) => {
|
||||
}, []);
|
||||
|
||||
const featchData = async () => {
|
||||
const chanels = await getSetting<NotifyChannels>("notifyChannels");
|
||||
const chanels = await get<NotifyChannels>("notifyChannels");
|
||||
dispatchNotify({
|
||||
type: "SET_CHANNELS",
|
||||
payload: chanels,
|
||||
@ -45,7 +45,7 @@ export const NotifyProvider = ({ children }: NotifyProviderProps) => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const setChannels = useCallback((setting: Setting<NotifyChannels>) => {
|
||||
const setChannels = useCallback((setting: Settings<NotifyChannels>) => {
|
||||
dispatchNotify({
|
||||
type: "SET_CHANNELS",
|
||||
payload: setting,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { NotifyChannel, NotifyChannels, Setting } from "@/domain/settings";
|
||||
import { NotifyChannel, NotifyChannels, Settings } from "@/domain/settings";
|
||||
|
||||
type Action =
|
||||
| {
|
||||
@ -10,10 +10,10 @@ type Action =
|
||||
}
|
||||
| {
|
||||
type: "SET_CHANNELS";
|
||||
payload: Setting<NotifyChannels>;
|
||||
payload: Settings<NotifyChannels>;
|
||||
};
|
||||
|
||||
export const notifyReducer = (state: Setting<NotifyChannels>, action: Action) => {
|
||||
export const notifyReducer = (state: Settings<NotifyChannels>, action: Action) => {
|
||||
switch (action.type) {
|
||||
case "SET_CHANNEL": {
|
||||
const channel = action.payload.channel;
|
||||
|
@ -1,36 +1,22 @@
|
||||
import { EmailsSetting, Setting } from "@/domain/settings";
|
||||
import { Settings } from "@/domain/settings";
|
||||
import { getPocketBase } from "./pocketbase";
|
||||
|
||||
export const getEmails = async () => {
|
||||
export const get = async <T>(name: string) => {
|
||||
try {
|
||||
const resp = await getPocketBase().collection("settings").getFirstListItem<Setting<EmailsSetting>>("name='emails'");
|
||||
const resp = await getPocketBase().collection("settings").getFirstListItem<Settings<T>>(`name='${name}'`);
|
||||
return resp;
|
||||
} catch (e) {
|
||||
} catch {
|
||||
return {
|
||||
content: { emails: [] },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export const getSetting = async <T>(name: string) => {
|
||||
try {
|
||||
const resp = await getPocketBase().collection("settings").getFirstListItem<Setting<T>>(`name='${name}'`);
|
||||
return resp;
|
||||
} catch (e) {
|
||||
const rs: Setting<T> = {
|
||||
name: name,
|
||||
};
|
||||
return rs;
|
||||
content: {} as T,
|
||||
} as Settings<T>;
|
||||
}
|
||||
};
|
||||
|
||||
export const update = async <T>(setting: Setting<T>) => {
|
||||
const pb = getPocketBase();
|
||||
let resp: Setting<T>;
|
||||
if (setting.id) {
|
||||
resp = await pb.collection("settings").update(setting.id, setting);
|
||||
} else {
|
||||
resp = await pb.collection("settings").create(setting);
|
||||
export const save = async <T>(record: Settings<T>) => {
|
||||
if (record.id) {
|
||||
return await getPocketBase().collection("settings").update<Settings<T>>(record.id, record);
|
||||
}
|
||||
return resp;
|
||||
|
||||
return await getPocketBase().collection("settings").create<Settings<T>>(record);
|
||||
};
|
||||
|
44
ui/src/stores/contact/index.ts
Normal file
44
ui/src/stores/contact/index.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { create } from "zustand";
|
||||
import { produce } from "immer";
|
||||
|
||||
import { type EmailsSettingsContent, type Settings } from "@/domain/settings";
|
||||
import { get as getSettings, save as saveSettings } from "@/repository/settings";
|
||||
|
||||
export interface ContactState {
|
||||
emails: string[];
|
||||
setEmails: (emails: string[]) => void;
|
||||
fetchEmails: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const useContactStore = create<ContactState>((set) => {
|
||||
let settings: Settings<EmailsSettingsContent>;
|
||||
|
||||
return {
|
||||
emails: [],
|
||||
|
||||
setEmails: async (emails: string[]) => {
|
||||
settings ??= await getSettings<EmailsSettingsContent>("emails");
|
||||
settings = await saveSettings<EmailsSettingsContent>({
|
||||
...settings,
|
||||
content: {
|
||||
...settings.content,
|
||||
emails: emails,
|
||||
},
|
||||
});
|
||||
|
||||
set(
|
||||
produce((state: ContactState) => {
|
||||
state.emails = settings.content.emails;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
fetchEmails: async () => {
|
||||
settings = await getSettings<EmailsSettingsContent>("emails");
|
||||
|
||||
set({
|
||||
emails: settings.content.emails?.sort() ?? [],
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user