Skip to content

Commit

Permalink
chore: Relocate settings subcomponents out of route file (#242)
Browse files Browse the repository at this point in the history
  • Loading branch information
evadecker authored Nov 30, 2024
1 parent 6174fc5 commit 98a5d49
Show file tree
Hide file tree
Showing 21 changed files with 488 additions and 342 deletions.
10 changes: 9 additions & 1 deletion src/components/common/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const overlayStyles = tv({
});

const modalStyles = tv({
base: "p-5 w-full max-w-md max-h-full rounded-2xl bg-gray-subtle forced-colors:bg-[Canvas] flex flex-col items-start gap-4 shadow-2xl bg-clip-padding border border-gray-dim",
base: "p-5 w-[400px] max-w-full max-h-full rounded-2xl bg-gray-subtle forced-colors:bg-[Canvas] flex flex-col items-start gap-4 shadow-2xl bg-clip-padding border border-gray-dim",
variants: {
isEntering: {
true: "animate-in zoom-in-105 ease-out duration-2",
Expand Down Expand Up @@ -58,3 +58,11 @@ export function ModalHeader({ title, children }: ModalHeaderProps) {
</header>
);
}

export function ModalFooter({ children }: { children: React.ReactNode }) {
return (
<footer className="flex w-full justify-end items-center gap-2">
{children}
</footer>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const CostInput = memo(function CostInput({
<div className="flex items-start gap-2">
<NumberField
aria-label="Cost"
className="w-28"
className="w-24"
prefix="$"
value={cost.cost}
onChange={(value) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const TimeRequiredInput = memo(function TimeRequiredInput({
<div className="flex items-end gap-2">
<NumberField
label="Est. min time"
className="w-28"
className="w-24"
value={timeRequired?.min}
maxValue={Math.max(timeRequired.max, 60)}
onChange={(value) =>
Expand All @@ -51,7 +51,7 @@ const TimeRequiredInput = memo(function TimeRequiredInput({
/>
<NumberField
label="Est. max time"
className="w-28"
className="w-24"
value={timeRequired.max}
minValue={Math.min(timeRequired.min, 1)}
onChange={(value) =>
Expand All @@ -63,7 +63,7 @@ const TimeRequiredInput = memo(function TimeRequiredInput({
/>
<Select
label="Unit"
className="w-40"
className="flex-1"
selectedKey={timeRequired.unit}
onSelectionChange={(key) =>
onChange({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Button, Modal, ModalFooter, ModalHeader } from "@/components/common";
import { SettingsItem } from "@/components/settings";
import { useAuthActions } from "@convex-dev/auth/react";
import { api } from "@convex/_generated/api";
import { useMutation } from "convex/react";
import { Trash } from "lucide-react";
import { useState } from "react";

type DeleteAccountModalProps = {
isOpen: boolean;
onOpenChange: (isOpen: boolean) => void;
onSubmit: () => void;
};

const DeleteAccountModal = ({
isOpen,
onOpenChange,
onSubmit,
}: DeleteAccountModalProps) => {
const { signOut } = useAuthActions();

const clearLocalStorage = () => {
localStorage.removeItem("theme");
};
const deleteAccount = useMutation(api.users.deleteCurrentUser);

const handleSubmit = () => {
clearLocalStorage();
deleteAccount();
signOut();
onSubmit();
};

return (
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalHeader title="Delete account?" />
<p>This will permanently erase your account and all data.</p>
<ModalFooter>
<Button onPress={() => onOpenChange(false)}>Cancel</Button>
<Button variant="destructive" onPress={handleSubmit}>
Delete
</Button>
</ModalFooter>
</Modal>
);
};

export const DeleteAccountSetting = () => {
const [isDeleteAccountModalOpen, setIsDeleteAccountModalOpen] =
useState(false);

return (
<SettingsItem
label="Delete account"
description="Permanently delete your Namesake account and data."
>
<Button onPress={() => setIsDeleteAccountModalOpen(true)} icon={Trash}>
Delete account
</Button>
<DeleteAccountModal
isOpen={isDeleteAccountModalOpen}
onOpenChange={setIsDeleteAccountModalOpen}
onSubmit={() => setIsDeleteAccountModalOpen(false)}
/>
</SettingsItem>
);
};
1 change: 1 addition & 0 deletions src/components/settings/DeleteAccountSetting/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./DeleteAccountSetting";
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import {
Button,
Form,
Modal,
ModalFooter,
ModalHeader,
Select,
SelectItem,
} from "@/components/common";
import { api } from "@convex/_generated/api";
import type { Doc } from "@convex/_generated/dataModel";
import { JURISDICTIONS, type Jurisdiction } from "@convex/constants";
import { useMutation } from "convex/react";
import { Pencil } from "lucide-react";
import { useState } from "react";
import { SettingsItem } from "../SettingsItem";

type EditBirthplaceModalProps = {
defaultBirthplace: Jurisdiction;
isOpen: boolean;
onOpenChange: (isOpen: boolean) => void;
onSubmit: () => void;
};

const EditBirthplaceModal = ({
defaultBirthplace,
isOpen,
onOpenChange,
onSubmit,
}: EditBirthplaceModalProps) => {
const updateBirthplace = useMutation(api.users.setBirthplace);
const [birthplace, setBirthplace] = useState(defaultBirthplace);

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
updateBirthplace({ birthplace });
onSubmit();
};

return (
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalHeader title="Edit birthplace" />
<Form onSubmit={handleSubmit} className="w-full">
<Select
aria-label="Birthplace"
name="birthplace"
selectedKey={birthplace}
onSelectionChange={(key) => setBirthplace(key as Jurisdiction)}
placeholder="Select state"
className="w-full"
>
{Object.entries(JURISDICTIONS).map(([value, label]) => (
<SelectItem key={value} id={value}>
{label}
</SelectItem>
))}
</Select>
<ModalFooter>
<Button variant="secondary" onPress={() => onOpenChange(false)}>
Cancel
</Button>
<Button type="submit" variant="primary">
Save
</Button>
</ModalFooter>
</Form>
</Modal>
);
};

type EditBirthplaceSettingProps = {
user: Doc<"users">;
};

export const EditBirthplaceSetting = ({ user }: EditBirthplaceSettingProps) => {
const [isBirthplaceModalOpen, setIsBirthplaceModalOpen] = useState(false);

return (
<SettingsItem
label="Birthplace"
description="Where were you born? This location is used to select the forms for your birth certificate."
>
<Button icon={Pencil} onPress={() => setIsBirthplaceModalOpen(true)}>
{user?.birthplace
? JURISDICTIONS[user.birthplace as Jurisdiction]
: "Set birthplace"}
</Button>
<EditBirthplaceModal
isOpen={isBirthplaceModalOpen}
onOpenChange={setIsBirthplaceModalOpen}
defaultBirthplace={user.birthplace as Jurisdiction}
onSubmit={() => setIsBirthplaceModalOpen(false)}
/>
</SettingsItem>
);
};
1 change: 1 addition & 0 deletions src/components/settings/EditBirthplaceSetting/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./EditBirthplaceSetting";
28 changes: 28 additions & 0 deletions src/components/settings/EditMinorSetting/EditMinorSetting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Switch } from "@/components/common";
import { SettingsItem } from "@/components/settings";
import { api } from "@convex/_generated/api";
import type { Doc } from "@convex/_generated/dataModel";
import { useMutation } from "convex/react";

type EditMinorSettingProps = {
user: Doc<"users">;
};

export const EditMinorSetting = ({ user }: EditMinorSettingProps) => {
const updateIsMinor = useMutation(api.users.setCurrentUserIsMinor);

return (
<SettingsItem
label="Under 18"
description="Are you under 18 years old or applying on behalf of someone who is?"
>
<Switch
name="isMinor"
isSelected={user.isMinor ?? false}
onChange={() => updateIsMinor({ isMinor: !user.isMinor })}
>
<span className="sr-only">Is minor</span>
</Switch>
</SettingsItem>
);
};
1 change: 1 addition & 0 deletions src/components/settings/EditMinorSetting/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./EditMinorSetting";
85 changes: 85 additions & 0 deletions src/components/settings/EditNameSetting/EditNameSetting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import {
Button,
Form,
Modal,
ModalFooter,
ModalHeader,
TextField,
} from "@/components/common";
import { api } from "@convex/_generated/api";
import type { Doc } from "@convex/_generated/dataModel";
import { useMutation } from "convex/react";
import { Pencil } from "lucide-react";
import { useState } from "react";
import { SettingsItem } from "../SettingsItem";

type EditNameModalProps = {
defaultName: string;
isOpen: boolean;
onOpenChange: (isOpen: boolean) => void;
onSubmit: () => void;
};

const EditNameModal = ({
defaultName,
isOpen,
onOpenChange,
onSubmit,
}: EditNameModalProps) => {
const updateName = useMutation(api.users.setName);
const [name, setName] = useState(defaultName);

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
updateName({ name });
onSubmit();
};

return (
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalHeader title="Edit name" />
<Form onSubmit={handleSubmit} className="w-full">
<TextField
name="name"
label="Name"
value={name}
onChange={setName}
className="w-full"
/>
<ModalFooter>
<Button variant="secondary" onPress={() => onOpenChange(false)}>
Cancel
</Button>
<Button type="submit" variant="primary">
Save
</Button>
</ModalFooter>
</Form>
</Modal>
);
};

type EditNameSettingProps = {
user: Doc<"users">;
};

export const EditNameSetting = ({ user }: EditNameSettingProps) => {
const [isNameModalOpen, setIsNameModalOpen] = useState(false);

return (
<SettingsItem
label="Name"
description="How should Namesake refer to you? This can be different from your legal name."
>
<Button icon={Pencil} onPress={() => setIsNameModalOpen(true)}>
{user?.name ?? "Set name"}
</Button>
<EditNameModal
isOpen={isNameModalOpen}
onOpenChange={setIsNameModalOpen}
defaultName={user.name ?? ""}
onSubmit={() => setIsNameModalOpen(false)}
/>
</SettingsItem>
);
};
1 change: 1 addition & 0 deletions src/components/settings/EditNameSetting/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./EditNameSetting";
Loading

0 comments on commit 98a5d49

Please sign in to comment.