Skip to content

Commit 4aa8064

Browse files
authored
Merge pull request #1574 from AshishViradiya153/218-presetOption
feat: Extend presets with all link options
2 parents 8423b43 + 9e20892 commit 4aa8064

29 files changed

Lines changed: 1765 additions & 925 deletions

File tree

components/links/link-sheet/agreement-panel/index.tsx

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import { useTeam } from "@/context/team-context";
1010
import { toast } from "sonner";
1111
import { mutate } from "swr";
1212

13+
import {
14+
DocumentData,
15+
createAgreementDocument,
16+
} from "@/lib/documents/create-document";
17+
import { putFile } from "@/lib/files/put-file";
18+
import { getSupportedContentType } from "@/lib/utils/get-content-type";
19+
1320
import DocumentUpload from "@/components/document-upload";
1421
import { Button } from "@/components/ui/button";
1522
import { Input } from "@/components/ui/input";
@@ -24,33 +31,55 @@ import {
2431
SheetTitle,
2532
} from "@/components/ui/sheet";
2633

27-
import {
28-
DocumentData,
29-
createAgreementDocument,
30-
} from "@/lib/documents/create-document";
31-
import { putFile } from "@/lib/files/put-file";
32-
import { getSupportedContentType } from "@/lib/utils/get-content-type";
33-
3434
import LinkItem from "../link-item";
3535

3636
export default function AgreementSheet({
37+
defaultData,
3738
isOpen,
3839
setIsOpen,
40+
isOnlyView = false,
41+
onClose,
3942
}: {
43+
defaultData?: { name: string; link: string; requireName: boolean } | null;
4044
isOpen: boolean;
4145
setIsOpen: Dispatch<SetStateAction<boolean>>;
46+
isOnlyView?: boolean;
47+
onClose?: () => void;
4248
}) {
4349
const teamInfo = useTeam();
4450
const teamId = teamInfo?.currentTeam?.id;
4551
const [data, setData] = useState({ name: "", link: "", requireName: true });
4652
const [isLoading, setIsLoading] = useState<boolean>(false);
4753
const [currentFile, setCurrentFile] = useState<File | null>(null);
48-
const [currentLink, setCurrentLink] = useState<string | null>(null);
54+
55+
useEffect(() => {
56+
if (defaultData) {
57+
setData({
58+
name: defaultData?.name || "",
59+
link: defaultData?.link || "",
60+
requireName: defaultData?.requireName || true,
61+
});
62+
}
63+
}, [defaultData]);
64+
65+
const handleClose = (open: boolean) => {
66+
setIsOpen(open);
67+
setData({ name: "", link: "", requireName: true });
68+
setCurrentFile(null);
69+
setIsLoading(false);
70+
if (onClose) {
71+
onClose();
72+
}
73+
};
4974

5075
const handleBrowserUpload = async () => {
5176
// event.preventDefault();
5277
// event.stopPropagation();
53-
78+
if (isOnlyView) {
79+
handleClose(false);
80+
toast.error("Cannot upload file in view mode!");
81+
return;
82+
}
5483
// Check if the file is chosen
5584
if (!currentFile) {
5685
toast.error("Please select a file to upload.");
@@ -112,6 +141,11 @@ export default function AgreementSheet({
112141
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
113142
e.preventDefault();
114143
e.stopPropagation();
144+
if (isOnlyView) {
145+
handleClose(false);
146+
toast.error("Agreement cannot be created in view mode");
147+
return;
148+
}
115149

116150
setIsLoading(true);
117151

@@ -151,13 +185,16 @@ export default function AgreementSheet({
151185
}, [currentFile]);
152186

153187
return (
154-
<Sheet open={isOpen} onOpenChange={setIsOpen}>
188+
<Sheet open={isOpen} onOpenChange={handleClose}>
155189
<SheetContent className="flex h-full w-[85%] flex-col justify-between bg-background px-4 text-foreground sm:w-[500px] md:px-5">
156190
<SheetHeader className="text-start">
157-
<SheetTitle>Create a new agreement</SheetTitle>
191+
<SheetTitle>
192+
{isOnlyView ? "View Agreement" : "Create a new agreement"}
193+
</SheetTitle>
158194
<SheetDescription>
159-
An agreement is a special document that visitors must accept before
160-
accessing your link. You can create a new agreement here.
195+
{isOnlyView
196+
? "View the details of this agreement."
197+
: "An agreement is a special document that visitors must accept before accessing your link. You can create a new agreement here."}
161198
</SheetDescription>
162199
</SheetHeader>
163200

@@ -182,6 +219,7 @@ export default function AgreementSheet({
182219
name: e.target.value,
183220
})
184221
}
222+
disabled={isOnlyView}
185223
/>
186224
</div>
187225

@@ -192,6 +230,7 @@ export default function AgreementSheet({
192230
action={() =>
193231
setData({ ...data, requireName: !data.requireName })
194232
}
233+
isAllowed={!isOnlyView}
195234
/>
196235
</div>
197236

@@ -220,28 +259,38 @@ export default function AgreementSheet({
220259
"Please enter a valid URL starting with https://",
221260
)
222261
}
262+
disabled={isOnlyView}
223263
/>
224264
</div>
225265

226-
<div className="space-y-12">
227-
<div className="space-y-2 pb-6">
228-
<Label>Or upload an agreement</Label>
229-
<div className="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
230-
<DocumentUpload
231-
currentFile={currentFile}
232-
setCurrentFile={setCurrentFile}
233-
/>
266+
{!isOnlyView ? (
267+
<div className="space-y-12">
268+
<div className="space-y-2 pb-6">
269+
<Label>Or upload an agreement</Label>
270+
<div className="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
271+
<DocumentUpload
272+
currentFile={currentFile}
273+
setCurrentFile={setCurrentFile}
274+
/>
275+
</div>
234276
</div>
235277
</div>
236-
</div>
278+
) : null}
237279
</div>
238280
</div>
239-
240-
<SheetFooter className="flex-shrink-0">
281+
<SheetFooter
282+
className={`flex-shrink-0 ${isOnlyView ? "mt-6" : ""}`}
283+
>
241284
<div className="flex items-center">
242-
<Button type="submit" loading={isLoading}>
243-
Create Agreement
244-
</Button>
285+
{isOnlyView ? (
286+
<Button type="button" onClick={() => handleClose(false)}>
287+
Close
288+
</Button>
289+
) : (
290+
<Button type="submit" loading={isLoading}>
291+
Create Agreement
292+
</Button>
293+
)}
245294
</div>
246295
</SheetFooter>
247296
</form>

components/links/link-sheet/agreement-section.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect, useState, useMemo } from "react";
22

33
import { motion } from "motion/react";
44

@@ -17,6 +17,7 @@ import { DEFAULT_LINK_TYPE } from ".";
1717
import AgreementSheet from "./agreement-panel";
1818
import LinkItem from "./link-item";
1919
import { LinkUpgradeOptions } from "./link-options";
20+
import { Agreement } from "@prisma/client";
2021

2122
export default function AgreementSection({
2223
data,
@@ -39,6 +40,8 @@ export default function AgreementSection({
3940
const [isAgreementSheetVisible, setIsAgreementSheetVisible] =
4041
useState<boolean>(false);
4142

43+
const filteredAgreements = useMemo(() => agreements.filter((agreement: Agreement) => !agreement.deletedAt || agreement.id === agreementId), [agreements]);
44+
4245
useEffect(() => {
4346
setEnabled(enableAgreement!);
4447
}, [enableAgreement]);
@@ -98,8 +101,8 @@ export default function AgreementSection({
98101
<SelectValue placeholder="Select an agreement" />
99102
</SelectTrigger>
100103
<SelectContent>
101-
{agreements &&
102-
agreements.map(({ id, name }) => (
104+
{filteredAgreements &&
105+
filteredAgreements.map(({ id, name }) => (
103106
<SelectItem key={id} value={id}>
104107
{name}
105108
</SelectItem>

components/links/link-sheet/allow-list-section.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { useEffect, useState } from "react";
22

3+
import { LinkPreset } from "@prisma/client";
34
import { motion } from "motion/react";
45

5-
import { Textarea } from "@/components/ui/textarea";
6-
76
import { FADE_IN_ANIMATION_SETTINGS } from "@/lib/constants";
87
import { sanitizeAllowDenyList } from "@/lib/utils";
98

9+
import { Textarea } from "@/components/ui/textarea";
10+
1011
import { DEFAULT_LINK_TYPE } from ".";
1112
import LinkItem from "./link-item";
1213
import { LinkUpgradeOptions } from "./link-options";
@@ -16,6 +17,7 @@ export default function AllowListSection({
1617
setData,
1718
isAllowed,
1819
handleUpgradeStateChange,
20+
presets,
1921
}: {
2022
data: DEFAULT_LINK_TYPE;
2123
setData: React.Dispatch<React.SetStateAction<DEFAULT_LINK_TYPE>>;
@@ -25,6 +27,7 @@ export default function AllowListSection({
2527
trigger,
2628
plan,
2729
}: LinkUpgradeOptions) => void;
30+
presets: LinkPreset | null;
2831
}) {
2932
const { emailProtected, allowList } = data;
3033

@@ -46,6 +49,13 @@ export default function AllowListSection({
4649
}));
4750
}, [allowListInput, emailProtected, enabled, setData]);
4851

52+
useEffect(() => {
53+
if (isAllowed && presets?.allowList && presets.allowList.length > 0) {
54+
setEnabled(true);
55+
setAllowListInput(presets.allowList.join("\n") || "");
56+
}
57+
}, [presets, isAllowed]);
58+
4959
const handleEnableAllowList = () => {
5060
const updatedEnabled = !enabled;
5161
setEnabled(updatedEnabled);
@@ -99,7 +109,9 @@ export default function AllowListSection({
99109
<Textarea
100110
className="focus:ring-inset"
101111
rows={5}
102-
placeholder="Enter allowed emails/domains, one per line, e.g. [email protected] @example.org"
112+
placeholder={`Enter allowed emails/domains, one per line, e.g.
113+
114+
@example.org`}
103115
value={allowListInput}
104116
onChange={handleAllowListChange}
105117
/>

components/links/link-sheet/custom-fields-panel/custom-field.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect, useState, useCallback, memo } from "react";
22

3-
import { ChevronDown, ChevronUp, Trash2 } from "lucide-react";
3+
import { Trash2 } from "lucide-react";
44

55
import { Button } from "@/components/ui/button";
66
import { Input } from "@/components/ui/input";
@@ -26,7 +26,7 @@ interface CustomFieldProps {
2626
isLast?: boolean;
2727
}
2828

29-
export default function CustomField({
29+
export default memo(function CustomField({
3030
field,
3131
onUpdate,
3232
onDelete,
@@ -39,7 +39,7 @@ export default function CustomField({
3939

4040
useEffect(() => {
4141
onUpdate(localField);
42-
}, [localField, onUpdate]);
42+
}, [localField]);
4343

4444
const handleInputChange = (
4545
e: React.ChangeEvent<HTMLInputElement>,
@@ -166,4 +166,4 @@ export default function CustomField({
166166
</div>
167167
</div>
168168
);
169-
}
169+
});

components/links/link-sheet/custom-fields-panel/index.tsx

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { CustomField, CustomFieldType } from "@prisma/client";
22
import { Plus } from "lucide-react";
33
import { toast } from "sonner";
4+
import { useCallback, useMemo } from "react";
45

56
import { Button } from "@/components/ui/button";
67
import { ScrollArea } from "@/components/ui/scroll-area";
@@ -40,14 +41,13 @@ export default function CustomFieldsPanel({
4041
}) {
4142
const { isDatarooms, isDataroomsPlus, isBusiness } = usePlan();
4243

43-
const getFieldLimit = () => {
44+
const fieldLimit = useMemo(() => {
4445
if (isDatarooms || isDataroomsPlus) return 3;
4546
if (isBusiness) return 1;
4647
return 0;
47-
};
48+
}, [isDatarooms, isDataroomsPlus, isBusiness]);
4849

49-
const addField = () => {
50-
const fieldLimit = getFieldLimit();
50+
const addField = useCallback(() => {
5151
if (fields.length >= fieldLimit) {
5252
toast.error(
5353
`You can only add up to ${fieldLimit} custom field${fieldLimit === 1 ? "" : "s"} on the ${isDatarooms ? "Data Rooms" : "Business"} plan`,
@@ -65,24 +65,24 @@ export default function CustomFieldsPanel({
6565
orderIndex: fields.length,
6666
};
6767
onChange([...fields, newField]);
68-
};
68+
}, [fields, fieldLimit, isDatarooms, onChange]);
6969

70-
const updateField = (index: number, updatedField: CustomFieldData) => {
70+
const updateField = useCallback((index: number, updatedField: CustomFieldData) => {
7171
const newFields = [...fields];
7272
newFields[index] = updatedField;
7373
onChange(newFields);
74-
};
74+
}, [fields, onChange]);
7575

76-
const removeField = (index: number) => {
76+
const removeField = useCallback((index: number) => {
7777
const newFields = fields.filter((_, i) => i !== index);
7878
// Update orderIndex for remaining fields
7979
newFields.forEach((field, i) => {
8080
field.orderIndex = i;
8181
});
8282
onChange(newFields);
83-
};
83+
}, [fields, onChange]);
8484

85-
const moveField = (index: number, direction: "up" | "down") => {
85+
const moveField = useCallback((index: number, direction: "up" | "down") => {
8686
if (
8787
(direction === "up" && index === 0) ||
8888
(direction === "down" && index === fields.length - 1)
@@ -102,9 +102,7 @@ export default function CustomFieldsPanel({
102102
});
103103

104104
onChange(newFields);
105-
};
106-
107-
const fieldLimit = getFieldLimit();
105+
}, [fields, onChange]);
108106

109107
return (
110108
<Sheet open={isConfigOpen} onOpenChange={setIsConfigOpen}>

0 commit comments

Comments
 (0)