From 6f10d173c08f80f79b4cf511de407d039ea4dbcb Mon Sep 17 00:00:00 2001 From: Tania Gutierrez Date: Wed, 13 Mar 2024 21:49:04 -0400 Subject: [PATCH 1/6] feat: Added user dropdown and active navbar item state --- app/components/general-layout.tsx | 42 ++++++++++++++++++++++++------- package.json | 5 ++-- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/app/components/general-layout.tsx b/app/components/general-layout.tsx index be41b25..337dd39 100644 --- a/app/components/general-layout.tsx +++ b/app/components/general-layout.tsx @@ -2,7 +2,7 @@ import { Button } from "~/components/ui/button" import logoPng from "~/images/lume-logo.png?url" import lumeColorLogoPng from "~/images/lume-color-logo.png?url" import discordLogoPng from "~/images/discord-logo.png?url" -import { Link } from "@remix-run/react" +import { Link, useLocation } from "@remix-run/react" import { Dialog, DialogContent, @@ -14,7 +14,7 @@ import { useUppy } from "./lib/uppy" import type { UppyFile } from "@uppy/core" import { Progress } from "~/components/ui/progress" import { DialogClose } from "@radix-ui/react-dialog" -import { TrashIcon } from "@radix-ui/react-icons" +import { ChevronDownIcon, TrashIcon } from "@radix-ui/react-icons" import { ClockIcon, DriveIcon, @@ -22,10 +22,15 @@ import { CloudUploadIcon, CloudCheckIcon, BoxCheckedIcon, - PageIcon + PageIcon, + ThemeIcon } from "./icons" +import { DropdownMenu, DropdownMenuTrigger } from "./ui/dropdown-menu" +import { Avatar } from "@radix-ui/react-avatar" +import { cn } from "~/utils" export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => { + const location = useLocation(); return (
@@ -35,7 +40,7 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => {
  • - + Dashboard @@ -43,7 +48,7 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => {
  • - + File Manager @@ -51,7 +56,7 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => {
  • - + Account @@ -71,13 +76,29 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => { Upload Files - +
+
+ + + + + + + +
+ {children}
@@ -250,9 +271,12 @@ const UploadFileItem = ({ ) } -const NavigationButton = ({ children }: React.PropsWithChildren) => { +const NavigationButton = ({ children, active }: React.PropsWithChildren<{ active?: boolean }>) => { return ( - ) diff --git a/package.json b/package.json index 93ae956..5e6653e 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,11 @@ "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.0.2", - "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-progress": "^1.0.3", + "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-slot": "^1.0.2", "@refinedev/cli": "^2.16.1", "@refinedev/core": "https://gitpkg.now.sh/LumeWeb/refine/packages/core?remix", @@ -31,10 +32,10 @@ "@remix-run/node": "^2.8.0", "@remix-run/react": "^2.8.0", "@tanstack/react-table": "^8.13.2", - "@visx/visx": "^3.10.2", "@uppy/core": "^3.9.3", "@uppy/tus": "^3.5.3", "@uppy/utils": "^5.7.4", + "@visx/visx": "^3.10.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "react": "^18.2.0", From 988dab24d1d789bce3c6c256c81726aa551f96e0 Mon Sep 17 00:00:00 2001 From: Tania Gutierrez Date: Wed, 13 Mar 2024 21:50:01 -0400 Subject: [PATCH 2/6] fix: Styled input and field components acording to design --- app/components/forms.tsx | 3 ++- app/components/ui/input.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/components/forms.tsx b/app/components/forms.tsx index c79eeec..faaa14d 100644 --- a/app/components/forms.tsx +++ b/app/components/forms.tsx @@ -23,9 +23,10 @@ export const Field = ({ const errorId = errors?.length ? `${id}-error` : undefined return (
-
@@ -32,4 +37,4 @@ export const UsageCard = ({ label, monthlyUsage, currentUsage, icon }: UsageCard
) -} \ No newline at end of file +} From bdc6de39b42e500be021d6f04d108a5eca97a0c8 Mon Sep 17 00:00:00 2001 From: Tania Gutierrez Date: Wed, 13 Mar 2024 21:52:31 -0400 Subject: [PATCH 4/6] feat: Added My Account route --- app/components/icons.tsx | 228 ++++++++++++++-------- app/components/management-card.tsx | 123 ++++++++++++ app/components/ui/button.tsx | 2 +- app/components/ui/dropdown-menu.tsx | 203 ++++++++++++++++++++ app/images/QR.png | Bin 0 -> 5012 bytes app/routes/account.tsx | 287 ++++++++++++++++++++++++++++ 6 files changed, 762 insertions(+), 81 deletions(-) create mode 100644 app/components/management-card.tsx create mode 100644 app/components/ui/dropdown-menu.tsx create mode 100644 app/images/QR.png create mode 100644 app/routes/account.tsx diff --git a/app/components/icons.tsx b/app/components/icons.tsx index 72fab8a..64dd2af 100644 --- a/app/components/icons.tsx +++ b/app/components/icons.tsx @@ -7,8 +7,7 @@ export const InfoIcon = ({ className }: { className?: string }) => { viewBox="0 0 23 24" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { - ) -} + ); +}; export const AddIcon = ({ className }: { className?: string }) => { return ( @@ -38,8 +37,7 @@ export const AddIcon = ({ className }: { className?: string }) => { viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { - ) -} + ); +}; export const CloudIcon = ({ className }: { className?: string }) => { return ( @@ -64,15 +62,14 @@ export const CloudIcon = ({ className }: { className?: string }) => { viewBox="0 0 23 21" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const CloudDownloadIcon = ({ className }: { className?: string }) => { return ( @@ -83,8 +80,7 @@ export const CloudDownloadIcon = ({ className }: { className?: string }) => { viewBox="0 0 21 15" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { fill="currentColor" /> - ) -} + ); +}; export const CloudUploadIcon = ({ className }: { className?: string }) => { return ( @@ -104,15 +100,14 @@ export const CloudUploadIcon = ({ className }: { className?: string }) => { viewBox="-0.5 0 21 17" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const CloudUploadSolidIcon = ({ className }: { className?: string }) => { return ( @@ -123,15 +118,14 @@ export const CloudUploadSolidIcon = ({ className }: { className?: string }) => { viewBox="0 0 24 16" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const CrownIcon = ({ className }: { className?: string }) => { return ( @@ -142,15 +136,14 @@ export const CrownIcon = ({ className }: { className?: string }) => { viewBox="0 0 20 15" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const PersonIcon = ({ className }: { className?: string }) => { return ( @@ -161,15 +154,14 @@ export const PersonIcon = ({ className }: { className?: string }) => { viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const CheckRoundedIcon = ({ className }: { className?: string }) => { return ( @@ -180,15 +172,14 @@ export const CheckRoundedIcon = ({ className }: { className?: string }) => { viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const ClockIcon = ({ className }: { className?: string }) => { return ( @@ -199,15 +190,14 @@ export const ClockIcon = ({ className }: { className?: string }) => { viewBox="0 0 23 23" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const CircleLockIcon = ({ className }: { className?: string }) => { return ( @@ -218,15 +208,14 @@ export const CircleLockIcon = ({ className }: { className?: string }) => { viewBox="0 0 23 24" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const DriveIcon = ({ className }: { className?: string }) => { return ( @@ -237,15 +226,14 @@ export const DriveIcon = ({ className }: { className?: string }) => { viewBox="0 0 23 24" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const PageIcon = ({ className }: { className?: string }) => { return ( @@ -256,8 +244,7 @@ export const PageIcon = ({ className }: { className?: string }) => { viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { strokeLinejoin="round" /> - ) -} + ); +}; export const TrashIcon = ({ className }: { className?: string }) => { return ( @@ -307,8 +294,7 @@ export const TrashIcon = ({ className }: { className?: string }) => { viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { fill="currentColor" /> - ) -} + ); +}; export const CloudCheckIcon = ({ className }: { className?: string }) => { return ( @@ -346,8 +332,7 @@ export const CloudCheckIcon = ({ className }: { className?: string }) => { viewBox="0 0 72 48" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { fill="currentColor" /> - ) -} + ); +}; export const BoxCheckedIcon = ({ className }: { className?: string }) => { return ( @@ -367,8 +352,7 @@ export const BoxCheckedIcon = ({ className }: { className?: string }) => { viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { strokeLinejoin="round" /> - ) -} + ); +}; export const PictureIcon = ({ className }: { className?: string }) => { return ( @@ -396,8 +380,7 @@ export const PictureIcon = ({ className }: { className?: string }) => { viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { fill="currentColor" /> - ) -} + ); +}; export const XlsxIcon = ({ className }: { className?: string }) => { return ( @@ -417,8 +400,7 @@ export const XlsxIcon = ({ className }: { className?: string }) => { viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { fill="currentColor" /> - ) -} + ); +}; export const FileIcon = ({ className }: { className?: string }) => { return ( @@ -438,15 +420,14 @@ export const FileIcon = ({ className }: { className?: string }) => { viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> - ) -} + ); +}; export const MoreIcon = ({ className }: { className?: string }) => { return ( @@ -457,8 +438,7 @@ export const MoreIcon = ({ className }: { className?: string }) => { viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" - className={className} - > + className={className}> { fill="currentColor" /> - ) -} + ); +}; + +export const FingerPrintIcon = ({ className }: { className?: string }) => { + return ( + + + + + + + + + + + ); +}; + +export const EditIcon = ({ className }: { className?: string }) => { + return ( + + + + + + + + + + + ); +}; + +export const ThemeIcon = ({ className }: { className?: string }) => { + return ( + + + + ); +}; + +export const ChevronDownIcon = ({ className }: { className?: string }) => { + return ( + + + + ); +}; diff --git a/app/components/management-card.tsx b/app/components/management-card.tsx new file mode 100644 index 0000000..8cb69b5 --- /dev/null +++ b/app/components/management-card.tsx @@ -0,0 +1,123 @@ +import { cn } from "~/utils"; +import { Avatar } from "./ui/avatar"; +import { Button } from "./ui/button"; +import { AddIcon, EditIcon, FingerPrintIcon } from "./icons"; +import { Dialog, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "./ui/dialog"; +import { DialogContent, Portal } from "@radix-ui/react-dialog"; + +interface ManagementCardProps { + title?: string; + value?: string; + subtitle?: string; + isInviteCard?: boolean; + isPasswordCard?: boolean; + isAvatarCard?: boolean; + isDeleteCard?: boolean + buttonText?: string; + buttonOnClick?: () => void + dialogNode?: React.ReactNode +} + +export const ManagementCard = ({ + title, + isAvatarCard, + isInviteCard, + isPasswordCard, + isDeleteCard, + subtitle, + value, + buttonText, + buttonOnClick, + dialogNode +}: ManagementCardProps) => { + const buttonVariant: string = isInviteCard ? "accent" : isDeleteCard ? "destructive" : "default"; + return ( +
+ {isAvatarCard ? ( +
+ + +
+ ) : ( + <> +
+ +

{title}

+
+ {subtitle && ( + {subtitle} + )} + {value && ( + {value} + )} + {isPasswordCard && } + {!dialogNode ? ( + + ): ( + + Open + + + Are you absolutely sure? + + This action cannot be undone. This will permanently delete your account + and remove your data from our servers. + + + + + + )} + + )} +
+ ); +}; + +const PasswordDots = ({ className }: { className?: string }) => { + return ( + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/app/components/ui/button.tsx b/app/components/ui/button.tsx index 6302846..6c8859e 100644 --- a/app/components/ui/button.tsx +++ b/app/components/ui/button.tsx @@ -14,7 +14,7 @@ const buttonVariants = cva( // TODO: name it better accent: "bg-ring text-primary-1-foreground hover:bg-ring/75 font-bold", destructive: - "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + "bg-destructive text-white shadow-sm hover:bg-destructive/90", outline: "border border-input bg-background shadow-sm hover:bg-primary-2/5", secondary: diff --git a/app/components/ui/dropdown-menu.tsx b/app/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..cbe1985 --- /dev/null +++ b/app/components/ui/dropdown-menu.tsx @@ -0,0 +1,203 @@ +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { + CheckIcon, + ChevronRightIcon, + DotFilledIcon, +} from "@radix-ui/react-icons" + +import { cn } from "~/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/app/images/QR.png b/app/images/QR.png new file mode 100644 index 0000000000000000000000000000000000000000..2a2a4f61f1a38cb1f05c3ae9135652e96061d1b2 GIT binary patch literal 5012 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 nA +

My Account

+ } + button={ + + } + /> +

Account Management

+
+ + setModal({ ...openModal, changeEmail: true })} + /> + +
+

Security

+
+ setModal({ ...openModal, changePassword: true })} + /> + setModal({ ...openModal, setupTwoFactor: true })} + /> + +
+

More

+
+ + + +
+ {/* Dialogs must be near to body as possible to open the modal, otherwise will be restricted to parent height-width */} + + setModal({ ...openModal, changeEmail: value }) + } + currentValue="bsimpson@springfield.oh.gov.com" + /> + + setModal({ ...openModal, changePassword: value }) + } + /> + + setModal({ ...openModal, setupTwoFactor: value }) + } + /> + + ); +} + +const ChangeEmailSchema = z.object({ + email: z.string().email(), + password: z.string(), + retypePassword: z.string(), +}); + +const ChangeEmailForm = ({ + open, + setOpen, + currentValue, +}: { + open: boolean; + setOpen: (value: boolean) => void; + currentValue: string; +}) => { + const [form, fields] = useForm({ + id: "login", + constraint: getZodConstraint(ChangeEmailSchema), + onValidate({ formData }) { + return parseWithZod(formData, { schema: ChangeEmailSchema }); + }, + shouldValidate: "onSubmit", + }); + + return ( + + + + Change Email +
+ {currentValue} +
+
+ + + + + +
+
+
+ ); +}; + +const ChangePasswordSchema = z.object({ + currentPassword: z.string().email(), + newPassword: z.string(), + retypePassword: z.string(), +}); + +const ChangePasswordForm = ({ + open, + setOpen, +}: { + open: boolean; + setOpen: (value: boolean) => void; +}) => { + const [form, fields] = useForm({ + id: "login", + constraint: getZodConstraint(ChangeEmailSchema), + onValidate({ formData }) { + return parseWithZod(formData, { schema: ChangePasswordSchema }); + }, + shouldValidate: "onSubmit", + }); + + return ( + + + + Change Password +
+ + + + + +
+
+
+ ); +}; + +const SetupTwoFactorDialog = ({ + open, + setOpen, +}: { + open: boolean; + setOpen: (value: boolean) => void; +}) => { + const [continueModal, setContinue] = useState(false); + + return ( + { + setOpen(value) + setContinue(false); + }}> + + + Setup Two-Factor +
+ {continueModal ? ( + <> +

Enter the authentication code generated in your two-factor application to confirm your setup.

+ + + + ) : ( + <> +
+ QR +
+

+ Don’t have access to scan? Use this code instead. +

+
+ HHH7MFGAMPJ44OM44FGAMPJ44O232 +
+ + + )} +
+
+
+
+ ); +}; From c7d7a129b96920ee54f7cbd1b4fa95cf5bbd3054 Mon Sep 17 00:00:00 2001 From: Tania Gutierrez Date: Wed, 13 Mar 2024 21:53:06 -0400 Subject: [PATCH 5/6] chore: Moved Icon definitions to icon.tsx --- app/components/file-card.tsx | 75 +----------------------------------- app/components/icons.tsx | 47 ++++++++++++++++++++++ app/components/ui/input.tsx | 2 +- 3 files changed, 50 insertions(+), 74 deletions(-) diff --git a/app/components/file-card.tsx b/app/components/file-card.tsx index 263edf6..7e6717e 100644 --- a/app/components/file-card.tsx +++ b/app/components/file-card.tsx @@ -1,3 +1,5 @@ +import { FolderIcon, MoreIcon, RecentIcon } from "./icons"; + export enum FileTypes { Folder = "FOLDER", Document = "DOCUMENT", @@ -33,76 +35,3 @@ export const FileCard = ({ type, fileName, createdAt, size }: FileCardProps) =>
); }; - -const FolderIcon = ({ className }: { className?: string }) => { - return ( - - - - ); -}; - -const MoreIcon = ({ className }: { className?: string }) => { - return ( - - - - - - ); -}; - -const RecentIcon = ({ className }: { className?: string }) => { - return ( - - - - - - - - - - - - ); -}; diff --git a/app/components/icons.tsx b/app/components/icons.tsx index 64dd2af..d2a51e8 100644 --- a/app/components/icons.tsx +++ b/app/components/icons.tsx @@ -542,3 +542,50 @@ export const ChevronDownIcon = ({ className }: { className?: string }) => { ); }; + +export const FolderIcon = ({ className }: { className?: string }) => { + return ( + + + + ); +}; + +export const RecentIcon = ({ className }: { className?: string }) => { + return ( + + + + + + + + + + + + ); +}; \ No newline at end of file diff --git a/app/components/ui/input.tsx b/app/components/ui/input.tsx index 8ea96d2..0bcde50 100644 --- a/app/components/ui/input.tsx +++ b/app/components/ui/input.tsx @@ -5,7 +5,7 @@ import { EyeOpenIcon, EyeNoneIcon } from "@radix-ui/react-icons" export interface InputProps extends React.InputHTMLAttributes { - fullWidth: boolean, + fullWidth?: boolean, leftIcon?: React.ReactNode } From 260b41b29b9543f3e2acd133f8cdcaed258555bd Mon Sep 17 00:00:00 2001 From: Tania Gutierrez Date: Wed, 13 Mar 2024 21:55:44 -0400 Subject: [PATCH 6/6] style: Formatted code --- app/components/general-layout.tsx | 112 ++++++++++++++++-------------- app/routes/account.tsx | 51 ++++++++------ 2 files changed, 88 insertions(+), 75 deletions(-) diff --git a/app/components/general-layout.tsx b/app/components/general-layout.tsx index 337dd39..7eeb351 100644 --- a/app/components/general-layout.tsx +++ b/app/components/general-layout.tsx @@ -1,20 +1,20 @@ -import { Button } from "~/components/ui/button" -import logoPng from "~/images/lume-logo.png?url" -import lumeColorLogoPng from "~/images/lume-color-logo.png?url" -import discordLogoPng from "~/images/discord-logo.png?url" -import { Link, useLocation } from "@remix-run/react" +import { Button } from "~/components/ui/button"; +import logoPng from "~/images/lume-logo.png?url"; +import lumeColorLogoPng from "~/images/lume-color-logo.png?url"; +import discordLogoPng from "~/images/discord-logo.png?url"; +import { Link, useLocation } from "@remix-run/react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, - DialogTrigger -} from "~/components/ui/dialog" -import { useUppy } from "./lib/uppy" -import type { UppyFile } from "@uppy/core" -import { Progress } from "~/components/ui/progress" -import { DialogClose } from "@radix-ui/react-dialog" -import { ChevronDownIcon, TrashIcon } from "@radix-ui/react-icons" + DialogTrigger, +} from "~/components/ui/dialog"; +import { useUppy } from "./lib/uppy"; +import type { UppyFile } from "@uppy/core"; +import { Progress } from "~/components/ui/progress"; +import { DialogClose } from "@radix-ui/react-dialog"; +import { ChevronDownIcon, TrashIcon } from "@radix-ui/react-icons"; import { ClockIcon, DriveIcon, @@ -23,11 +23,11 @@ import { CloudCheckIcon, BoxCheckedIcon, PageIcon, - ThemeIcon -} from "./icons" -import { DropdownMenu, DropdownMenuTrigger } from "./ui/dropdown-menu" -import { Avatar } from "@radix-ui/react-avatar" -import { cn } from "~/utils" + ThemeIcon, +} from "./icons"; +import { DropdownMenu, DropdownMenuTrigger } from "./ui/dropdown-menu"; +import { Avatar } from "@radix-ui/react-avatar"; +import { cn } from "~/utils"; export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => { const location = useLocation(); @@ -40,7 +40,8 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => {
  • - + Dashboard @@ -48,7 +49,8 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => {
  • - + File Manager @@ -56,7 +58,8 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => {
  • - + Account @@ -87,7 +90,7 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => { - + @@ -133,8 +134,8 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => { - ) -} + ); +}; const UploadFileForm = () => { const { @@ -144,17 +145,17 @@ const UploadFileForm = () => { upload, state, removeFile, - cancelAll + cancelAll, } = useUppy({ uploader: "tus", - endpoint: import.meta.env.VITE_PUBLIC_TUS_ENDPOINT - }) + endpoint: import.meta.env.VITE_PUBLIC_TUS_ENDPOINT, + }); - console.log({ state, files: getFiles() }) + console.log({ state, files: getFiles() }); - const isUploading = state === "uploading" - const isCompleted = state === "completed" - const hasStarted = state !== "idle" && state !== "initializing" + const isUploading = state === "uploading"; + const isCompleted = state === "completed"; + const hasStarted = state !== "idle" && state !== "initializing"; return ( <> @@ -164,8 +165,7 @@ const UploadFileForm = () => { {!hasStarted ? (
    + className="border border-border rounded text-primary-2 bg-primary-dark h-48 flex flex-col items-center justify-center"> { key={file.id} file={file} onRemove={(id) => { - removeFile(id) + removeFile(id); }} /> ))} @@ -222,19 +222,19 @@ const UploadFileForm = () => { ) : null} - ) -} + ); +}; function bytestoMegabytes(bytes: number) { - return bytes / 1024 / 1024 + return bytes / 1024 / 1024; } const UploadFileItem = ({ file, - onRemove + onRemove, }: { - file: UppyFile - onRemove: (id: string) => void + file: UppyFile; + onRemove: (id: string) => void; }) => { return (
    @@ -258,8 +258,7 @@ const UploadFileItem = ({ size={"icon"} variant={"ghost"} className="!text-inherit" - onClick={() => onRemove(file.id)} - > + onClick={() => onRemove(file.id)}>
    @@ -268,16 +267,21 @@ const UploadFileItem = ({ ) : null}
    - ) -} + ); +}; -const NavigationButton = ({ children, active }: React.PropsWithChildren<{ active?: boolean }>) => { +const NavigationButton = ({ + children, + active, +}: React.PropsWithChildren<{ active?: boolean }>) => { return ( - - ) -} + ); +}; diff --git a/app/routes/account.tsx b/app/routes/account.tsx index 54f0436..edf89f8 100644 --- a/app/routes/account.tsx +++ b/app/routes/account.tsx @@ -248,36 +248,45 @@ const SetupTwoFactorDialog = ({ open: boolean; setOpen: (value: boolean) => void; }) => { - const [continueModal, setContinue] = useState(false); + const [continueModal, setContinue] = useState(false); return ( - { - setOpen(value) + { + setOpen(value); setContinue(false); - }}> + }}> Setup Two-Factor
    {continueModal ? ( - <> -

    Enter the authentication code generated in your two-factor application to confirm your setup.

    - - - + <> +

    + Enter the authentication code generated in your two-factor + application to confirm your setup. +

    + + + ) : ( - <> -
    - QR -
    -

    - Don’t have access to scan? Use this code instead. -

    -
    - HHH7MFGAMPJ44OM44FGAMPJ44O232 -
    - - + <> +
    + QR +
    +

    + Don’t have access to scan? Use this code instead. +

    +
    + HHH7MFGAMPJ44OM44FGAMPJ44O232 +
    + + )}