gitscope
← marzneshin / v0.6.4 / dashboard/src/modules/settings/subscription/form/form.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/modules/settings/subscription/form/form.tsx · TypeScript
Blame Raw
  1import { zodResolver } from "@hookform/resolvers/zod";
  2import { useFieldArray, useForm } from "react-hook-form";
  3import { useTranslation } from "react-i18next";
  4import { schema } from "./schema";
  5import { RuleItem } from "./rule-item";
  6import {
  7    HStack,
  8    Button,
  9    Form,
 10    Sortable,
 11    ScrollArea,
 12    FormLabel,
 13    Separator,
 14    Awaiting,
 15    CheckboxField,
 16} from "@marzneshin/common/components";
 17import { Schema } from "./schema"
 18import { Overlay } from "./overlay"
 19import {
 20    ProfileTitleField,
 21    SupportLinkField,
 22    UpdateIntervalField,
 23    PlaceholderRemarkField,
 24} from "./fields";
 25import { NoRulesAlert } from "./no-rules-alert";
 26import {
 27    useSubscriptionSettingsQuery,
 28    useSubscriptionSettingsMutation,
 29} from "@marzneshin/modules/settings/subscription";
 30import { useEffect, useCallback } from "react";
 31
 32export function SubscriptionRulesForm() {
 33    const { t } = useTranslation()
 34    const { data, isFetching } = useSubscriptionSettingsQuery()
 35    const subscriptionSettings = useSubscriptionSettingsMutation()
 36    const form = useForm<Schema>({
 37        resolver: zodResolver(schema),
 38        defaultValues: data,
 39    })
 40
 41    const handleResetLocalChanges = useCallback(
 42        () => {
 43            form.reset(data)
 44        },
 45        [form, data],
 46    )
 47
 48    const handleSubscriptionRulesDataUpdate = useCallback(
 49        () => {
 50            form.reset(data, {
 51                keepDirtyValues: true
 52            })
 53        },
 54        [form, data],
 55    )
 56
 57    useEffect(() => {
 58        if (data) {
 59            handleSubscriptionRulesDataUpdate()
 60        }
 61    }, [data, handleSubscriptionRulesDataUpdate])
 62
 63    const onSubmit = (data: Schema) => {
 64        subscriptionSettings.mutate(data)
 65    }
 66
 67    const { fields, append, move, remove } = useFieldArray({
 68        control: form.control,
 69        name: "rules"
 70    })
 71
 72    return (
 73        <Form {...form}>
 74            <form
 75                onSubmit={form.handleSubmit(onSubmit)}
 76                className="flex w-full max-w-4xl flex-col gap-2"
 77            >
 78                <ProfileTitleField />
 79                <div className="md:grid grid-cols-2 gap-2 flex flex-col">
 80                    <UpdateIntervalField />
 81                    <SupportLinkField />
 82                </div>
 83                <CheckboxField
 84                    name="template_on_acceptance"
 85                    label={t("page.settings.subscription-settings.template-on-acceptance")}
 86                />
 87                <PlaceholderRemarkField />
 88                <CheckboxField
 89                    name="placeholder_if_disabled"
 90                    label={t("page.settings.subscription-settings.placeholder-if-disabled")}
 91                />
 92                <CheckboxField
 93                    name="shuffle_configs"
 94                    label={t("page.settings.subscription-settings.shuffle-configs")}
 95                />
 96                <Separator className="my-3" />
 97                <h4 className="text-lg mt-2">
 98                    {t("page.settings.subscription-settings.subscription-title")}
 99                </h4>
100                <p className="text-sm text-muted-foreground">
101                    {t("page.settings.subscription-settings.subscription-desc")}
102                </p>
103                <Awaiting
104                    isFetching={isFetching}
105                    Skeleton={
106                        <>
107                            <Overlay />
108                            <Overlay />
109                            <Overlay />
110                            <Overlay />
111                        </>
112                    }
113                    isNotFound={fields.length === 0}
114                    NotFound={<NoRulesAlert />}
115                    Component={
116                        <div className="space-y-1">
117                            <Sortable
118                                value={fields}
119                                onMove={({ activeIndex, overIndex }) =>
120                                    move(activeIndex, overIndex)
121                                }
122                            >
123                                <div className="grid grid-cols-[2fr,1.3fr,0.25fr,0.25fr] items-center justify-start gap-2 my-2">
124                                    <FormLabel>
125                                        {t("pattern")}
126                                    </FormLabel>
127                                    <FormLabel>
128                                        {t("result")}
129                                    </FormLabel>
130                                </div>
131                                <ScrollArea className="flex flex-col w-full max-h-[400px] gap-2" type="always">
132                                    {fields.map((field, index) => (
133                                        <RuleItem
134                                            field={field}
135                                            index={index}
136                                            onRemove={remove} />
137                                    ))}
138                                </ScrollArea>
139                            </Sortable>
140                        </div>
141                    }
142                />
143                <HStack className="w-full flex-end">
144                    <Button
145                        type="button"
146                        variant="destructive"
147                        className="w-fit"
148                        onMouseDown={handleResetLocalChanges}
149                    >
150                        {t("page.settings.subscription-settings.reset-local-changes")}
151                    </Button>
152                    <Button
153                        type="button"
154                        variant="outline"
155                        className="w-fit"
156                        onClick={() =>
157                            append({
158                                pattern: "",
159                                result: "block",
160                            })
161                        }
162                    >
163                        {t("page.settings.subscription-settings.add-rule")}
164                    </Button>
165                    <Button type="submit" className="w-fit">
166                        {t("submit")}
167                    </Button>
168                </HStack>
169            </form>
170        </Form>
171    )
172}