From 61010ebf30da5d5ff69d4275c102d28486610fe7 Mon Sep 17 00:00:00 2001 From: Juan Andrade Date: Sun, 5 May 2024 01:32:45 -0300 Subject: [PATCH 01/10] Updated witness component to be a select with search functionallity --- .../[id]/_components/HighlineHeader.tsx | 2 +- .../[id]/_components}/RegistryEntry.tsx | 81 ++-- .../[id]/_components/witness-select.tsx | 401 ++++++++++++++++++ components/ui/badge.tsx | 36 ++ components/ui/command.tsx | 158 +++++++ components/ui/popover.tsx | 46 +- components/ui/separator.tsx | 31 ++ components/ui/skeleton.tsx | 15 + package.json | 2 + yarn.lock | 44 +- 10 files changed, 745 insertions(+), 71 deletions(-) rename {components => app/[locale]/[id]/_components}/RegistryEntry.tsx (87%) create mode 100644 app/[locale]/[id]/_components/witness-select.tsx create mode 100644 components/ui/badge.tsx create mode 100644 components/ui/command.tsx create mode 100644 components/ui/separator.tsx create mode 100644 components/ui/skeleton.tsx diff --git a/app/[locale]/[id]/_components/HighlineHeader.tsx b/app/[locale]/[id]/_components/HighlineHeader.tsx index 90c84d4..829ee26 100644 --- a/app/[locale]/[id]/_components/HighlineHeader.tsx +++ b/app/[locale]/[id]/_components/HighlineHeader.tsx @@ -5,7 +5,7 @@ import { useTranslations } from "next-intl"; import { useEffect, useRef, useState } from "react"; import type { Highline } from "@/app/actions/getHighline"; -import { RegistryEntry } from "@/components/RegistryEntry"; +import { RegistryEntry } from "@/app/[locale]/[id]/_components/RegistryEntry"; import { Button } from "@/components/ui/button"; import { CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { cn } from "@/lib/utils"; diff --git a/components/RegistryEntry.tsx b/app/[locale]/[id]/_components/RegistryEntry.tsx similarity index 87% rename from components/RegistryEntry.tsx rename to app/[locale]/[id]/_components/RegistryEntry.tsx index 48777d6..9a43c34 100644 --- a/components/RegistryEntry.tsx +++ b/app/[locale]/[id]/_components/RegistryEntry.tsx @@ -8,6 +8,7 @@ import { useForm } from "react-hook-form"; import { z } from "zod"; import { PlusSvg } from "@/assets"; +import { SuccessAnimation } from "@/components/animations/SuccessAnimation"; import { Button, ButtonLoading } from "@/components/ui/button"; import { Drawer, @@ -19,10 +20,6 @@ import { DrawerTitle, DrawerTrigger, } from "@/components/ui/drawer"; -import { transformTimeStringToSeconds } from "@/utils/helperFunctions"; -import useSupabaseBrowser from "@/utils/supabase/client"; - -import { SuccessAnimation } from "./animations/SuccessAnimation"; import { Form, FormControl, @@ -30,10 +27,14 @@ import { FormField, FormItem, FormLabel, -} from "./ui/form"; -import { Input } from "./ui/Input"; -import NumberPicker from "./ui/NumberPicker"; -import { TextArea } from "./ui/TextArea"; +} from "@/components/ui/form"; +import { Input } from "@/components/ui/Input"; +import NumberPicker from "@/components/ui/NumberPicker"; +import { TextArea } from "@/components/ui/TextArea"; +import { transformTimeStringToSeconds } from "@/utils/helperFunctions"; +import useSupabaseBrowser from "@/utils/supabase/client"; + +import MultiSelectFormField from "./witness-select"; const formSchema = z.object({ instagram: z @@ -59,11 +60,9 @@ const formSchema = z.object({ "Inválido, use o formato mm:ss" ), witness: z - .string() - .refine( - (w) => /^(?=.*@[^,\s]+,.*@[^,\s]+).*$/.test(w), - "Inválido, coloque o instagram de duas pessoas, separado por vírgula." - ), + .array(z.string().min(1)) + .min(1) + .nonempty("Please select at least two witness."), comment: z.string(), }); @@ -90,7 +89,7 @@ export const RegistryEntry = ({ highlineId, highlineDistance }: Props) => { full_lines: 0, distance: 0, time: "", - witness: "", + witness: [], comment: "", }, }); @@ -104,32 +103,30 @@ export const RegistryEntry = ({ highlineId, highlineDistance }: Props) => { if (totalDistance) entryForm.setValue("distance", totalDistance); }, [watchCadenas, watchFullLines, highlineDistance, entryForm]); - const createRecord = async (formData: FormSchema) => { - const response = await supabase.from("entry").insert([ - { - highline_id: highlineId, - instagram: formData.instagram.toLowerCase(), - cadenas: formData.cadenas, - full_lines: formData.full_lines, - distance_walked: formData.distance, - crossing_time: formData.time - ? transformTimeStringToSeconds(formData.time) - : null, - comment: formData.comment, - witness: formData.witness?.replace(" ", "").split(","), - is_highliner: true, // TODO: Remove this field from database - }, - ]); - - if (response.error) { - throw new Error(response.error.message); - } + const formMutation = useMutation({ + mutationFn: async (formData: FormSchema) => { + const response = await supabase.from("entry").insert([ + { + highline_id: highlineId, + instagram: formData.instagram.toLowerCase(), + cadenas: formData.cadenas, + full_lines: formData.full_lines, + distance_walked: formData.distance, + crossing_time: formData.time + ? transformTimeStringToSeconds(formData.time) + : null, + comment: formData.comment, + witness: formData.witness, + is_highliner: true, // TODO: Remove this field from database + }, + ]); - return response.data; - }; + if (response.error) { + throw new Error(response.error.message); + } - const formMutation = useMutation({ - mutationFn: createRecord, + return response.data; + }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["entry"] }); }, @@ -157,7 +154,7 @@ export const RegistryEntry = ({ highlineId, highlineDistance }: Props) => { - + true && e.preventDefault()}>
{formMutation.isSuccess ? ( <> @@ -301,9 +298,11 @@ export const RegistryEntry = ({ highlineId, highlineDistance }: Props) => {
- diff --git a/app/[locale]/[id]/_components/witness-select.tsx b/app/[locale]/[id]/_components/witness-select.tsx new file mode 100644 index 0000000..ed6283a --- /dev/null +++ b/app/[locale]/[id]/_components/witness-select.tsx @@ -0,0 +1,401 @@ +import { useQuery } from "@tanstack/react-query"; +import { cva, type VariantProps } from "class-variance-authority"; +import { BadgeCheckIcon, CheckIcon, ChevronDown, XIcon } from "lucide-react"; +import Image from "next/image"; +import * as React from "react"; + +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandLoading, + CommandSeparator, +} from "@/components/ui/command"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { Separator } from "@/components/ui/separator"; +import { cn } from "@/lib/utils"; +import useSupabaseBrowser from "@/utils/supabase/client"; + +import { Skeleton } from "../../../../components/ui/skeleton"; + +const multiSelectVariants = cva( + "gap-2 m-1 transition ease-in-out delay-150 hover:-translate-y-1 hover:scale-110 duration-300", + { + variants: { + variant: { + default: + "border-foreground/10 drop-shadow-md text-foreground bg-card hover:bg-card/80", + secondary: + "border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + inverted: "inverted", + }, + }, + defaultVariants: { + variant: "default", + }, + } +); + +interface MultiSelectFormFieldProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; + defaultValue?: string[]; + disabled?: boolean; + placeholder: string; + className?: string; + onValueChange: (value: string[]) => void; +} + +const MultiSelectFormField = React.forwardRef< + HTMLButtonElement, + MultiSelectFormFieldProps +>( + ( + { + className, + variant, + asChild = false, + defaultValue, + onValueChange, + disabled, + placeholder, + ...props + }, + ref + ) => { + const supabase = useSupabaseBrowser(); + + const [search, setSearch] = React.useState(""); + const normalizedSearch = React.useMemo( + () => (!search || search.startsWith("@") ? search : `@${search}`), + [search] + ); + const [debouncedInputValue, setDebouncedInputValue] = React.useState(""); + + const { + data, + refetch: refetchProfile, + isPending, + } = useQuery({ + queryKey: ["profiles", { username: debouncedInputValue }], + queryFn: async () => { + const query = supabase.from("profiles").select("*"); + + if (debouncedInputValue) { + query.ilike("username", `%${debouncedInputValue}%`); + } else { + query.limit(5); + } + const response = await query; + return response.data; + }, + }); + + const [selectedOption, setSelectedOption] = React.useState< + { username: string; verified: boolean }[] + >([]); + const [isPopoverOpen, setIsPopoverOpen] = React.useState(false); + + // use debounce + React.useEffect(() => { + const timeoutId = setTimeout(() => { + setDebouncedInputValue(search); + }, 750); + return () => clearTimeout(timeoutId); + }, [search]); + + React.useEffect(() => { + refetchProfile(); + }, [debouncedInputValue, refetchProfile]); + + const handleInputKeyDown = (event: any) => { + if (event.key === "Enter") { + setIsPopoverOpen(true); + } else if (event.key === "Backspace" && !event.target.value) { + setSelectedOption((prev) => prev.slice(0, prev.length - 1)); + } + }; + + const toggleOption = (option: { username: string; verified: boolean }) => { + const idx = selectedOption.findIndex( + (value) => value.username === option.username + ); + if (idx === -1) { + setSearch(""); + setSelectedOption((prev) => [...prev, option]); + } else { + setSelectedOption((prev) => + prev.filter((v) => v.username !== option.username) + ); + } + }; + + React.useEffect(() => { + onValueChange(selectedOption.map((value) => value.username)); + }, [selectedOption, onValueChange]); + + return ( + + + + + { + e.stopPropagation(); + setIsPopoverOpen(false); + }} + onInteractOutside={(event) => { + if (!event.defaultPrevented) { + setIsPopoverOpen(false); + } + }} + portal={false} + > + + + + {/* {isPending ? Loading : null} */} + No results found. + {search.length > 0 || + selectedOption.find((value) => value.verified === false) ? ( + + {normalizedSearch && + !data?.find((dt) => dt.username === normalizedSearch) ? ( + + toggleOption({ + username: normalizedSearch, + verified: false, + }) + } + style={{ + pointerEvents: "auto", + }} + disabled={ + selectedOption.length === 2 && + selectedOption.findIndex( + (value) => value.username === normalizedSearch + ) === -1 + } + className="my-1 cursor-pointer aria-disabled:cursor-not-allowed aria-disabled:bg-muted aria-disabled:opacity-60" + > +
value.username === normalizedSearch + ) !== -1 + ? "bg-primary text-primary-foreground" + : "opacity-50 [&_svg]:invisible" + )} + > + +
+ {normalizedSearch} +
+ ) : ( + false + )} + {selectedOption.map((value) => { + if ( + value.verified === true || + value.username === normalizedSearch + ) + return null; + return ( + toggleOption(value)} + style={{ + pointerEvents: "auto", + }} + className="my-1 cursor-pointer aria-disabled:cursor-not-allowed aria-disabled:bg-muted aria-disabled:opacity-60" + > +
+ +
+ {value.username} +
+ ); + })} +
+ ) : null} + {data && data.length > 0 ? ( + + {data?.map((dt) => { + if (!dt.username) return null; + const username = dt.username; + const isSelected = selectedOption.find( + (value) => value.username === username + ); + return ( + + toggleOption({ username, verified: true }) + } + style={{ + pointerEvents: "auto", + }} + disabled={selectedOption.length === 2 && !isSelected} + className="my-1 cursor-pointer aria-disabled:cursor-not-allowed aria-disabled:bg-muted aria-disabled:opacity-60" + > +
+ +
+ {dt.profile_picture && ( + {`${username} + )} +
+ + {dt.name} + + + {username} + +
+ +
+ ); + })} +
+ ) : null} + {isPending && ( + + + + + + )} + + +
+ {selectedOption.length > 0 && ( + <> + { + setSelectedOption([]); + }} + style={{ + pointerEvents: "auto", + opacity: 1, + }} + className="flex-1 cursor-pointer justify-center" + > + Clear + + + + )} + + setIsPopoverOpen(false)} + style={{ + pointerEvents: "auto", + opacity: 1, + }} + className="flex-1 cursor-pointer justify-center" + > + Close + +
+
+
+
+
+
+ ); + } +); + +MultiSelectFormField.displayName = "MultiSelectFormField"; + +export default MultiSelectFormField; diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx new file mode 100644 index 0000000..83e7296 --- /dev/null +++ b/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import { cva, type VariantProps } from "class-variance-authority"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const badgeVariants = cva( + "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +); + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ); +} + +export { Badge, badgeVariants }; diff --git a/components/ui/command.tsx b/components/ui/command.tsx new file mode 100644 index 0000000..166977b --- /dev/null +++ b/components/ui/command.tsx @@ -0,0 +1,158 @@ +"use client"; + +import { type DialogProps } from "@radix-ui/react-dialog"; +import { MagnifyingGlassIcon } from "@radix-ui/react-icons"; +import { Command as CommandPrimitive } from "cmdk"; +import * as React from "react"; + +import { Dialog, DialogContent } from "@/components/ui/dialog"; +import { cn } from "@/lib/utils"; + +const Command = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +Command.displayName = CommandPrimitive.displayName; + +interface CommandDialogProps extends DialogProps {} + +const CommandDialog = ({ children, ...props }: CommandDialogProps) => { + return ( + + + + {children} + + + + ); +}; + +const CommandInput = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ + +
+)); + +CommandInput.displayName = CommandPrimitive.Input.displayName; + +const CommandList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); + +CommandList.displayName = CommandPrimitive.List.displayName; + +const CommandEmpty = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>((props, ref) => ( + +)); + +CommandEmpty.displayName = CommandPrimitive.Empty.displayName; + +const CommandGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); + +CommandGroup.displayName = CommandPrimitive.Group.displayName; + +const CommandSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +CommandSeparator.displayName = CommandPrimitive.Separator.displayName; + +const CommandItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); + +CommandItem.displayName = CommandPrimitive.Item.displayName; + +const CommandShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ); +}; +CommandShortcut.displayName = "CommandShortcut"; + +const CommandLoading = CommandPrimitive.Loading; + +export { + Command, + CommandDialog, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandLoading, + CommandSeparator, + CommandShortcut, +}; diff --git a/components/ui/popover.tsx b/components/ui/popover.tsx index db16704..8f5573d 100644 --- a/components/ui/popover.tsx +++ b/components/ui/popover.tsx @@ -11,23 +11,39 @@ const PopoverTrigger = PopoverPrimitive.Trigger; const PopoverAnchor = PopoverPrimitive.Anchor; +interface PopoverContentProps + extends React.ComponentPropsWithoutRef { + portal?: boolean; +} + const PopoverContent = React.forwardRef< React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( - - - -)); + PopoverContentProps +>( + ( + { className, align = "center", sideOffset = 4, portal = true, ...props }, + ref + ) => { + const content = ( + + ); + + return portal ? ( + {content} + ) : ( + content + ); + } +); PopoverContent.displayName = PopoverPrimitive.Content.displayName; export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger }; diff --git a/components/ui/separator.tsx b/components/ui/separator.tsx new file mode 100644 index 0000000..8f88cc9 --- /dev/null +++ b/components/ui/separator.tsx @@ -0,0 +1,31 @@ +"use client"; + +import * as SeparatorPrimitive from "@radix-ui/react-separator"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + + ) +); +Separator.displayName = SeparatorPrimitive.Root.displayName; + +export { Separator }; diff --git a/components/ui/skeleton.tsx b/components/ui/skeleton.tsx new file mode 100644 index 0000000..d7e45f7 --- /dev/null +++ b/components/ui/skeleton.tsx @@ -0,0 +1,15 @@ +import { cn } from "@/lib/utils" + +function Skeleton({ + className, + ...props +}: React.HTMLAttributes) { + return ( +
+ ) +} + +export { Skeleton } diff --git a/package.json b/package.json index 64a50eb..1814150 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", @@ -31,6 +32,7 @@ "autoprefixer": "10.4.14", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", + "cmdk": "^1.0.0", "cookies-next": "^4.1.0", "date-fns": "^3.6.0", "embla-carousel-react": "^8.0.0", diff --git a/yarn.lock b/yarn.lock index 4a3ecb0..2af2745 100644 --- a/yarn.lock +++ b/yarn.lock @@ -403,20 +403,20 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-dialog@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.4.tgz#06bce6c16bb93eb36d7a8589e665a20f4c1c52c1" - integrity sha512-hJtRy/jPULGQZceSAP2Re6/4NpKo8im6V8P2hUqZsdFiSL8l35kYsw3qbRI6Ay5mQd2+wlLqje770eq+RJ3yZg== +"@radix-ui/react-dialog@1.0.5", "@radix-ui/react-dialog@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300" + integrity sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q== dependencies: "@babel/runtime" "^7.13.10" "@radix-ui/primitive" "1.0.1" "@radix-ui/react-compose-refs" "1.0.1" "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-dismissable-layer" "1.0.4" + "@radix-ui/react-dismissable-layer" "1.0.5" "@radix-ui/react-focus-guards" "1.0.1" - "@radix-ui/react-focus-scope" "1.0.3" + "@radix-ui/react-focus-scope" "1.0.4" "@radix-ui/react-id" "1.0.1" - "@radix-ui/react-portal" "1.0.3" + "@radix-ui/react-portal" "1.0.4" "@radix-ui/react-presence" "1.0.1" "@radix-ui/react-primitive" "1.0.3" "@radix-ui/react-slot" "1.0.2" @@ -424,20 +424,20 @@ aria-hidden "^1.1.1" react-remove-scroll "2.5.5" -"@radix-ui/react-dialog@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300" - integrity sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q== +"@radix-ui/react-dialog@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.4.tgz#06bce6c16bb93eb36d7a8589e665a20f4c1c52c1" + integrity sha512-hJtRy/jPULGQZceSAP2Re6/4NpKo8im6V8P2hUqZsdFiSL8l35kYsw3qbRI6Ay5mQd2+wlLqje770eq+RJ3yZg== dependencies: "@babel/runtime" "^7.13.10" "@radix-ui/primitive" "1.0.1" "@radix-ui/react-compose-refs" "1.0.1" "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-dismissable-layer" "1.0.5" + "@radix-ui/react-dismissable-layer" "1.0.4" "@radix-ui/react-focus-guards" "1.0.1" - "@radix-ui/react-focus-scope" "1.0.4" + "@radix-ui/react-focus-scope" "1.0.3" "@radix-ui/react-id" "1.0.1" - "@radix-ui/react-portal" "1.0.4" + "@radix-ui/react-portal" "1.0.3" "@radix-ui/react-presence" "1.0.1" "@radix-ui/react-primitive" "1.0.3" "@radix-ui/react-slot" "1.0.2" @@ -679,6 +679,14 @@ aria-hidden "^1.1.1" react-remove-scroll "2.5.5" +"@radix-ui/react-separator@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.0.3.tgz#be5a931a543d5726336b112f465f58585c04c8aa" + integrity sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot@1.0.2", "@radix-ui/react-slot@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" @@ -1720,6 +1728,14 @@ cmd-shim@^6.0.0: resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.1.tgz#a65878080548e1dca760b3aea1e21ed05194da9d" integrity sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q== +cmdk@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cmdk/-/cmdk-1.0.0.tgz#0a095fdafca3dfabed82d1db78a6262fb163ded9" + integrity sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q== + dependencies: + "@radix-ui/react-dialog" "1.0.5" + "@radix-ui/react-primitive" "1.0.3" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" From f89aa783dd9fcdc232070decbac894e19df425a1 Mon Sep 17 00:00:00 2001 From: Juan Andrade Date: Sun, 5 May 2024 01:41:50 -0300 Subject: [PATCH 02/10] Updated input component --- .../[id]/_components/RegistryEntry.tsx | 2 +- app/[locale]/_components/UsernameDialog.tsx | 2 +- app/[locale]/_components/search.tsx | 2 +- components/CreateHighline.tsx | 2 +- components/layout/navbar/SignUp.tsx | 2 +- components/layout/navbar/UpdateProfile.tsx | 2 +- components/ui/Input.tsx | 27 ------------------- components/ui/dialog.tsx | 2 +- components/ui/input.tsx | 25 +++++++++++++++++ 9 files changed, 32 insertions(+), 34 deletions(-) delete mode 100644 components/ui/Input.tsx create mode 100644 components/ui/input.tsx diff --git a/app/[locale]/[id]/_components/RegistryEntry.tsx b/app/[locale]/[id]/_components/RegistryEntry.tsx index 9a43c34..a8deeab 100644 --- a/app/[locale]/[id]/_components/RegistryEntry.tsx +++ b/app/[locale]/[id]/_components/RegistryEntry.tsx @@ -28,7 +28,7 @@ import { FormItem, FormLabel, } from "@/components/ui/form"; -import { Input } from "@/components/ui/Input"; +import { Input } from "@/components/ui/input"; import NumberPicker from "@/components/ui/NumberPicker"; import { TextArea } from "@/components/ui/TextArea"; import { transformTimeStringToSeconds } from "@/utils/helperFunctions"; diff --git a/app/[locale]/_components/UsernameDialog.tsx b/app/[locale]/_components/UsernameDialog.tsx index 764493e..7252e41 100644 --- a/app/[locale]/_components/UsernameDialog.tsx +++ b/app/[locale]/_components/UsernameDialog.tsx @@ -26,7 +26,7 @@ import { FormLabel, FormMessage, } from "@/components/ui/form"; -import { Input } from "@/components/ui/Input"; +import { Input } from "@/components/ui/input"; import { useRouter } from "@/navigation"; import useSupabaseBrowser from "@/utils/supabase/client"; diff --git a/app/[locale]/_components/search.tsx b/app/[locale]/_components/search.tsx index bfd2d37..7a0dffa 100644 --- a/app/[locale]/_components/search.tsx +++ b/app/[locale]/_components/search.tsx @@ -3,7 +3,7 @@ import { SearchIcon } from "lucide-react"; import { useTranslations } from "next-intl"; -import { Input } from "@/components/ui/Input"; +import { Input } from "@/components/ui/input"; import { useQueryString } from "@/hooks/useQueryString"; export default function Search() { diff --git a/components/CreateHighline.tsx b/components/CreateHighline.tsx index 2d98ee9..e97ebfc 100644 --- a/components/CreateHighline.tsx +++ b/components/CreateHighline.tsx @@ -38,7 +38,7 @@ import { import { SuccessAnimation } from "./animations/SuccessAnimation"; import Dropzone from "./ui/Dropzone"; import { Form, FormControl, FormField, FormItem, FormLabel } from "./ui/form"; -import { Input } from "./ui/Input"; +import { Input } from "./ui/input"; import { TextArea } from "./ui/TextArea"; const formSchema = z.object({ diff --git a/components/layout/navbar/SignUp.tsx b/components/layout/navbar/SignUp.tsx index 9d4af64..687e588 100644 --- a/components/layout/navbar/SignUp.tsx +++ b/components/layout/navbar/SignUp.tsx @@ -24,7 +24,7 @@ import { FormItem, FormMessage, } from "@/components/ui/form"; -import { Input } from "@/components/ui/Input"; +import { Input } from "@/components/ui/input"; import useSupabaseBrowser from "@/utils/supabase/client"; import { useLoginModal } from "@/utils/useLoginModal"; diff --git a/components/layout/navbar/UpdateProfile.tsx b/components/layout/navbar/UpdateProfile.tsx index e3173e0..f1eb104 100644 --- a/components/layout/navbar/UpdateProfile.tsx +++ b/components/layout/navbar/UpdateProfile.tsx @@ -29,7 +29,7 @@ import { FormLabel, FormMessage, } from "@/components/ui/form"; -import { Input } from "@/components/ui/Input"; +import { Input } from "@/components/ui/input"; import { Popover, PopoverContent, diff --git a/components/ui/Input.tsx b/components/ui/Input.tsx deleted file mode 100644 index ece5a4e..0000000 --- a/components/ui/Input.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import * as React from "react"; - -import { cn } from "@/lib/utils"; - -export interface InputProps - extends React.InputHTMLAttributes { - className?: string; -} - -const Input = React.forwardRef( - ({ className, type, ...props }, ref) => { - return ( - - ); - } -); -Input.displayName = "Input"; - -export { Input }; diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx index e21b56a..4d94146 100644 --- a/components/ui/dialog.tsx +++ b/components/ui/dialog.tsx @@ -73,7 +73,7 @@ const DialogFooter = ({ }: React.HTMLAttributes) => (
{} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } From b371e1f5b14181a8821462fe476f43af67bdd53e Mon Sep 17 00:00:00 2001 From: Juan Andrade Date: Sun, 5 May 2024 01:44:51 -0300 Subject: [PATCH 03/10] Updated textarea component --- .../[id]/_components/RegistryEntry.tsx | 4 +-- components/CreateHighline.tsx | 4 +-- components/layout/navbar/UpdateProfile.tsx | 4 +-- components/ui/TextArea.tsx | 25 ------------------- components/ui/textarea.tsx | 24 ++++++++++++++++++ 5 files changed, 30 insertions(+), 31 deletions(-) delete mode 100644 components/ui/TextArea.tsx create mode 100644 components/ui/textarea.tsx diff --git a/app/[locale]/[id]/_components/RegistryEntry.tsx b/app/[locale]/[id]/_components/RegistryEntry.tsx index a8deeab..de5fafb 100644 --- a/app/[locale]/[id]/_components/RegistryEntry.tsx +++ b/app/[locale]/[id]/_components/RegistryEntry.tsx @@ -30,7 +30,7 @@ import { } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import NumberPicker from "@/components/ui/NumberPicker"; -import { TextArea } from "@/components/ui/TextArea"; +import { Textarea } from "@/components/ui/textarea"; import { transformTimeStringToSeconds } from "@/utils/helperFunctions"; import useSupabaseBrowser from "@/utils/supabase/client"; @@ -315,7 +315,7 @@ export const RegistryEntry = ({ highlineId, highlineDistance }: Props) => { {t("comment.label")} -