From b744363736c8b3e42dbec343de12378ea4d7ab35 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Wed, 11 Dec 2024 16:42:23 +0800 Subject: [PATCH] refactor(ui): refactor emails state using zustand store --- ui/src/components/certimate/EmailsEdit.tsx | 34 +++++---------- ui/src/components/notify/Bark.tsx | 6 +-- ui/src/components/notify/DingTalk.tsx | 6 +-- ui/src/components/notify/Email.tsx | 6 +-- ui/src/components/notify/Lark.tsx | 6 +-- ui/src/components/notify/NotifyTemplate.tsx | 6 +-- ui/src/components/notify/ServerChan.tsx | 6 +-- ui/src/components/notify/Telegram.tsx | 6 +-- ui/src/components/notify/Webhook.tsx | 6 +-- ui/src/components/workflow/ApplyForm.tsx | 15 ++++--- ui/src/domain/settings.ts | 13 +++--- ui/src/i18n/locales/zh/nls.access.json | 2 +- ui/src/i18n/locales/zh/nls.workflow.json | 2 +- ui/src/pages/accesses/AccessList.tsx | 6 +-- ui/src/pages/settings/SSLProvider.tsx | 21 +++++----- ui/src/providers/config/index.tsx | 46 +++++---------------- ui/src/providers/config/reducer.ts | 22 +--------- ui/src/providers/notify/index.tsx | 12 +++--- ui/src/providers/notify/reducer.tsx | 6 +-- ui/src/repository/settings.ts | 36 +++++----------- ui/src/stores/contact/index.ts | 44 ++++++++++++++++++++ 21 files changed, 141 insertions(+), 166 deletions(-) create mode 100644 ui/src/stores/contact/index.ts diff --git a/ui/src/components/certimate/EmailsEdit.tsx b/ui/src/components/certimate/EmailsEdit.tsx index 367c25ea..49bad862 100644 --- a/ui/src/components/certimate/EmailsEdit.tsx +++ b/ui/src/components/certimate/EmailsEdit.tsx @@ -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) => { - 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(); diff --git a/ui/src/components/notify/Bark.tsx b/ui/src/components/notify/Bark.tsx index 2dafe5b4..f09f2bce 100644 --- a/ui/src/components/notify/Bark.tsx +++ b/ui/src/components/notify/Bark.tsx @@ -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: { diff --git a/ui/src/components/notify/DingTalk.tsx b/ui/src/components/notify/DingTalk.tsx index 6b8c729e..04e5b577 100644 --- a/ui/src/components/notify/DingTalk.tsx +++ b/ui/src/components/notify/DingTalk.tsx @@ -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: { diff --git a/ui/src/components/notify/Email.tsx b/ui/src/components/notify/Email.tsx index e285ee17..3defc2f3 100644 --- a/ui/src/components/notify/Email.tsx +++ b/ui/src/components/notify/Email.tsx @@ -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: { diff --git a/ui/src/components/notify/Lark.tsx b/ui/src/components/notify/Lark.tsx index a52e34fa..e70278e9 100644 --- a/ui/src/components/notify/Lark.tsx +++ b/ui/src/components/notify/Lark.tsx @@ -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: { diff --git a/ui/src/components/notify/NotifyTemplate.tsx b/ui/src/components/notify/NotifyTemplate.tsx index 251a6d2f..1ca6bd63 100644 --- a/ui/src/components/notify/NotifyTemplate.tsx +++ b/ui/src/components/notify/NotifyTemplate.tsx @@ -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, diff --git a/ui/src/components/notify/ServerChan.tsx b/ui/src/components/notify/ServerChan.tsx index 4e97294a..cb2ff1a6 100644 --- a/ui/src/components/notify/ServerChan.tsx +++ b/ui/src/components/notify/ServerChan.tsx @@ -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: { diff --git a/ui/src/components/notify/Telegram.tsx b/ui/src/components/notify/Telegram.tsx index 31d793e5..0fb3ad40 100644 --- a/ui/src/components/notify/Telegram.tsx +++ b/ui/src/components/notify/Telegram.tsx @@ -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: { diff --git a/ui/src/components/notify/Webhook.tsx b/ui/src/components/notify/Webhook.tsx index d9377f43..13145f21 100644 --- a/ui/src/components/notify/Webhook.tsx +++ b/ui/src/components/notify/Webhook.tsx @@ -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: { diff --git a/ui/src/components/workflow/ApplyForm.tsx b/ui/src/components/workflow/ApplyForm.tsx index 998e5564..c4a6e306 100644 --- a/ui/src/components/workflow/ApplyForm.tsx +++ b/ui/src/components/workflow/ApplyForm.tsx @@ -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) => { {t("domain.application.form.email.list")} - {(emails.content as EmailsSetting).emails.map((item) => ( + {emails.map((item) => (
{item}
diff --git a/ui/src/domain/settings.ts b/ui/src/domain/settings.ts index 46803370..df2e2b04 100644 --- a/ui/src/domain/settings.ts +++ b/ui/src/domain/settings.ts @@ -1,10 +1,11 @@ -export type Setting = { - id?: string; - name?: string; - content?: T; -}; +import { type BaseModel } from "pocketbase"; -export type EmailsSetting = { +export interface Settings extends BaseModel { + name: string; + content: T; +} + +export type EmailsSettingsContent = { emails: string[]; }; diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index fbbe38b5..cbf8c677 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -1,7 +1,7 @@ { "access.page.title": "授权管理", - "access.nodata": "暂无授权信息,请先新建", + "access.nodata": "暂无授权信息,请先新建授权", "access.action.add": "新建授权", "access.action.edit": "编辑授权", diff --git a/ui/src/i18n/locales/zh/nls.workflow.json b/ui/src/i18n/locales/zh/nls.workflow.json index bbb0c364..7e6e7783 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.json +++ b/ui/src/i18n/locales/zh/nls.workflow.json @@ -1,7 +1,7 @@ { "workflow.page.title": "工作流", - "workflow.nodata": "暂无工作流,请先新建", + "workflow.nodata": "暂无工作流,请先新建工作流", "workflow.action.create": "新建工作流", "workflow.action.edit": "编辑工作流", diff --git a/ui/src/pages/accesses/AccessList.tsx b/ui/src/pages/accesses/AccessList.tsx index 8198cfdc..174db0b6 100644 --- a/ui/src/pages/accesses/AccessList.tsx +++ b/ui/src/pages/accesses/AccessList.tsx @@ -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; diff --git a/ui/src/pages/settings/SSLProvider.tsx b/ui/src/pages/settings/SSLProvider.tsx index d8421c74..879e1472 100644 --- a/ui/src/pages/settings/SSLProvider.tsx +++ b/ui/src/pages/settings/SSLProvider.tsx @@ -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; - onSubmit: (data: Setting) => void; - setConfig: (config: Setting) => void; + setting: Settings; + onSubmit: (data: Settings) => void; + setConfig: (config: Settings) => void; }; const Context = createContext({} as SSLProviderContext); @@ -31,19 +31,18 @@ export const useSSLProviderContext = () => { const SSLProvider = () => { const { t } = useTranslation(); - const [config, setConfig] = useState>({ - id: "", + const [config, setConfig] = useState>({ content: { provider: "letsencrypt", config: {}, }, - }); + } as Settings); const { toast } = useToast(); useEffect(() => { const fetchData = async () => { - const setting = await getSetting("ssl-provider"); + const setting = await get("ssl-provider"); if (setting) { setConfig(setting); @@ -74,10 +73,10 @@ const SSLProvider = () => { return ""; }; - const onSubmit = async (data: Setting) => { + const onSubmit = async (data: Settings) => { try { console.log(data); - const resp = await update({ ...data }); + const resp = await save({ ...data }); setConfig(resp); toast({ title: t("common.text.operation_succeeded"), diff --git a/ui/src/providers/config/index.tsx b/ui/src/providers/config/index.tsx index 511a3d4c..7a3162fa 100644 --- a/ui/src/providers/config/index.tsx +++ b/ui/src/providers/config/index.tsx @@ -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; + accesses: AccessType[]; }; export type ConfigContext = { config: ConfigData; - setEmails: (email: Setting) => 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) => { - 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} ); }; diff --git a/ui/src/providers/config/reducer.ts b/ui/src/providers/config/reducer.ts index 9586f9bb..7864d30d 100644 --- a/ui/src/providers/config/reducer.ts +++ b/ui/src/providers/config/reducer.ts @@ -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 } - | { 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; } diff --git a/ui/src/providers/notify/index.tsx b/ui/src/providers/notify/index.tsx index 29b25421..73a331fa 100644 --- a/ui/src/providers/notify/index.tsx +++ b/ui/src/providers/notify/index.tsx @@ -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; + config: Settings; setChannel: (data: { channel: string; data: NotifyChannel }) => void; - setChannels: (data: Setting) => void; + setChannels: (data: Settings) => void; initChannels: () => void; }; @@ -27,7 +27,7 @@ export const NotifyProvider = ({ children }: NotifyProviderProps) => { }, []); const featchData = async () => { - const chanels = await getSetting("notifyChannels"); + const chanels = await get("notifyChannels"); dispatchNotify({ type: "SET_CHANNELS", payload: chanels, @@ -45,7 +45,7 @@ export const NotifyProvider = ({ children }: NotifyProviderProps) => { }); }, []); - const setChannels = useCallback((setting: Setting) => { + const setChannels = useCallback((setting: Settings) => { dispatchNotify({ type: "SET_CHANNELS", payload: setting, diff --git a/ui/src/providers/notify/reducer.tsx b/ui/src/providers/notify/reducer.tsx index 8bdaecc9..1641c594 100644 --- a/ui/src/providers/notify/reducer.tsx +++ b/ui/src/providers/notify/reducer.tsx @@ -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; + payload: Settings; }; -export const notifyReducer = (state: Setting, action: Action) => { +export const notifyReducer = (state: Settings, action: Action) => { switch (action.type) { case "SET_CHANNEL": { const channel = action.payload.channel; diff --git a/ui/src/repository/settings.ts b/ui/src/repository/settings.ts index 1b008f57..3ea1b5ba 100644 --- a/ui/src/repository/settings.ts +++ b/ui/src/repository/settings.ts @@ -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 (name: string) => { try { - const resp = await getPocketBase().collection("settings").getFirstListItem>("name='emails'"); + const resp = await getPocketBase().collection("settings").getFirstListItem>(`name='${name}'`); return resp; - } catch (e) { + } catch { return { - content: { emails: [] }, - }; - } -}; - -export const getSetting = async (name: string) => { - try { - const resp = await getPocketBase().collection("settings").getFirstListItem>(`name='${name}'`); - return resp; - } catch (e) { - const rs: Setting = { name: name, - }; - return rs; + content: {} as T, + } as Settings; } }; -export const update = async (setting: Setting) => { - const pb = getPocketBase(); - let resp: Setting; - if (setting.id) { - resp = await pb.collection("settings").update(setting.id, setting); - } else { - resp = await pb.collection("settings").create(setting); +export const save = async (record: Settings) => { + if (record.id) { + return await getPocketBase().collection("settings").update>(record.id, record); } - return resp; + + return await getPocketBase().collection("settings").create>(record); }; diff --git a/ui/src/stores/contact/index.ts b/ui/src/stores/contact/index.ts new file mode 100644 index 00000000..8b0bb3ef --- /dev/null +++ b/ui/src/stores/contact/index.ts @@ -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; +} + +export const useContactStore = create((set) => { + let settings: Settings; + + return { + emails: [], + + setEmails: async (emails: string[]) => { + settings ??= await getSettings("emails"); + settings = await saveSettings({ + ...settings, + content: { + ...settings.content, + emails: emails, + }, + }); + + set( + produce((state: ContactState) => { + state.emails = settings.content.emails; + }) + ); + }, + + fetchEmails: async () => { + settings = await getSettings("emails"); + + set({ + emails: settings.content.emails?.sort() ?? [], + }); + }, + }; +});