diff --git a/app/(dashboard)/add-job/page.tsx b/app/(dashboard)/add-job/page.tsx index 5e90522..d53f44c 100644 --- a/app/(dashboard)/add-job/page.tsx +++ b/app/(dashboard)/add-job/page.tsx @@ -1,4 +1,4 @@ -import CreateJobForm from '@/components/ui/CreateJobForm' +import { CreateJobForm } from '../../../components/ui/CreateJobForm' const AddJobPage = () => { return ( diff --git a/app/(dashboard)/jobs/page.tsx b/app/(dashboard)/jobs/page.tsx index bec4085..4e6c8bd 100644 --- a/app/(dashboard)/jobs/page.tsx +++ b/app/(dashboard)/jobs/page.tsx @@ -1,4 +1,4 @@ -import Spinner from '@/components/ui/Spinner' +import { Spinner } from '../../../components/ui/Spinner' const JobPage = () => { return ( diff --git a/app/(dashboard)/layout.tsx b/app/(dashboard)/layout.tsx index 0ad57bf..7d4841d 100644 --- a/app/(dashboard)/layout.tsx +++ b/app/(dashboard)/layout.tsx @@ -1,5 +1,5 @@ -import Navbar from '../../components/ui/Navbar' -import Sidebar from '../../components/ui/Sidebar' +import { Navbar } from '../../components/ui/Navbar' +import { Sidebar } from '../../components/ui/Sidebar' import { PropsWithChildren } from 'react' @@ -10,12 +10,12 @@ const layout = ({ children }: PropsWithChildren) => {
+ {/* second-col hide dropdown on big screen */}
{children}
- {children} ) } diff --git a/app/(dashboard)/stats/page.tsx b/app/(dashboard)/stats/page.tsx index f872a20..49a2348 100644 --- a/app/(dashboard)/stats/page.tsx +++ b/app/(dashboard)/stats/page.tsx @@ -1,4 +1,4 @@ -import Spinner from '@/components/ui/Spinner' +import { Spinner } from '../../../components/ui/Spinner' const StatsPage = () => { return ( diff --git a/app/layout.tsx b/app/layout.tsx index ffb5329..fbdcb0c 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,7 +2,7 @@ import type { Metadata } from 'next' import { Geist, Geist_Mono } from 'next/font/google' import './globals.css' import { ClerkProvider } from '@clerk/nextjs' -import Providers from './providers' +import { Providers } from './providers' const geistSans = Geist({ variable: '--font-geist-sans', diff --git a/app/page.tsx b/app/page.tsx index cefb7b4..ab1273d 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,7 +1,7 @@ import Image from 'next/image' import LandingImg from '../assets/main-illustration.png' import Logo from '../assets/logo.svg' -import { Button } from '@/components/ui/button' +import { Button } from '@/components/ui/Button/Button' import Link from 'next/link' export default function Home() { diff --git a/app/providers.tsx b/app/providers.tsx index cb9a4f1..691fdcc 100644 --- a/app/providers.tsx +++ b/app/providers.tsx @@ -1,6 +1,6 @@ 'use client' -import ThemeProvider from '@/components/ui/ThemeProvider' +import { ThemeProvider } from '@/components/ui/ThemeProvider' const Providers = ({ children }: { children: React.ReactNode }) => { return ( @@ -17,4 +17,4 @@ const Providers = ({ children }: { children: React.ReactNode }) => { ) } -export default Providers +export { Providers } diff --git a/components/ui/button.tsx b/components/ui/Button/Button.tsx similarity index 100% rename from components/ui/button.tsx rename to components/ui/Button/Button.tsx diff --git a/components/ui/Button/index.tsx b/components/ui/Button/index.tsx new file mode 100644 index 0000000..6d1d7f8 --- /dev/null +++ b/components/ui/Button/index.tsx @@ -0,0 +1 @@ +export { Button, buttonVariants } from './Button' diff --git a/components/ui/CreateJobForm/CreateJobForm.tsx b/components/ui/CreateJobForm/CreateJobForm.tsx index 342ffd4..089e43f 100644 --- a/components/ui/CreateJobForm/CreateJobForm.tsx +++ b/components/ui/CreateJobForm/CreateJobForm.tsx @@ -2,61 +2,69 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useForm } from 'react-hook-form' -import * as z from 'zod' -import { Button } from '@/components/ui/button' import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@/components/ui/form' -import { Input } from '@/components/ui/input' - -const formSchema = z.object({ - username: z.string().min(2, { - message: 'Username must be at least 2 characters.', - }), -}) + JobStatus, + JobMode, + createAndEditJobSchema, + CreateAndEditJobType, +} from '@/utils/types' + +import { Button } from '../Button' +import { Form } from '../Form' + +import { CustomFormField, CustomFormSelect } from '../FormComponents' const CreateJobForm = () => { // 1. Define your form. - const form = useForm>({ - resolver: zodResolver(formSchema), + const form = useForm({ + resolver: zodResolver(createAndEditJobSchema), defaultValues: { - username: '', + position: '', + company: '', + location: '', + status: JobStatus.Pending, + mode: JobMode.FullTime, }, }) - // 2. Define a submit handler. - function onSubmit(values: z.infer) { - // Do something with the form values. - // ✅ This will be type-safe and validated. - console.log(values) + const onSubmit = (value: CreateAndEditJobType) => { + console.log(value) } return (
- - ( - - Username - - - - - - )} - /> - + +

add job

+
+ {/* position */} + + {/* company */} + + {/* location */} + + + {/* job status */} + + {/* job mode */} + + +
) } -export default CreateJobForm +export { CreateJobForm } diff --git a/components/ui/CreateJobForm/index.tsx b/components/ui/CreateJobForm/index.tsx index 99a7da2..393c07d 100644 --- a/components/ui/CreateJobForm/index.tsx +++ b/components/ui/CreateJobForm/index.tsx @@ -1 +1 @@ -export { default } from './CreateJobForm' +export { CreateJobForm } from './CreateJobForm' diff --git a/components/ui/dropdown-menu.tsx b/components/ui/DropDownMenu.tsx/DropDownMenu.tsx similarity index 100% rename from components/ui/dropdown-menu.tsx rename to components/ui/DropDownMenu.tsx/DropDownMenu.tsx diff --git a/components/ui/DropDownMenu.tsx/index.tsx b/components/ui/DropDownMenu.tsx/index.tsx new file mode 100644 index 0000000..74fb39d --- /dev/null +++ b/components/ui/DropDownMenu.tsx/index.tsx @@ -0,0 +1,17 @@ +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} from './DropDownMenu' diff --git a/components/ui/form.tsx b/components/ui/Form/Form.tsx similarity index 81% rename from components/ui/form.tsx rename to components/ui/Form/Form.tsx index ce264ae..26fa236 100644 --- a/components/ui/form.tsx +++ b/components/ui/Form/Form.tsx @@ -1,8 +1,8 @@ -"use client" +'use client' -import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { Slot } from "@radix-ui/react-slot" +import * as React from 'react' +import * as LabelPrimitive from '@radix-ui/react-label' +import { Slot } from '@radix-ui/react-slot' import { Controller, ControllerProps, @@ -10,10 +10,10 @@ import { FieldValues, FormProvider, useFormContext, -} from "react-hook-form" +} from 'react-hook-form' -import { cn } from "@/lib/utils" -import { Label } from "@/components/ui/label" +import { cn } from '@/lib/utils' +import { Label } from '../Label' const Form = FormProvider @@ -49,7 +49,7 @@ const useFormField = () => { const fieldState = getFieldState(fieldContext.name, formState) if (!fieldContext) { - throw new Error("useFormField should be used within ") + throw new Error('useFormField should be used within ') } const { id } = itemContext @@ -80,11 +80,11 @@ const FormItem = React.forwardRef< return ( -
+
) }) -FormItem.displayName = "FormItem" +FormItem.displayName = 'FormItem' const FormLabel = React.forwardRef< React.ElementRef, @@ -95,13 +95,13 @@ const FormLabel = React.forwardRef< return (
- +
) } -export default Navbar +export { Navbar } diff --git a/components/ui/Navbar/index.tsx b/components/ui/Navbar/index.tsx index e6400ae..7d0bade 100644 --- a/components/ui/Navbar/index.tsx +++ b/components/ui/Navbar/index.tsx @@ -1 +1 @@ -export { default } from './Navbar' +export { Navbar } from './Navbar' diff --git a/components/ui/Select/Select.tsx b/components/ui/Select/Select.tsx new file mode 100644 index 0000000..cbe5a36 --- /dev/null +++ b/components/ui/Select/Select.tsx @@ -0,0 +1,160 @@ +"use client" + +import * as React from "react" +import * as SelectPrimitive from "@radix-ui/react-select" +import { Check, ChevronDown, ChevronUp } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Select = SelectPrimitive.Root + +const SelectGroup = SelectPrimitive.Group + +const SelectValue = SelectPrimitive.Value + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className + )} + {...props} + > + {children} + + + + +)) +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)) +SelectContent.displayName = SelectPrimitive.Content.displayName + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectLabel.displayName = SelectPrimitive.Label.displayName + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + + {children} + +)) +SelectItem.displayName = SelectPrimitive.Item.displayName + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectSeparator.displayName = SelectPrimitive.Separator.displayName + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +} diff --git a/components/ui/Select/index.tsx b/components/ui/Select/index.tsx new file mode 100644 index 0000000..5b2c8d6 --- /dev/null +++ b/components/ui/Select/index.tsx @@ -0,0 +1,12 @@ +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +} from './Select' diff --git a/components/ui/Sidebar/Sidebar.tsx b/components/ui/Sidebar/Sidebar.tsx index 8d8fdeb..d179f2e 100644 --- a/components/ui/Sidebar/Sidebar.tsx +++ b/components/ui/Sidebar/Sidebar.tsx @@ -3,7 +3,7 @@ import Logo from '../../../assets/logo.svg' import links from '@/utils/links' import Image from 'next/image' import Link from 'next/link' -import { Button } from '../button' +import { Button } from '../Button/Button' import { usePathname } from 'next/navigation' const Sidebar = () => { @@ -30,4 +30,4 @@ const Sidebar = () => { ) } -export default Sidebar +export { Sidebar } diff --git a/components/ui/Sidebar/index.tsx b/components/ui/Sidebar/index.tsx index 877187c..70fb43e 100644 --- a/components/ui/Sidebar/index.tsx +++ b/components/ui/Sidebar/index.tsx @@ -1 +1 @@ -export { default } from './Sidebar' +export { Sidebar } from './Sidebar' diff --git a/components/ui/Spinner/Spinner.tsx b/components/ui/Spinner/Spinner.tsx index 26a4ee7..729e8b8 100644 --- a/components/ui/Spinner/Spinner.tsx +++ b/components/ui/Spinner/Spinner.tsx @@ -11,4 +11,4 @@ const Spinner = () => { ) } -export default Spinner +export { Spinner } diff --git a/components/ui/Spinner/index.tsx b/components/ui/Spinner/index.tsx index 0be0188..fbf16c1 100644 --- a/components/ui/Spinner/index.tsx +++ b/components/ui/Spinner/index.tsx @@ -1 +1 @@ -export { default } from './Spinner' +export { Spinner } from './Spinner' diff --git a/components/ui/ThemeProvider/ThemeProvider.tsx b/components/ui/ThemeProvider/ThemeProvider.tsx index e4b1bab..51e0288 100644 --- a/components/ui/ThemeProvider/ThemeProvider.tsx +++ b/components/ui/ThemeProvider/ThemeProvider.tsx @@ -7,4 +7,4 @@ const ThemeProvider = ({ children, ...props }: ThemeProviderProps) => { return {children} } -export default ThemeProvider +export { ThemeProvider } diff --git a/components/ui/ThemeProvider/index.tsx b/components/ui/ThemeProvider/index.tsx index 274fd0d..a06d025 100644 --- a/components/ui/ThemeProvider/index.tsx +++ b/components/ui/ThemeProvider/index.tsx @@ -1 +1 @@ -export { default } from './ThemeProvider' +export { ThemeProvider } from './ThemeProvider' diff --git a/components/ui/ThemeToggle/ThemeToggle.tsx b/components/ui/ThemeToggle/ThemeToggle.tsx index 576086d..f7b0e84 100644 --- a/components/ui/ThemeToggle/ThemeToggle.tsx +++ b/components/ui/ThemeToggle/ThemeToggle.tsx @@ -4,13 +4,13 @@ import * as React from 'react' import { Moon, Sun } from 'lucide-react' import { useTheme } from 'next-themes' -import { Button } from '@/components/ui/button' +import { Button } from '@/components/ui/Button/Button' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, -} from '@/components/ui/dropdown-menu' +} from '@/components/ui/DropDownMenu.tsx' const ModeToggle = () => { const { setTheme } = useTheme() @@ -39,4 +39,4 @@ const ModeToggle = () => { ) } -export default ModeToggle +export { ModeToggle } diff --git a/components/ui/ThemeToggle/index.tsx b/components/ui/ThemeToggle/index.tsx index ab0c814..1dc9e34 100644 --- a/components/ui/ThemeToggle/index.tsx +++ b/components/ui/ThemeToggle/index.tsx @@ -1 +1 @@ -export { default } from './ThemeToggle' +export { ModeToggle } from './ThemeToggle' diff --git a/package-lock.json b/package-lock.json index 6a40fc4..79457d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@hookform/resolvers": "^3.9.1", "@radix-ui/react-dropdown-menu": "^2.1.4", "@radix-ui/react-label": "^2.1.1", + "@radix-ui/react-select": "^2.1.4", "@radix-ui/react-slot": "^1.1.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -1149,6 +1150,12 @@ "@prisma/debug": "5.22.0" } }, + "node_modules/@radix-ui/number": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", + "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==", + "license": "MIT" + }, "node_modules/@radix-ui/primitive": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", @@ -1560,6 +1567,49 @@ } } }, + "node_modules/@radix-ui/react-select": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.4.tgz", + "integrity": "sha512-pOkb2u8KgO47j/h7AylCj7dJsm69BXcjkrvTqMptFqsE2i0p8lHkfgneXKjAgPzBMivnoMyt8o4KiV4wYzDdyQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collection": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.3", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.1", + "@radix-ui/react-portal": "1.1.3", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-slot": "1.1.1", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-visually-hidden": "1.1.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "^2.6.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", @@ -1644,6 +1694,21 @@ } } }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", + "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-rect": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", @@ -1680,6 +1745,29 @@ } } }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.1.tgz", + "integrity": "sha512-vVfA2IZ9q/J+gEamvj761Oq1FpWgCDaNOOIfbPVp2MVPLEomUr5+Vf7kJGwQ24YxZSlQVar7Bes8kyTo5Dshpg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/rect": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", diff --git a/package.json b/package.json index 40af543..0c446a6 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@hookform/resolvers": "^3.9.1", "@radix-ui/react-dropdown-menu": "^2.1.4", "@radix-ui/react-label": "^2.1.1", + "@radix-ui/react-select": "^2.1.4", "@radix-ui/react-slot": "^1.1.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1",