diff --git a/app/components/data-table.tsx b/app/components/data-table.tsx index f989308..171e2b5 100644 --- a/app/components/data-table.tsx +++ b/app/components/data-table.tsx @@ -1,8 +1,8 @@ import { useMemo} from "react"; -import { BaseRecord } from "@refinedev/core"; +import type { BaseRecord } from "@refinedev/core"; import { useTable } from "@refinedev/react-table"; import { - ColumnDef, + type ColumnDef, flexRender, } from "@tanstack/react-table"; @@ -56,9 +56,9 @@ export function DataTable({ {table.getHeaderGroups().map((headerGroup) => ( - {headerGroup.headers.map((header) => { + {headerGroup.headers.map((header, index) => { return ( - + {header.isPlaceholder ? null : flexRender( @@ -73,14 +73,14 @@ export function DataTable({ {rows.length ? ( - rows.map((row) => ( + rows.map((row, index) => ( - {row.getVisibleCells().map((cell) => ( - + {row.getVisibleCells().map((cell, index) => ( + {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} diff --git a/app/components/forms.tsx b/app/components/forms.tsx index faaa14d..ea1d989 100644 --- a/app/components/forms.tsx +++ b/app/components/forms.tsx @@ -1,6 +1,6 @@ import { Label } from "@radix-ui/react-label" import { Input } from "./ui/input" -import { FieldName, useInputControl } from "@conform-to/react" +import { type FieldName, useInputControl } from "@conform-to/react" import { useId } from "react" import { cn } from "~/utils" import { Checkbox } from "~/components/ui/checkbox" @@ -58,7 +58,7 @@ export const FieldCheckbox = ({ const input = useInputControl({ key, name: inputProps.name, - formId: inputProps.form, + formId: inputProps.form, initialValue: defaultChecked ? checkedValue : undefined }) const fallbackId = useId() diff --git a/app/components/general-layout.tsx b/app/components/general-layout.tsx index 4e67447..eab243f 100644 --- a/app/components/general-layout.tsx +++ b/app/components/general-layout.tsx @@ -25,20 +25,30 @@ import { PageIcon, ThemeIcon, } from "./icons"; -import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem } from "./ui/dropdown-menu"; +import { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, +} from "./ui/dropdown-menu"; import { Avatar } from "@radix-ui/react-avatar"; import { cn } from "~/utils"; import { useGetIdentity, useLogout } from "@refinedev/core"; -import { Identity } from "~/data/auth-provider"; import { PinningNetworkBanner } from "./pinning-network-banner"; import { PinningProvider } from "~/providers/PinningProvider"; +import type { Identity } from "~/data/auth-provider"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, + TooltipProvider, +} from "./ui/tooltip"; - -export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => { +export const GeneralLayout = ({ children }: React.PropsWithChildren) => { const location = useLocation(); const { data: identity } = useGetIdentity(); - const{ mutate: logout } = useLogout() - + const { mutate: logout } = useLogout(); return (
@@ -93,7 +103,6 @@ export const GeneralLayout = ({ children }: React.PropsWithChildren<{}>) => { -
@@ -252,6 +265,7 @@ const UploadFileItem = ({ file: UppyFile; onRemove: (id: string) => void; }) => { + const sizeInMb = bytestoMegabytes(file.size).toFixed(2); return (
@@ -263,12 +277,23 @@ const UploadFileItem = ({ )}
-

- - {file.name} - {" "} - ({bytestoMegabytes(file.size).toFixed(2)} MB) -

+ + + +

+ + {file.name} + {" "} + ({sizeInMb}MB) +

+
+ +

+ {file.name} ({sizeInMb}MB) +

+
+
+
- -
- - + + + +

File Manager

+ + + + + + +

Files

+
+ } + placeholder="Search files by name or CID" + className="border-ring font-medium w-full grow h-12 flex-1 bg-primary-2/10" + /> + + + + +
+ + + + Pin Content + +
+ + + + +
+
+
+
); } diff --git a/app/routes/login.otp.tsx b/app/routes/login.otp.tsx new file mode 100644 index 0000000..0002c40 --- /dev/null +++ b/app/routes/login.otp.tsx @@ -0,0 +1,69 @@ +import { getFormProps, useForm } from "@conform-to/react"; +import { getZodConstraint, parseWithZod } from "@conform-to/zod"; +import { useGo, useIsAuthenticated, useParsed } from "@refinedev/core"; +import { Link } from "@remix-run/react"; +import { useEffect } from "react"; +import { z } from "zod"; +import { Field } from "~/components/forms"; +import { Button } from "~/components/ui/button"; +import type { LoginParams } from "./login"; + +const OtpSchema = z.object({ + otp: z.string().length(6, { message: "OTP must be 6 characters" }), +}); + +export default function OtpForm() { + const { isLoading: isAuthLoading, data: authData } = useIsAuthenticated(); + const go = useGo(); + const parsed = useParsed(); + // TODO: Add support for resending the OTP + const [form, fields] = useForm({ + id: "otp", + constraint: getZodConstraint(OtpSchema), + onValidate({ formData }) { + return parseWithZod(formData, { schema: OtpSchema }); + }, + shouldValidate: "onSubmit", + }); + const valid = true; + const to = parsed.params?.to ?? "/dashboard"; + + useEffect(() => { + if (!isAuthLoading) { + if (authData?.authenticated && valid) { + go({ to, type: "push" }); + } + } + }, [isAuthLoading, authData, to, go]); + + return ( +
+ +

Check your inbox

+

+ We will need the six digit confirmation code you received in your + email in order to verify your account and get started. Didn’t receive + a code?{" "} + +

+
+ + +

+ + ← Back to Login + +

+ + ); +} diff --git a/app/routes/login.tsx b/app/routes/login.tsx index 0e495cf..8c4a480 100644 --- a/app/routes/login.tsx +++ b/app/routes/login.tsx @@ -1,5 +1,5 @@ import type { MetaFunction } from "@remix-run/node"; -import { Link, useLocation } from "@remix-run/react"; +import { Link } from "@remix-run/react"; import { z } from "zod"; import { Button } from "~/components/ui/button"; import logoPng from "~/images/lume-logo.png?url"; @@ -11,7 +11,6 @@ import { getFormProps, useForm } from "@conform-to/react"; import { getZodConstraint, parseWithZod } from "@conform-to/zod"; import { useGo, - useIsAuthenticated, useLogin, useParsed, } from "@refinedev/core"; @@ -25,30 +24,11 @@ export const meta: MetaFunction = () => { ]; }; -type LoginParams = { +export type LoginParams = { to: string; }; export default function Login() { - const location = useLocation(); - const { isLoading: isAuthLoading, data: authData } = useIsAuthenticated(); - const hash = location.hash; - const go = useGo(); - const parsed = useParsed(); - - useEffect(() => { - if (!isAuthLoading) { - if (authData?.authenticated) { - let to = "/dashboard"; - if (parsed.params?.to) { - to = parsed.params.to; - } - - go({ to, type: "push" }); - } - } - }, [isAuthLoading, authData]); - return (
@@ -62,8 +42,7 @@ export default function Login() { />
- {hash === "" && } - {hash === "#otp" && } +