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}