From 7f7e76dc3f1b02f9a4ccc8f02f06871875513735 Mon Sep 17 00:00:00 2001 From: DaKheera47 Date: Thu, 22 Jan 2026 18:57:11 +0000 Subject: [PATCH 01/14] Initial commit for UI --- docker-compose.yml | 2 - orchestrator/src/client/App.tsx | 2 + orchestrator/src/client/api/client.ts | 12 +- .../src/client/components/OnboardingGate.tsx | 339 ++++++++++++++++++ orchestrator/src/server/api/routes/profile.ts | 39 +- orchestrator/src/server/app.ts | 2 +- orchestrator/src/server/services/settings.ts | 5 +- orchestrator/src/shared/types.ts | 5 + 8 files changed, 400 insertions(+), 6 deletions(-) create mode 100644 orchestrator/src/client/components/OnboardingGate.tsx diff --git a/docker-compose.yml b/docker-compose.yml index d29e177..203c2d1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,8 +16,6 @@ services: - ./data:/app/data # Base resume JSON (read-only) - ./resume-generator/base.json:/app/resume-generator/base.json:ro - env_file: - - .env environment: # Server config - NODE_ENV=production diff --git a/orchestrator/src/client/App.tsx b/orchestrator/src/client/App.tsx index e6ec43b..c5df563 100644 --- a/orchestrator/src/client/App.tsx +++ b/orchestrator/src/client/App.tsx @@ -11,6 +11,7 @@ import { OrchestratorPage } from "./pages/OrchestratorPage"; import { SettingsPage } from "./pages/SettingsPage"; import { UkVisaJobsPage } from "./pages/UkVisaJobsPage"; import { VisaSponsorsPage } from "./pages/VisaSponsorsPage"; +import { OnboardingGate } from "./components/OnboardingGate"; export const App: React.FC = () => { const location = useLocation(); @@ -27,6 +28,7 @@ export const App: React.FC = () => { return ( <> + { return fetchApi('/profile'); } +export async function getProfileStatus(): Promise { + return fetchApi('/profile/status'); +} + +export async function uploadProfile(profile: ResumeProfile): Promise { + return fetchApi('/profile/upload', { + method: 'POST', + body: JSON.stringify({ profile }), + }); +} export async function updateSettings(update: { model?: string | null diff --git a/orchestrator/src/client/components/OnboardingGate.tsx b/orchestrator/src/client/components/OnboardingGate.tsx new file mode 100644 index 0000000..795b3bd --- /dev/null +++ b/orchestrator/src/client/components/OnboardingGate.tsx @@ -0,0 +1,339 @@ +import React, { useCallback, useEffect, useMemo, useRef, useState } from "react" +import { toast } from "sonner" + +import { AlertDialog, AlertDialogContent, AlertDialogDescription, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Separator } from "@/components/ui/separator" +import { cn } from "@/lib/utils" +import * as api from "@client/api" +import { useSettings } from "@client/hooks/useSettings" +import { SettingsInput } from "@client/pages/settings/components/SettingsInput" +import { formatSecretHint } from "@client/pages/settings/utils" +import type { ProfileStatusResponse, ResumeProfile } from "@shared/types" + +type RequirementRowProps = { + label: string + helper?: string + complete: boolean +} + +const RequirementRow: React.FC = ({ label, helper, complete }) => ( +
+
+

{label}

+ {helper &&

{helper}

} +
+ + {complete ? "Ready" : "Next"} + +
+) + +export const OnboardingGate: React.FC = () => { + const { settings, isLoading: settingsLoading, refreshSettings } = useSettings() + const [profileStatus, setProfileStatus] = useState(null) + const [isCheckingProfile, setIsCheckingProfile] = useState(false) + const [isSavingEnv, setIsSavingEnv] = useState(false) + const [isUploadingResume, setIsUploadingResume] = useState(false) + + const [openrouterApiKey, setOpenrouterApiKey] = useState("") + const [rxresumeEmail, setRxresumeEmail] = useState("") + const [rxresumePassword, setRxresumePassword] = useState("") + const [resumeFile, setResumeFile] = useState(null) + const fileInputRef = useRef(null) + + const refreshProfileStatus = useCallback(async () => { + setIsCheckingProfile(true) + try { + const status = await api.getProfileStatus() + setProfileStatus(status) + } catch (error) { + const message = error instanceof Error ? error.message : "Failed to check base resume" + setProfileStatus({ exists: false, error: message }) + } finally { + setIsCheckingProfile(false) + } + }, []) + + useEffect(() => { + void refreshProfileStatus() + }, [refreshProfileStatus]) + + const hasOpenrouterKey = Boolean(settings?.openrouterApiKeyHint) + const hasRxresumeEmail = Boolean(settings?.rxresumeEmail?.trim()) + const hasRxresumePassword = Boolean(settings?.rxresumePasswordHint) + const hasRxresumeCredentials = hasRxresumeEmail && hasRxresumePassword + const hasBaseResume = Boolean(profileStatus?.exists) + + const shouldOpen = Boolean(settings && profileStatus && !settingsLoading && !isCheckingProfile) + && !(hasOpenrouterKey && hasRxresumeCredentials && hasBaseResume) + + const openrouterCurrent = settings?.openrouterApiKeyHint + ? formatSecretHint(settings.openrouterApiKeyHint) + : undefined + const rxresumeEmailCurrent = settings?.rxresumeEmail?.trim() + ? settings.rxresumeEmail + : undefined + const rxresumePasswordCurrent = settings?.rxresumePasswordHint + ? formatSecretHint(settings.rxresumePasswordHint) + : undefined + + const handleRefresh = async () => { + const results = await Promise.allSettled([refreshSettings(), refreshProfileStatus()]) + const failed = results.find((result) => result.status === "rejected") + if (failed) { + const reason = failed.status === "rejected" ? failed.reason : null + const message = reason instanceof Error ? reason.message : "Failed to refresh setup" + toast.error(message) + } + } + + const handleSaveCredentials = async () => { + if (!settings) return + const update: { openrouterApiKey?: string; rxresumeEmail?: string; rxresumePassword?: string } = {} + const openrouterValue = openrouterApiKey.trim() + const emailValue = rxresumeEmail.trim() + const passwordValue = rxresumePassword.trim() + + const missing: string[] = [] + + if (!hasOpenrouterKey && !openrouterValue) { + missing.push("OpenRouter API key") + } + + if (!hasRxresumeCredentials) { + if (!hasRxresumeEmail && !emailValue) missing.push("RxResume email") + if (!hasRxresumePassword && !passwordValue) missing.push("RxResume password") + } + + if (missing.length > 0) { + toast.info("Almost there", { + description: `Missing: ${missing.join(", ")}`, + }) + return + } + + if (openrouterValue) update.openrouterApiKey = openrouterValue + if (emailValue) update.rxresumeEmail = emailValue + if (passwordValue) update.rxresumePassword = passwordValue + + if (Object.keys(update).length === 0) { + toast.info("Nothing new to save") + return + } + + try { + setIsSavingEnv(true) + await api.updateSettings(update) + await refreshSettings() + setOpenrouterApiKey("") + setRxresumePassword("") + toast.success("Credentials saved") + } catch (error) { + const message = error instanceof Error ? error.message : "Failed to save credentials" + toast.error(message) + } finally { + setIsSavingEnv(false) + } + } + + const handleUploadResume = async () => { + if (!resumeFile) { + toast.info("Choose your base.json file") + return + } + + try { + setIsUploadingResume(true) + const text = await resumeFile.text() + let parsed: ResumeProfile + try { + parsed = JSON.parse(text) as ResumeProfile + } catch { + throw new Error("Resume JSON is invalid. Export the base.json from RxResume.") + } + + await api.uploadProfile(parsed) + await refreshProfileStatus() + setResumeFile(null) + if (fileInputRef.current) { + fileInputRef.current.value = "" + } + toast.success("Resume uploaded") + } catch (error) { + const message = error instanceof Error ? error.message : "Failed to upload resume" + toast.error(message) + } finally { + setIsUploadingResume(false) + } + } + + const resumeFileName = resumeFile?.name || "" + + const checklist = useMemo( + () => [ + { + label: "OpenRouter API key", + helper: "Needed for scoring + tailoring", + complete: hasOpenrouterKey, + }, + { + label: "RxResume credentials", + helper: "Used to export PDFs", + complete: hasRxresumeCredentials, + }, + { + label: "Base resume JSON", + helper: "Upload resume-generator/base.json", + complete: hasBaseResume, + }, + ], + [hasBaseResume, hasOpenrouterKey, hasRxresumeCredentials] + ) + + if (!shouldOpen) return null + + return ( + + event.preventDefault()} + onPointerDownOutside={(event) => event.preventDefault()} + onInteractOutside={(event) => event.preventDefault()} + > + + Welcome to Job Ops + + Let’s get your workspace ready. Add your keys and resume once, then the pipeline can run end-to-end. + + + +
+
+
+

Quick setup checklist

+ +
+
+ {checklist.map((item) => ( + + ))} +
+
+ + + +
+
+

OpenRouter

+

Used for job scoring, summaries, and tailoring.

+
+ setOpenrouterApiKey(event.target.value), + }} + type="password" + placeholder="sk-or-v1..." + current={openrouterCurrent} + helper="Create a key at openrouter.ai" + disabled={isSavingEnv} + /> +
+ + + +
+
+

RxResume account

+

Used to export tailored PDFs.

+
+
+ setRxresumeEmail(event.target.value), + }} + placeholder="you@example.com" + current={rxresumeEmailCurrent} + disabled={isSavingEnv} + /> + setRxresumePassword(event.target.value), + }} + type="password" + placeholder="Enter password" + current={rxresumePasswordCurrent} + disabled={isSavingEnv} + /> +
+
+ +
+
+ + + +
+
+

Base resume JSON

+

Upload your RxResume export named base.json.

+
+
+
+ + setResumeFile(event.target.files?.[0] ?? null)} + disabled={isUploadingResume} + /> + {resumeFileName && ( +

Selected: {resumeFileName}

+ )} +
+ +
+
+ +
+ Friendly heads-up: pipelines can be slow or a little flaky in alpha. If anything feels off, open a GitHub issue and + we will take a look.{" "} + + Open an issue + + . +
+
+
+
+ ) +} diff --git a/orchestrator/src/server/api/routes/profile.ts b/orchestrator/src/server/api/routes/profile.ts index e802cd0..ad531b9 100644 --- a/orchestrator/src/server/api/routes/profile.ts +++ b/orchestrator/src/server/api/routes/profile.ts @@ -1,6 +1,8 @@ import { Router, Request, Response } from 'express'; +import { access, mkdir, writeFile } from 'fs/promises'; +import { dirname } from 'path'; import { extractProjectsFromProfile } from '../../services/resumeProjects.js'; -import { getProfile } from '../../services/profile.js'; +import { clearProfileCache, DEFAULT_PROFILE_PATH, getProfile } from '../../services/profile.js'; export const profileRouter = Router(); @@ -30,3 +32,38 @@ profileRouter.get('/', async (req: Request, res: Response) => { res.status(500).json({ success: false, error: message }); } }); + +/** + * GET /api/profile/status - Check if base resume exists + */ +profileRouter.get('/status', async (_req: Request, res: Response) => { + try { + await access(DEFAULT_PROFILE_PATH); + res.json({ success: true, data: { exists: true, error: null } }); + } catch (error) { + const message = error instanceof Error ? error.message : 'Unknown error'; + res.json({ success: true, data: { exists: false, error: message } }); + } +}); + +/** + * POST /api/profile/upload - Upload base resume JSON + */ +profileRouter.post('/upload', async (req: Request, res: Response) => { + try { + const profile = (req.body && typeof req.body === 'object' ? (req.body as Record).profile : null) as unknown; + + if (!profile || typeof profile !== 'object' || Array.isArray(profile)) { + throw new Error('Invalid profile payload. Expected a JSON object.'); + } + + await mkdir(dirname(DEFAULT_PROFILE_PATH), { recursive: true }); + await writeFile(DEFAULT_PROFILE_PATH, JSON.stringify(profile, null, 2), 'utf-8'); + clearProfileCache(); + + res.json({ success: true, data: { exists: true, error: null } }); + } catch (error) { + const message = error instanceof Error ? error.message : 'Unknown error'; + res.status(400).json({ success: false, error: message }); + } +}); diff --git a/orchestrator/src/server/app.ts b/orchestrator/src/server/app.ts index 4f39077..1cd20e7 100644 --- a/orchestrator/src/server/app.ts +++ b/orchestrator/src/server/app.ts @@ -74,7 +74,7 @@ export function createApp() { const authGuard = createBasicAuthGuard(); app.use(cors()); - app.use(express.json()); + app.use(express.json({ limit: '5mb' })); // Logging middleware app.use((req, res, next) => { diff --git a/orchestrator/src/server/services/settings.ts b/orchestrator/src/server/services/settings.ts index fd82c7e..76e47b1 100644 --- a/orchestrator/src/server/services/settings.ts +++ b/orchestrator/src/server/services/settings.ts @@ -11,7 +11,10 @@ export async function getEffectiveSettings(): Promise { // Parallelize slow operations const [overrides, profile] = await Promise.all([ settingsRepo.getAllSettings(), - getProfile(), + getProfile().catch((error) => { + console.warn('Failed to load base resume profile for settings:', error); + return {}; + }), ]); const envSettings = await getEnvSettingsData(overrides); diff --git a/orchestrator/src/shared/types.ts b/orchestrator/src/shared/types.ts index fbafbf6..5d69d1e 100644 --- a/orchestrator/src/shared/types.ts +++ b/orchestrator/src/shared/types.ts @@ -331,6 +331,11 @@ export interface ResumeProfile { [key: string]: any; } +export interface ProfileStatusResponse { + exists: boolean; + error: string | null; +} + export interface AppSettings { model: string; defaultModel: string; From 662e4a344ab1439c1c2a8ee92c933855ad792998 Mon Sep 17 00:00:00 2001 From: DaKheera47 Date: Thu, 22 Jan 2026 19:11:53 +0000 Subject: [PATCH 02/14] multistep has better UI --- .../src/client/components/OnboardingGate.tsx | 401 +++++++++++------- 1 file changed, 237 insertions(+), 164 deletions(-) diff --git a/orchestrator/src/client/components/OnboardingGate.tsx b/orchestrator/src/client/components/OnboardingGate.tsx index 795b3bd..1e8c846 100644 --- a/orchestrator/src/client/components/OnboardingGate.tsx +++ b/orchestrator/src/client/components/OnboardingGate.tsx @@ -1,11 +1,12 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react" +import { Check } from "lucide-react" import { toast } from "sonner" import { AlertDialog, AlertDialogContent, AlertDialogDescription, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog" -import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" -import { Separator } from "@/components/ui/separator" +import { Progress } from "@/components/ui/progress" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { cn } from "@/lib/utils" import * as api from "@client/api" import { useSettings } from "@client/hooks/useSettings" @@ -13,33 +14,13 @@ import { SettingsInput } from "@client/pages/settings/components/SettingsInput" import { formatSecretHint } from "@client/pages/settings/utils" import type { ProfileStatusResponse, ResumeProfile } from "@shared/types" -type RequirementRowProps = { - label: string - helper?: string - complete: boolean -} - -const RequirementRow: React.FC = ({ label, helper, complete }) => ( -
-
-

{label}

- {helper &&

{helper}

} -
- - {complete ? "Ready" : "Next"} - -
-) - export const OnboardingGate: React.FC = () => { const { settings, isLoading: settingsLoading, refreshSettings } = useSettings() const [profileStatus, setProfileStatus] = useState(null) const [isCheckingProfile, setIsCheckingProfile] = useState(false) const [isSavingEnv, setIsSavingEnv] = useState(false) const [isUploadingResume, setIsUploadingResume] = useState(false) + const [currentStep, setCurrentStep] = useState(null) const [openrouterApiKey, setOpenrouterApiKey] = useState("") const [rxresumeEmail, setRxresumeEmail] = useState("") @@ -83,6 +64,39 @@ export const OnboardingGate: React.FC = () => { ? formatSecretHint(settings.rxresumePasswordHint) : undefined + const steps = useMemo( + () => [ + { + id: "openrouter", + label: "Connect AI", + subtitle: "OpenRouter key", + complete: hasOpenrouterKey, + }, + { + id: "rxresume", + label: "PDF Export", + subtitle: "RxResume login", + complete: hasRxresumeCredentials, + }, + { + id: "resume", + label: "Resume JSON", + subtitle: "Upload your file", + complete: hasBaseResume, + }, + ], + [hasBaseResume, hasOpenrouterKey, hasRxresumeCredentials] + ) + + const defaultStep = steps.find((step) => !step.complete)?.id ?? steps[0]?.id + + useEffect(() => { + if (!shouldOpen) return + if (!currentStep && defaultStep) { + setCurrentStep(defaultStep) + } + }, [currentStep, defaultStep, shouldOpen]) + const handleRefresh = async () => { const results = await Promise.allSettled([refreshSettings(), refreshProfileStatus()]) const failed = results.find((result) => result.status === "rejected") @@ -93,59 +107,73 @@ export const OnboardingGate: React.FC = () => { } } - const handleSaveCredentials = async () => { - if (!settings) return - const update: { openrouterApiKey?: string; rxresumeEmail?: string; rxresumePassword?: string } = {} + const handleSaveOpenrouter = async (): Promise => { const openrouterValue = openrouterApiKey.trim() + if (hasOpenrouterKey && !openrouterValue) return true + if (!openrouterValue) { + toast.info("Add your OpenRouter API key to continue") + return false + } + + try { + setIsSavingEnv(true) + await api.updateSettings({ openrouterApiKey: openrouterValue }) + await refreshSettings() + setOpenrouterApiKey("") + toast.success("OpenRouter connected") + return true + } catch (error) { + const message = error instanceof Error ? error.message : "Failed to save OpenRouter key" + toast.error(message) + return false + } finally { + setIsSavingEnv(false) + } + } + + const handleSaveRxresume = async (): Promise => { const emailValue = rxresumeEmail.trim() const passwordValue = rxresumePassword.trim() - const missing: string[] = [] - if (!hasOpenrouterKey && !openrouterValue) { - missing.push("OpenRouter API key") - } - - if (!hasRxresumeCredentials) { - if (!hasRxresumeEmail && !emailValue) missing.push("RxResume email") - if (!hasRxresumePassword && !passwordValue) missing.push("RxResume password") - } + if (!hasRxresumeEmail && !emailValue) missing.push("RxResume email") + if (!hasRxresumePassword && !passwordValue) missing.push("RxResume password") if (missing.length > 0) { toast.info("Almost there", { description: `Missing: ${missing.join(", ")}`, }) - return + return false } - if (openrouterValue) update.openrouterApiKey = openrouterValue + const update: { rxresumeEmail?: string; rxresumePassword?: string } = {} if (emailValue) update.rxresumeEmail = emailValue if (passwordValue) update.rxresumePassword = passwordValue if (Object.keys(update).length === 0) { - toast.info("Nothing new to save") - return + return true } try { setIsSavingEnv(true) await api.updateSettings(update) await refreshSettings() - setOpenrouterApiKey("") setRxresumePassword("") - toast.success("Credentials saved") + toast.success("RxResume connected") + return true } catch (error) { - const message = error instanceof Error ? error.message : "Failed to save credentials" + const message = error instanceof Error ? error.message : "Failed to save RxResume credentials" toast.error(message) + return false } finally { setIsSavingEnv(false) } } - const handleUploadResume = async () => { + const handleUploadResume = async (): Promise => { if (!resumeFile) { toast.info("Choose your base.json file") - return + return false } try { @@ -165,160 +193,205 @@ export const OnboardingGate: React.FC = () => { fileInputRef.current.value = "" } toast.success("Resume uploaded") + return true } catch (error) { const message = error instanceof Error ? error.message : "Failed to upload resume" toast.error(message) + return false } finally { setIsUploadingResume(false) } } const resumeFileName = resumeFile?.name || "" + const resolvedStepIndex = currentStep ? steps.findIndex((step) => step.id === currentStep) : 0 + const stepIndex = resolvedStepIndex >= 0 ? resolvedStepIndex : 0 + const completedSteps = steps.filter((step) => step.complete).length + const progressValue = steps.length > 0 ? Math.round((completedSteps / steps.length) * 100) : 0 + const isBusy = isSavingEnv || isUploadingResume || settingsLoading || isCheckingProfile + const canGoBack = stepIndex > 0 + const canGoForward = stepIndex < steps.length - 1 + const primaryLabel = currentStep === "resume" + ? (hasBaseResume ? "Finish" : "Upload and finish") + : (currentStep === "openrouter" && !hasOpenrouterKey) || (currentStep === "rxresume" && !hasRxresumeCredentials) + ? "Save" + : "Continue" - const checklist = useMemo( - () => [ - { - label: "OpenRouter API key", - helper: "Needed for scoring + tailoring", - complete: hasOpenrouterKey, - }, - { - label: "RxResume credentials", - helper: "Used to export PDFs", - complete: hasRxresumeCredentials, - }, - { - label: "Base resume JSON", - helper: "Upload resume-generator/base.json", - complete: hasBaseResume, - }, - ], - [hasBaseResume, hasOpenrouterKey, hasRxresumeCredentials] - ) + const handlePrimaryAction = async () => { + if (!currentStep) return + if (currentStep === "openrouter") { + await handleSaveOpenrouter() + return + } + if (currentStep === "rxresume") { + await handleSaveRxresume() + return + } + if (currentStep === "resume") { + if (hasBaseResume) { + await handleRefresh() + return + } + await handleUploadResume() + } + } - if (!shouldOpen) return null + const handleBack = () => { + if (!canGoBack) return + setCurrentStep(steps[stepIndex - 1]?.id ?? currentStep) + } + + if (!shouldOpen || !currentStep) return null return ( event.preventDefault()} onPointerDownOutside={(event) => event.preventDefault()} onInteractOutside={(event) => event.preventDefault()} > - - Welcome to Job Ops - - Let’s get your workspace ready. Add your keys and resume once, then the pipeline can run end-to-end. - - +
+ + Welcome to Job Ops + + Let’s get your workspace ready. Add your keys and resume once, then the pipeline can run end-to-end. + + -
-
-
-

Quick setup checklist

- -
-
- {checklist.map((item) => ( - - ))} -
-
+ + + {steps.map((step, index) => { + const isActive = step.id === currentStep + const isComplete = step.complete - + return ( + +
+ + {isComplete ? : index + 1} + + + {step.label} + +
+ {step.subtitle} +
+ ) + })} +
-
-
-

OpenRouter

-

Used for job scoring, summaries, and tailoring.

-
- setOpenrouterApiKey(event.target.value), - }} - type="password" - placeholder="sk-or-v1..." - current={openrouterCurrent} - helper="Create a key at openrouter.ai" - disabled={isSavingEnv} - /> -
- - - -
-
-

RxResume account

-

Used to export tailored PDFs.

-
-
+ +
+

Connect OpenRouter

+

Used for job scoring, summaries, and tailoring.

+
setRxresumeEmail(event.target.value), - }} - placeholder="you@example.com" - current={rxresumeEmailCurrent} - disabled={isSavingEnv} - /> - setRxresumePassword(event.target.value), + name: "openrouterApiKey", + value: openrouterApiKey, + onChange: (event) => setOpenrouterApiKey(event.target.value), }} type="password" - placeholder="Enter password" - current={rxresumePasswordCurrent} + placeholder="sk-or-v1..." + current={openrouterCurrent} + helper="Create a key at openrouter.ai" disabled={isSavingEnv} /> -
-
- -
-
+ - - -
-
-

Base resume JSON

-

Upload your RxResume export named base.json.

-
-
-
- - setResumeFile(event.target.files?.[0] ?? null)} - disabled={isUploadingResume} - /> - {resumeFileName && ( -

Selected: {resumeFileName}

- )} + +
+

Link your RxResume account

+

Used to export tailored PDFs.

- +
+ +
+ +
Friendly heads-up: pipelines can be slow or a little flaky in alpha. If anything feels off, open a GitHub issue and we will take a look.{" "} From 7b5afd25d1c4a626725c8eaeda435f33b0123e90 Mon Sep 17 00:00:00 2001 From: DaKheera47 Date: Thu, 22 Jan 2026 19:28:32 +0000 Subject: [PATCH 03/14] correcting animations --- .../src/components/ui/alert-dialog.tsx | 220 ++++++++++-------- 1 file changed, 119 insertions(+), 101 deletions(-) diff --git a/orchestrator/src/components/ui/alert-dialog.tsx b/orchestrator/src/components/ui/alert-dialog.tsx index fa2b442..0863e40 100644 --- a/orchestrator/src/components/ui/alert-dialog.tsx +++ b/orchestrator/src/components/ui/alert-dialog.tsx @@ -1,128 +1,146 @@ +"use client" + import * as React from "react" import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" import { cn } from "@/lib/utils" import { buttonVariants } from "@/components/ui/button" -const AlertDialog = AlertDialogPrimitive.Root +function AlertDialog({ + ...props +}: React.ComponentProps) { + return +} -const AlertDialogTrigger = AlertDialogPrimitive.Trigger +function AlertDialogTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} -const AlertDialogPortal = AlertDialogPrimitive.Portal +function AlertDialogPortal({ + ...props +}: React.ComponentProps) { + return ( + + ) +} -const AlertDialogOverlay = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName - -const AlertDialogContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - ) { + return ( + - -)) -AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName + ) +} -const AlertDialogHeader = ({ +function AlertDialogContent({ className, ...props -}: React.HTMLAttributes) => ( -
-) -AlertDialogHeader.displayName = "AlertDialogHeader" +}: React.ComponentProps) { + return ( + + + + + ) +} -const AlertDialogFooter = ({ +function AlertDialogHeader({ className, ...props -}: React.HTMLAttributes) => ( -
-) -AlertDialogFooter.displayName = "AlertDialogFooter" +}: React.ComponentProps<"div">) { + return ( +
+ ) +} -const AlertDialogTitle = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName +function AlertDialogFooter({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} -const AlertDialogDescription = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AlertDialogDescription.displayName = - AlertDialogPrimitive.Description.displayName +function AlertDialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} -const AlertDialogAction = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName +function AlertDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} -const AlertDialogCancel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName +function AlertDialogAction({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogCancel({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} export { AlertDialog, From f60ce5db4fb2cb9bc6cd86a5abdefd3d35bfc751 Mon Sep 17 00:00:00 2001 From: DaKheera47 Date: Thu, 22 Jan 2026 20:04:08 +0000 Subject: [PATCH 04/14] tailwind config artefacts cleaned up --- orchestrator/package-lock.json | 240 ++++++++---------- orchestrator/package.json | 5 +- .../src/components/ui/alert-dialog.tsx | 220 ++++++++-------- orchestrator/src/index.css | 70 +---- orchestrator/tailwind.config.ts | 19 -- orchestrator/vite.config.ts | 3 +- 6 files changed, 221 insertions(+), 336 deletions(-) diff --git a/orchestrator/package-lock.json b/orchestrator/package-lock.json index 3fcd2ce..195831c 100644 --- a/orchestrator/package-lock.json +++ b/orchestrator/package-lock.json @@ -14,11 +14,14 @@ "@radix-ui/react-checkbox": "^1.3.2", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-label": "^2.1.8", "@radix-ui/react-progress": "^1.1.8", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-tooltip": "^1.2.8", + "@tailwindcss/vite": "^4.1.18", "better-sqlite3": "^11.6.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -35,7 +38,6 @@ "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tailwindcss-animate": "^1.0.7", - "tw-animate-css": "^1.4.0", "vaul": "^1.1.2", "zod": "^3.23.8" }, @@ -62,6 +64,7 @@ "tailwindcss": "^4.1.18", "tsc-alias": "^1.8.16", "tsx": "^4.19.2", + "tw-animate-css": "^1.4.0", "typescript": "^5.7.2", "vite": "^6.0.3", "vitest": "^4.0.16" @@ -1243,7 +1246,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1277,7 +1279,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1311,7 +1312,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1439,7 +1439,6 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1450,7 +1449,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -1461,7 +1459,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1471,14 +1468,12 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1569,6 +1564,7 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", + "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", @@ -1934,6 +1930,52 @@ } } }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", + "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "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-label/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "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-menu": { "version": "2.1.16", "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", @@ -2165,6 +2207,38 @@ } } }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.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-roving-focus": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", @@ -2199,6 +2273,7 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", + "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.4" }, @@ -2243,6 +2318,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, @@ -2507,7 +2583,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2521,7 +2596,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2535,7 +2609,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2549,7 +2622,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2563,7 +2635,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2577,7 +2648,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2591,7 +2661,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2605,7 +2674,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2619,7 +2687,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2633,7 +2700,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2647,7 +2713,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2661,7 +2726,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2675,7 +2739,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2689,7 +2752,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2703,7 +2765,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2717,7 +2778,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2731,7 +2791,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2745,7 +2804,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2759,7 +2817,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2773,7 +2830,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2787,7 +2843,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2801,7 +2856,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2824,7 +2878,6 @@ "version": "4.1.18", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", - "dev": true, "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", @@ -2839,7 +2892,6 @@ "version": "4.1.18", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", - "dev": true, "engines": { "node": ">= 10" }, @@ -2865,7 +2917,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -2881,7 +2932,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -2897,7 +2947,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -2913,7 +2962,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -2929,7 +2977,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2945,7 +2992,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2961,7 +3007,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2977,7 +3022,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -2993,7 +3037,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -3017,7 +3060,6 @@ "cpu": [ "wasm32" ], - "dev": true, "optional": true, "dependencies": { "@emnapi/core": "^1.7.1", @@ -3038,7 +3080,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -3054,7 +3095,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -3076,6 +3116,20 @@ "tailwindcss": "4.1.18" } }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz", + "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==", + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "tailwindcss": "4.1.18" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, "node_modules/@testing-library/dom": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", @@ -4108,6 +4162,7 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", "dependencies": { "clsx": "^2.1.1" }, @@ -4134,6 +4189,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -4674,7 +4730,6 @@ "version": "5.18.4", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -4980,7 +5035,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -5103,7 +5157,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5226,7 +5279,7 @@ "version": "4.13.0", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -5290,8 +5343,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/has-flag": { "version": "4.0.0", @@ -5651,7 +5703,6 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -5732,7 +5783,6 @@ "version": "1.30.2", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", - "dev": true, "dependencies": { "detect-libc": "^2.0.3" }, @@ -5764,7 +5814,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -5784,7 +5833,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -5804,7 +5852,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -5824,7 +5871,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -5844,7 +5890,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5864,7 +5909,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5884,7 +5928,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5904,7 +5947,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5924,7 +5966,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -5944,7 +5985,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -5964,7 +6004,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -6012,6 +6051,7 @@ "version": "0.561.0", "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.561.0.tgz", "integrity": "sha512-Y59gMY38tl4/i0qewcqohPdEbieBy7SovpBL9IFebhc2mDd8x4PZSOsiFRkpPcOq6bj1r/mjH/Rk73gSlIJP2A==", + "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } @@ -6030,7 +6070,6 @@ "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } @@ -7000,7 +7039,6 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, "funding": [ { "type": "github", @@ -7217,14 +7255,12 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -7250,7 +7286,6 @@ "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -7823,7 +7858,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, + "devOptional": true, "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" @@ -7844,7 +7879,6 @@ "version": "4.53.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -8313,7 +8347,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -8473,6 +8506,7 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/dcastil" @@ -8481,7 +8515,8 @@ "node_modules/tailwindcss": { "version": "4.1.18", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", - "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==" + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", + "license": "MIT" }, "node_modules/tailwindcss-animate": { "version": "1.0.7", @@ -8495,7 +8530,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "dev": true, "engines": { "node": ">=6" }, @@ -8551,7 +8585,6 @@ "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -8697,7 +8730,7 @@ "version": "4.21.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "esbuild": "~0.27.0", @@ -8720,7 +8753,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8737,7 +8769,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8754,7 +8785,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8771,7 +8801,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8788,7 +8817,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8805,7 +8833,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8822,7 +8849,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8839,7 +8865,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8856,7 +8881,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8873,7 +8897,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8890,7 +8913,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8907,7 +8929,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8924,7 +8945,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8941,7 +8961,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8958,7 +8977,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8975,7 +8993,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -8992,7 +9009,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9009,7 +9025,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9026,7 +9041,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9043,7 +9057,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9060,7 +9073,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9077,7 +9089,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9094,7 +9105,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9108,7 +9118,7 @@ "version": "0.27.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", "integrity": "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -9162,6 +9172,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==", + "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/Wombosvideo" } @@ -9428,7 +9440,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", @@ -9506,7 +9517,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9523,7 +9533,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9540,7 +9549,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9557,7 +9565,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9574,7 +9581,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9591,7 +9597,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9608,7 +9613,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9625,7 +9629,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9642,7 +9645,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9659,7 +9661,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9676,7 +9677,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9693,7 +9693,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9710,7 +9709,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9727,7 +9725,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9744,7 +9741,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9761,7 +9757,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9778,7 +9773,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9795,7 +9789,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9812,7 +9805,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9829,7 +9821,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9846,7 +9837,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9863,7 +9853,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9880,7 +9869,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9897,7 +9885,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9914,7 +9901,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9931,7 +9917,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -9945,7 +9930,6 @@ "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { diff --git a/orchestrator/package.json b/orchestrator/package.json index 3999cd9..62d472a 100644 --- a/orchestrator/package.json +++ b/orchestrator/package.json @@ -26,11 +26,14 @@ "@radix-ui/react-checkbox": "^1.3.2", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-label": "^2.1.8", "@radix-ui/react-progress": "^1.1.8", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-tooltip": "^1.2.8", + "@tailwindcss/vite": "^4.1.18", "better-sqlite3": "^11.6.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", @@ -47,7 +50,6 @@ "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tailwindcss-animate": "^1.0.7", - "tw-animate-css": "^1.4.0", "vaul": "^1.1.2", "zod": "^3.23.8" }, @@ -74,6 +76,7 @@ "tailwindcss": "^4.1.18", "tsc-alias": "^1.8.16", "tsx": "^4.19.2", + "tw-animate-css": "^1.4.0", "typescript": "^5.7.2", "vite": "^6.0.3", "vitest": "^4.0.16" diff --git a/orchestrator/src/components/ui/alert-dialog.tsx b/orchestrator/src/components/ui/alert-dialog.tsx index 0863e40..6b537d7 100644 --- a/orchestrator/src/components/ui/alert-dialog.tsx +++ b/orchestrator/src/components/ui/alert-dialog.tsx @@ -1,146 +1,128 @@ -"use client" - import * as React from "react" import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" import { cn } from "@/lib/utils" import { buttonVariants } from "@/components/ui/button" -function AlertDialog({ - ...props -}: React.ComponentProps) { - return -} +const AlertDialog = AlertDialogPrimitive.Root -function AlertDialogTrigger({ - ...props -}: React.ComponentProps) { - return ( - - ) -} +const AlertDialogTrigger = AlertDialogPrimitive.Trigger -function AlertDialogPortal({ - ...props -}: React.ComponentProps) { - return ( - - ) -} +const AlertDialogPortal = AlertDialogPrimitive.Portal -function AlertDialogOverlay({ - className, - ...props -}: React.ComponentProps) { - return ( - , + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + - ) -} + +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName -function AlertDialogContent({ +const AlertDialogHeader = ({ className, ...props -}: React.ComponentProps) { - return ( - - - - - ) -} +}: React.HTMLAttributes) => ( +
+) +AlertDialogHeader.displayName = "AlertDialogHeader" -function AlertDialogHeader({ +const AlertDialogFooter = ({ className, ...props -}: React.ComponentProps<"div">) { - return ( -
- ) -} +}: React.HTMLAttributes) => ( +
+) +AlertDialogFooter.displayName = "AlertDialogFooter" -function AlertDialogFooter({ - className, - ...props -}: React.ComponentProps<"div">) { - return ( -
- ) -} +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName -function AlertDialogTitle({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName -function AlertDialogDescription({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName -function AlertDialogAction({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} - -function AlertDialogCancel({ - className, - ...props -}: React.ComponentProps) { - return ( - - ) -} +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName export { AlertDialog, diff --git a/orchestrator/src/index.css b/orchestrator/src/index.css index a9bb87e..cca4e24 100644 --- a/orchestrator/src/index.css +++ b/orchestrator/src/index.css @@ -1,15 +1,10 @@ @import url("https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600;700&family=Lora:wght@400;500;600;700&display=swap"); @import "tailwindcss"; - @import "tw-animate-css"; -@plugin "tailwindcss-animate"; - @custom-variant dark (&:is(.dark *)); -@tailwind utilities; - @theme inline { --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); @@ -132,68 +127,6 @@ --shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10); --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25); --tracking-normal: 0em; - - --animate-in: in 0.5s ease-out forwards; - --animate-out: out 0.3s ease-in forwards; - --animate-fade-in: fade-in 0.5s ease-out forwards; - --animate-fade-out: fade-out 0.3s ease-in forwards; - --animate-slide-in-from-left: slide-in-from-left 0.5s ease-out forwards; - --animate-slide-out-to-left: slide-out-to-left 0.3s ease-in forwards; - --animate-slide-in-from-right: slide-in-from-right 0.5s ease-out forwards; - --animate-slide-out-to-right: slide-out-to-right 0.3s ease-in forwards; - --animate-slide-in-from-top: slide-in-from-top 0.5s ease-out forwards; - --animate-slide-out-to-top: slide-out-to-top 0.3s ease-in forwards; - --animate-slide-in-from-bottom: slide-in-from-bottom 0.5s ease-out forwards; - --animate-slide-out-to-bottom: slide-out-to-bottom 0.3s ease-in forwards; - - @keyframes in { - from { opacity: 0; } - to { opacity: 1; } - } - @keyframes out { - from { opacity: 1; } - to { opacity: 0; } - } - @keyframes fade-in { - from { opacity: 0; } - to { opacity: 1; } - } - @keyframes fade-out { - from { opacity: 1; } - to { opacity: 0; } - } - @keyframes slide-in-from-left { - from { transform: translateX(-100%); } - to { transform: translateX(0); } - } - @keyframes slide-out-to-left { - from { transform: translateX(0); } - to { transform: translateX(-100%); } - } - @keyframes slide-in-from-right { - from { transform: translateX(100%); } - to { transform: translateX(0); } - } - @keyframes slide-out-to-right { - from { transform: translateX(0); } - to { transform: translateX(100%); } - } - @keyframes slide-in-from-top { - from { transform: translateY(-100%); } - to { transform: translateY(0); } - } - @keyframes slide-out-to-top { - from { transform: translateY(0); } - to { transform: translateY(-100%); } - } - @keyframes slide-in-from-bottom { - from { transform: translateY(100%); } - to { transform: translateY(0); } - } - @keyframes slide-out-to-bottom { - from { transform: translateY(0); } - to { transform: translateY(100%); } - } } .dark { @@ -255,6 +188,7 @@ * { @apply border-border outline-ring/50; } + body { font-family: var(--font-sans); @apply bg-background text-foreground antialiased; @@ -276,4 +210,4 @@ .page-exit-active { opacity: 0; transition: opacity 75ms ease-in; -} \ No newline at end of file +} diff --git a/orchestrator/tailwind.config.ts b/orchestrator/tailwind.config.ts index 64f9d9b..57b3bcc 100644 --- a/orchestrator/tailwind.config.ts +++ b/orchestrator/tailwind.config.ts @@ -3,24 +3,5 @@ import type { Config } from "tailwindcss"; export default { darkMode: "class", content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], - theme: { - extend: { - keyframes: { - "accordion-down": { - from: { height: "0" }, - to: { height: "var(--radix-accordion-content-height)" }, - }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: "0" }, - }, - }, - animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", - }, - }, - }, plugins: [], } satisfies Config; - diff --git a/orchestrator/vite.config.ts b/orchestrator/vite.config.ts index 663ef69..e11b661 100644 --- a/orchestrator/vite.config.ts +++ b/orchestrator/vite.config.ts @@ -2,9 +2,10 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import path from 'path'; +import tailwindcss from '@tailwindcss/vite' export default defineConfig({ - plugins: [react()], + plugins: [react(), tailwindcss()], test: { globals: true, environment: 'jsdom', From 8fe9074eadf0e1856ee114c731682f9b13b6f1d8 Mon Sep 17 00:00:00 2001 From: DaKheera47 Date: Thu, 22 Jan 2026 20:04:21 +0000 Subject: [PATCH 05/14] nice looking components --- .../src/client/components/OnboardingGate.tsx | 56 ++-- orchestrator/src/components/ui/field.tsx | 244 ++++++++++++++++++ orchestrator/src/components/ui/label.tsx | 26 ++ .../src/components/ui/radio-group.tsx | 42 +++ 4 files changed, 340 insertions(+), 28 deletions(-) create mode 100644 orchestrator/src/components/ui/field.tsx create mode 100644 orchestrator/src/components/ui/label.tsx create mode 100644 orchestrator/src/components/ui/radio-group.tsx diff --git a/orchestrator/src/client/components/OnboardingGate.tsx b/orchestrator/src/client/components/OnboardingGate.tsx index 1e8c846..3a5a863 100644 --- a/orchestrator/src/client/components/OnboardingGate.tsx +++ b/orchestrator/src/client/components/OnboardingGate.tsx @@ -4,6 +4,7 @@ import { toast } from "sonner" import { AlertDialog, AlertDialogContent, AlertDialogDescription, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog" import { Button } from "@/components/ui/button" +import { Field, FieldContent, FieldDescription, FieldLabel, FieldTitle } from "@/components/ui/field" import { Input } from "@/components/ui/input" import { Progress } from "@/components/ui/progress" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" @@ -248,8 +249,6 @@ export const OnboardingGate: React.FC = () => { event.preventDefault()} - onPointerDownOutside={(event) => event.preventDefault()} - onInteractOutside={(event) => event.preventDefault()} >
@@ -260,40 +259,41 @@ export const OnboardingGate: React.FC = () => { - + {steps.map((step, index) => { const isActive = step.id === currentStep const isComplete = step.complete return ( - -
- + + + {step.label} + {step.subtitle} + + - {isComplete ? : index + 1} - - - {step.label} - -
- {step.subtitle} -
+ )} + > + {isComplete ? : index + 1} + + + + ) })}
diff --git a/orchestrator/src/components/ui/field.tsx b/orchestrator/src/components/ui/field.tsx new file mode 100644 index 0000000..0a276fc --- /dev/null +++ b/orchestrator/src/components/ui/field.tsx @@ -0,0 +1,244 @@ +"use client" + +import { useMemo } from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +import { Label } from "@/components/ui/label" +import { Separator } from "@/components/ui/separator" + +function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { + return ( +
[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", + className + )} + {...props} + /> + ) +} + +function FieldLegend({ + className, + variant = "legend", + ...props +}: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) { + return ( + + ) +} + +function FieldGroup({ className, ...props }: React.ComponentProps<"div">) { + return ( +
[data-slot=field-group]]:gap-4", + className + )} + {...props} + /> + ) +} + +const fieldVariants = cva( + "group/field data-[invalid=true]:text-destructive flex w-full gap-3", + { + variants: { + orientation: { + vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"], + horizontal: [ + "flex-row items-center", + "[&>[data-slot=field-label]]:flex-auto", + "has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px has-[>[data-slot=field-content]]:items-start", + ], + responsive: [ + "@md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto flex-col [&>*]:w-full [&>.sr-only]:w-auto", + "@md/field-group:[&>[data-slot=field-label]]:flex-auto", + "@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", + ], + }, + }, + defaultVariants: { + orientation: "vertical", + }, + } +) + +function Field({ + className, + orientation = "vertical", + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function FieldContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function FieldLabel({ + className, + ...props +}: React.ComponentProps) { + return ( +