Spaces:
Paused
Paused
Update uptime route and dependencies for improved functionality
Browse files- app/routes/uptime.tsx +84 -78
- package-lock.json +193 -0
- package.json +1 -0
app/routes/uptime.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import { Separator } from "~/components/ui/separator";
|
|
| 12 |
import { Alert, AlertDescription } from "~/components/ui/alert";
|
| 13 |
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "~/components/ui/dialog";
|
| 14 |
import { Avatar, AvatarFallback } from "~/components/ui/avatar";
|
|
|
|
| 15 |
import { Plus, LogOut, Pencil, Trash2, Activity, Clock, TrendingUp, AlertCircle } from "lucide-react";
|
| 16 |
import { ThemeToggle } from "~/components/theme-toggle";
|
| 17 |
|
|
@@ -143,7 +144,7 @@ export function meta({}: Route.MetaArgs) {
|
|
| 143 |
export default function Uptime({ loaderData, actionData }: Route.ComponentProps) {
|
| 144 |
const { stats, user } = loaderData;
|
| 145 |
const revalidator = useRevalidator();
|
| 146 |
-
const [
|
| 147 |
const [editingMonitor, setEditingMonitor] = useState<UptimeStats | null>(null);
|
| 148 |
const [deletingMonitor, setDeletingMonitor] = useState<string | null>(null);
|
| 149 |
|
|
@@ -159,7 +160,7 @@ export default function Uptime({ loaderData, actionData }: Route.ComponentProps)
|
|
| 159 |
// Close forms on successful action
|
| 160 |
useEffect(() => {
|
| 161 |
if (actionData?.success) {
|
| 162 |
-
|
| 163 |
setEditingMonitor(null);
|
| 164 |
setDeletingMonitor(null);
|
| 165 |
revalidator.revalidate();
|
|
@@ -167,8 +168,9 @@ export default function Uptime({ loaderData, actionData }: Route.ComponentProps)
|
|
| 167 |
}, [actionData, revalidator]);
|
| 168 |
|
| 169 |
return (
|
| 170 |
-
<
|
| 171 |
-
<div className="
|
|
|
|
| 172 |
{/* Header */}
|
| 173 |
<header className="mb-8 flex items-center justify-between">
|
| 174 |
<div>
|
|
@@ -200,73 +202,12 @@ export default function Uptime({ loaderData, actionData }: Route.ComponentProps)
|
|
| 200 |
|
| 201 |
{/* Add Monitor Button */}
|
| 202 |
<div className="mb-6">
|
| 203 |
-
<Button onClick={() =>
|
| 204 |
<Plus className="h-4 w-4 mr-2" />
|
| 205 |
-
|
| 206 |
</Button>
|
| 207 |
</div>
|
| 208 |
|
| 209 |
-
{/* Add Monitor Form */}
|
| 210 |
-
{showAddForm && (
|
| 211 |
-
<Card className="mb-6">
|
| 212 |
-
<CardHeader>
|
| 213 |
-
<CardTitle>Add New Monitor</CardTitle>
|
| 214 |
-
<CardDescription>
|
| 215 |
-
Start monitoring a new service endpoint
|
| 216 |
-
</CardDescription>
|
| 217 |
-
</CardHeader>
|
| 218 |
-
<CardContent>
|
| 219 |
-
{actionData?.error && (
|
| 220 |
-
<Alert variant="destructive" className="mb-4">
|
| 221 |
-
<AlertCircle className="h-4 w-4" />
|
| 222 |
-
<AlertDescription>{actionData.error}</AlertDescription>
|
| 223 |
-
</Alert>
|
| 224 |
-
)}
|
| 225 |
-
<Form method="post" className="space-y-4">
|
| 226 |
-
<input type="hidden" name="intent" value="create" />
|
| 227 |
-
|
| 228 |
-
<div className="space-y-2">
|
| 229 |
-
<Label htmlFor="url">URL to Monitor</Label>
|
| 230 |
-
<Input
|
| 231 |
-
id="url"
|
| 232 |
-
type="url"
|
| 233 |
-
name="url"
|
| 234 |
-
required
|
| 235 |
-
placeholder="https://example.com"
|
| 236 |
-
/>
|
| 237 |
-
</div>
|
| 238 |
-
|
| 239 |
-
<div className="space-y-2">
|
| 240 |
-
<Label htmlFor="interval">Check Interval (seconds)</Label>
|
| 241 |
-
<Input
|
| 242 |
-
id="interval"
|
| 243 |
-
type="number"
|
| 244 |
-
name="interval"
|
| 245 |
-
required
|
| 246 |
-
min="10"
|
| 247 |
-
defaultValue="30"
|
| 248 |
-
placeholder="30"
|
| 249 |
-
/>
|
| 250 |
-
<p className="text-xs text-muted-foreground">
|
| 251 |
-
Minimum 10 seconds
|
| 252 |
-
</p>
|
| 253 |
-
</div>
|
| 254 |
-
|
| 255 |
-
<div className="flex gap-3">
|
| 256 |
-
<Button type="submit">Create Monitor</Button>
|
| 257 |
-
<Button
|
| 258 |
-
type="button"
|
| 259 |
-
variant="outline"
|
| 260 |
-
onClick={() => setShowAddForm(false)}
|
| 261 |
-
>
|
| 262 |
-
Cancel
|
| 263 |
-
</Button>
|
| 264 |
-
</div>
|
| 265 |
-
</Form>
|
| 266 |
-
</CardContent>
|
| 267 |
-
</Card>
|
| 268 |
-
)}
|
| 269 |
-
|
| 270 |
{stats.length === 0 ? (
|
| 271 |
<Card>
|
| 272 |
<CardContent className="pt-6 text-center py-12">
|
|
@@ -386,17 +327,26 @@ export default function Uptime({ loaderData, actionData }: Route.ComponentProps)
|
|
| 386 |
.slice(-20)
|
| 387 |
.reverse()
|
| 388 |
.map((check, idx: number) => (
|
| 389 |
-
<
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
))}
|
| 401 |
</div>
|
| 402 |
</div>
|
|
@@ -408,6 +358,61 @@ export default function Uptime({ loaderData, actionData }: Route.ComponentProps)
|
|
| 408 |
</div>
|
| 409 |
)}
|
| 410 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 411 |
{/* Edit Monitor Modal */}
|
| 412 |
<Dialog open={!!editingMonitor} onOpenChange={() => setEditingMonitor(null)}>
|
| 413 |
<DialogContent>
|
|
@@ -502,5 +507,6 @@ export default function Uptime({ loaderData, actionData }: Route.ComponentProps)
|
|
| 502 |
</footer>
|
| 503 |
</div>
|
| 504 |
</div>
|
|
|
|
| 505 |
);
|
| 506 |
}
|
|
|
|
| 12 |
import { Alert, AlertDescription } from "~/components/ui/alert";
|
| 13 |
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "~/components/ui/dialog";
|
| 14 |
import { Avatar, AvatarFallback } from "~/components/ui/avatar";
|
| 15 |
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "~/components/ui/tooltip";
|
| 16 |
import { Plus, LogOut, Pencil, Trash2, Activity, Clock, TrendingUp, AlertCircle } from "lucide-react";
|
| 17 |
import { ThemeToggle } from "~/components/theme-toggle";
|
| 18 |
|
|
|
|
| 144 |
export default function Uptime({ loaderData, actionData }: Route.ComponentProps) {
|
| 145 |
const { stats, user } = loaderData;
|
| 146 |
const revalidator = useRevalidator();
|
| 147 |
+
const [showAddDialog, setShowAddDialog] = useState(false);
|
| 148 |
const [editingMonitor, setEditingMonitor] = useState<UptimeStats | null>(null);
|
| 149 |
const [deletingMonitor, setDeletingMonitor] = useState<string | null>(null);
|
| 150 |
|
|
|
|
| 160 |
// Close forms on successful action
|
| 161 |
useEffect(() => {
|
| 162 |
if (actionData?.success) {
|
| 163 |
+
setShowAddDialog(false);
|
| 164 |
setEditingMonitor(null);
|
| 165 |
setDeletingMonitor(null);
|
| 166 |
revalidator.revalidate();
|
|
|
|
| 168 |
}, [actionData, revalidator]);
|
| 169 |
|
| 170 |
return (
|
| 171 |
+
<TooltipProvider>
|
| 172 |
+
<div className="min-h-screen bg-background">
|
| 173 |
+
<div className="container mx-auto px-4 py-8 max-w-7xl">
|
| 174 |
{/* Header */}
|
| 175 |
<header className="mb-8 flex items-center justify-between">
|
| 176 |
<div>
|
|
|
|
| 202 |
|
| 203 |
{/* Add Monitor Button */}
|
| 204 |
<div className="mb-6">
|
| 205 |
+
<Button onClick={() => setShowAddDialog(true)}>
|
| 206 |
<Plus className="h-4 w-4 mr-2" />
|
| 207 |
+
Add New Monitor
|
| 208 |
</Button>
|
| 209 |
</div>
|
| 210 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
{stats.length === 0 ? (
|
| 212 |
<Card>
|
| 213 |
<CardContent className="pt-6 text-center py-12">
|
|
|
|
| 327 |
.slice(-20)
|
| 328 |
.reverse()
|
| 329 |
.map((check, idx: number) => (
|
| 330 |
+
<Tooltip key={idx}>
|
| 331 |
+
<TooltipTrigger asChild>
|
| 332 |
+
<div
|
| 333 |
+
className={`w-3 h-16 rounded cursor-pointer transition-opacity hover:opacity-80 ${
|
| 334 |
+
check.status === "up"
|
| 335 |
+
? "bg-green-500"
|
| 336 |
+
: "bg-red-500"
|
| 337 |
+
}`}
|
| 338 |
+
/>
|
| 339 |
+
</TooltipTrigger>
|
| 340 |
+
<TooltipContent>
|
| 341 |
+
<div className="space-y-1">
|
| 342 |
+
<p className="font-semibold">{check.status === "up" ? "Online" : "Offline"}</p>
|
| 343 |
+
<p>{new Date(check.timestamp).toLocaleString()}</p>
|
| 344 |
+
{check.responseTime && <p>Response: {check.responseTime}ms</p>}
|
| 345 |
+
{check.statusCode && <p>Status Code: {check.statusCode}</p>}
|
| 346 |
+
{check.error && <p className="text-red-300">Error: {check.error}</p>}
|
| 347 |
+
</div>
|
| 348 |
+
</TooltipContent>
|
| 349 |
+
</Tooltip>
|
| 350 |
))}
|
| 351 |
</div>
|
| 352 |
</div>
|
|
|
|
| 358 |
</div>
|
| 359 |
)}
|
| 360 |
|
| 361 |
+
{/* Add Monitor Modal */}
|
| 362 |
+
<Dialog open={showAddDialog} onOpenChange={setShowAddDialog}>
|
| 363 |
+
<DialogContent>
|
| 364 |
+
<DialogHeader>
|
| 365 |
+
<DialogTitle>Add New Monitor</DialogTitle>
|
| 366 |
+
<DialogDescription>
|
| 367 |
+
Start monitoring a new service endpoint
|
| 368 |
+
</DialogDescription>
|
| 369 |
+
</DialogHeader>
|
| 370 |
+
{actionData?.error && (
|
| 371 |
+
<Alert variant="destructive">
|
| 372 |
+
<AlertCircle className="h-4 w-4" />
|
| 373 |
+
<AlertDescription>{actionData.error}</AlertDescription>
|
| 374 |
+
</Alert>
|
| 375 |
+
)}
|
| 376 |
+
<Form method="post" className="space-y-4">
|
| 377 |
+
<input type="hidden" name="intent" value="create" />
|
| 378 |
+
|
| 379 |
+
<div className="space-y-2">
|
| 380 |
+
<Label htmlFor="url">URL to Monitor</Label>
|
| 381 |
+
<Input
|
| 382 |
+
id="url"
|
| 383 |
+
type="url"
|
| 384 |
+
name="url"
|
| 385 |
+
required
|
| 386 |
+
placeholder="https://example.com"
|
| 387 |
+
/>
|
| 388 |
+
</div>
|
| 389 |
+
|
| 390 |
+
<div className="space-y-2">
|
| 391 |
+
<Label htmlFor="interval">Check Interval (seconds)</Label>
|
| 392 |
+
<Input
|
| 393 |
+
id="interval"
|
| 394 |
+
type="number"
|
| 395 |
+
name="interval"
|
| 396 |
+
required
|
| 397 |
+
min="10"
|
| 398 |
+
defaultValue="30"
|
| 399 |
+
placeholder="30"
|
| 400 |
+
/>
|
| 401 |
+
<p className="text-xs text-muted-foreground">
|
| 402 |
+
Minimum 10 seconds
|
| 403 |
+
</p>
|
| 404 |
+
</div>
|
| 405 |
+
|
| 406 |
+
<DialogFooter>
|
| 407 |
+
<Button type="button" variant="outline" onClick={() => setShowAddDialog(false)}>
|
| 408 |
+
Cancel
|
| 409 |
+
</Button>
|
| 410 |
+
<Button type="submit">Create Monitor</Button>
|
| 411 |
+
</DialogFooter>
|
| 412 |
+
</Form>
|
| 413 |
+
</DialogContent>
|
| 414 |
+
</Dialog>
|
| 415 |
+
|
| 416 |
{/* Edit Monitor Modal */}
|
| 417 |
<Dialog open={!!editingMonitor} onOpenChange={() => setEditingMonitor(null)}>
|
| 418 |
<DialogContent>
|
|
|
|
| 507 |
</footer>
|
| 508 |
</div>
|
| 509 |
</div>
|
| 510 |
+
</TooltipProvider>
|
| 511 |
);
|
| 512 |
}
|
package-lock.json
CHANGED
|
@@ -13,6 +13,7 @@
|
|
| 13 |
"@radix-ui/react-dialog": "^1.1.15",
|
| 14 |
"@radix-ui/react-separator": "^1.1.7",
|
| 15 |
"@radix-ui/react-slot": "^1.2.3",
|
|
|
|
| 16 |
"@react-router/node": "^7.9.2",
|
| 17 |
"@react-router/serve": "^7.9.2",
|
| 18 |
"class-variance-authority": "^0.7.1",
|
|
@@ -1573,6 +1574,44 @@
|
|
| 1573 |
"node": ">=18"
|
| 1574 |
}
|
| 1575 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1576 |
"node_modules/@inquirer/ansi": {
|
| 1577 |
"version": "1.0.1",
|
| 1578 |
"resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.1.tgz",
|
|
@@ -3132,6 +3171,29 @@
|
|
| 3132 |
"integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
|
| 3133 |
"license": "MIT"
|
| 3134 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3135 |
"node_modules/@radix-ui/react-avatar": {
|
| 3136 |
"version": "1.1.10",
|
| 3137 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz",
|
|
@@ -3310,6 +3372,38 @@
|
|
| 3310 |
}
|
| 3311 |
}
|
| 3312 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3313 |
"node_modules/@radix-ui/react-portal": {
|
| 3314 |
"version": "1.1.9",
|
| 3315 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
|
|
@@ -3422,6 +3516,40 @@
|
|
| 3422 |
}
|
| 3423 |
}
|
| 3424 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3425 |
"node_modules/@radix-ui/react-use-callback-ref": {
|
| 3426 |
"version": "1.1.1",
|
| 3427 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
|
|
@@ -3525,6 +3653,71 @@
|
|
| 3525 |
}
|
| 3526 |
}
|
| 3527 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3528 |
"node_modules/@react-router/dev": {
|
| 3529 |
"version": "7.9.4",
|
| 3530 |
"resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.9.4.tgz",
|
|
|
|
| 13 |
"@radix-ui/react-dialog": "^1.1.15",
|
| 14 |
"@radix-ui/react-separator": "^1.1.7",
|
| 15 |
"@radix-ui/react-slot": "^1.2.3",
|
| 16 |
+
"@radix-ui/react-tooltip": "^1.2.8",
|
| 17 |
"@react-router/node": "^7.9.2",
|
| 18 |
"@react-router/serve": "^7.9.2",
|
| 19 |
"class-variance-authority": "^0.7.1",
|
|
|
|
| 1574 |
"node": ">=18"
|
| 1575 |
}
|
| 1576 |
},
|
| 1577 |
+
"node_modules/@floating-ui/core": {
|
| 1578 |
+
"version": "1.7.3",
|
| 1579 |
+
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
|
| 1580 |
+
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
|
| 1581 |
+
"license": "MIT",
|
| 1582 |
+
"dependencies": {
|
| 1583 |
+
"@floating-ui/utils": "^0.2.10"
|
| 1584 |
+
}
|
| 1585 |
+
},
|
| 1586 |
+
"node_modules/@floating-ui/dom": {
|
| 1587 |
+
"version": "1.7.4",
|
| 1588 |
+
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
|
| 1589 |
+
"integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
|
| 1590 |
+
"license": "MIT",
|
| 1591 |
+
"dependencies": {
|
| 1592 |
+
"@floating-ui/core": "^1.7.3",
|
| 1593 |
+
"@floating-ui/utils": "^0.2.10"
|
| 1594 |
+
}
|
| 1595 |
+
},
|
| 1596 |
+
"node_modules/@floating-ui/react-dom": {
|
| 1597 |
+
"version": "2.1.6",
|
| 1598 |
+
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
|
| 1599 |
+
"integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
|
| 1600 |
+
"license": "MIT",
|
| 1601 |
+
"dependencies": {
|
| 1602 |
+
"@floating-ui/dom": "^1.7.4"
|
| 1603 |
+
},
|
| 1604 |
+
"peerDependencies": {
|
| 1605 |
+
"react": ">=16.8.0",
|
| 1606 |
+
"react-dom": ">=16.8.0"
|
| 1607 |
+
}
|
| 1608 |
+
},
|
| 1609 |
+
"node_modules/@floating-ui/utils": {
|
| 1610 |
+
"version": "0.2.10",
|
| 1611 |
+
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
|
| 1612 |
+
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
|
| 1613 |
+
"license": "MIT"
|
| 1614 |
+
},
|
| 1615 |
"node_modules/@inquirer/ansi": {
|
| 1616 |
"version": "1.0.1",
|
| 1617 |
"resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.1.tgz",
|
|
|
|
| 3171 |
"integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
|
| 3172 |
"license": "MIT"
|
| 3173 |
},
|
| 3174 |
+
"node_modules/@radix-ui/react-arrow": {
|
| 3175 |
+
"version": "1.1.7",
|
| 3176 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
|
| 3177 |
+
"integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
|
| 3178 |
+
"license": "MIT",
|
| 3179 |
+
"dependencies": {
|
| 3180 |
+
"@radix-ui/react-primitive": "2.1.3"
|
| 3181 |
+
},
|
| 3182 |
+
"peerDependencies": {
|
| 3183 |
+
"@types/react": "*",
|
| 3184 |
+
"@types/react-dom": "*",
|
| 3185 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 3186 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 3187 |
+
},
|
| 3188 |
+
"peerDependenciesMeta": {
|
| 3189 |
+
"@types/react": {
|
| 3190 |
+
"optional": true
|
| 3191 |
+
},
|
| 3192 |
+
"@types/react-dom": {
|
| 3193 |
+
"optional": true
|
| 3194 |
+
}
|
| 3195 |
+
}
|
| 3196 |
+
},
|
| 3197 |
"node_modules/@radix-ui/react-avatar": {
|
| 3198 |
"version": "1.1.10",
|
| 3199 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz",
|
|
|
|
| 3372 |
}
|
| 3373 |
}
|
| 3374 |
},
|
| 3375 |
+
"node_modules/@radix-ui/react-popper": {
|
| 3376 |
+
"version": "1.2.8",
|
| 3377 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
|
| 3378 |
+
"integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
|
| 3379 |
+
"license": "MIT",
|
| 3380 |
+
"dependencies": {
|
| 3381 |
+
"@floating-ui/react-dom": "^2.0.0",
|
| 3382 |
+
"@radix-ui/react-arrow": "1.1.7",
|
| 3383 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 3384 |
+
"@radix-ui/react-context": "1.1.2",
|
| 3385 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 3386 |
+
"@radix-ui/react-use-callback-ref": "1.1.1",
|
| 3387 |
+
"@radix-ui/react-use-layout-effect": "1.1.1",
|
| 3388 |
+
"@radix-ui/react-use-rect": "1.1.1",
|
| 3389 |
+
"@radix-ui/react-use-size": "1.1.1",
|
| 3390 |
+
"@radix-ui/rect": "1.1.1"
|
| 3391 |
+
},
|
| 3392 |
+
"peerDependencies": {
|
| 3393 |
+
"@types/react": "*",
|
| 3394 |
+
"@types/react-dom": "*",
|
| 3395 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 3396 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 3397 |
+
},
|
| 3398 |
+
"peerDependenciesMeta": {
|
| 3399 |
+
"@types/react": {
|
| 3400 |
+
"optional": true
|
| 3401 |
+
},
|
| 3402 |
+
"@types/react-dom": {
|
| 3403 |
+
"optional": true
|
| 3404 |
+
}
|
| 3405 |
+
}
|
| 3406 |
+
},
|
| 3407 |
"node_modules/@radix-ui/react-portal": {
|
| 3408 |
"version": "1.1.9",
|
| 3409 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
|
|
|
|
| 3516 |
}
|
| 3517 |
}
|
| 3518 |
},
|
| 3519 |
+
"node_modules/@radix-ui/react-tooltip": {
|
| 3520 |
+
"version": "1.2.8",
|
| 3521 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
|
| 3522 |
+
"integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
|
| 3523 |
+
"license": "MIT",
|
| 3524 |
+
"dependencies": {
|
| 3525 |
+
"@radix-ui/primitive": "1.1.3",
|
| 3526 |
+
"@radix-ui/react-compose-refs": "1.1.2",
|
| 3527 |
+
"@radix-ui/react-context": "1.1.2",
|
| 3528 |
+
"@radix-ui/react-dismissable-layer": "1.1.11",
|
| 3529 |
+
"@radix-ui/react-id": "1.1.1",
|
| 3530 |
+
"@radix-ui/react-popper": "1.2.8",
|
| 3531 |
+
"@radix-ui/react-portal": "1.1.9",
|
| 3532 |
+
"@radix-ui/react-presence": "1.1.5",
|
| 3533 |
+
"@radix-ui/react-primitive": "2.1.3",
|
| 3534 |
+
"@radix-ui/react-slot": "1.2.3",
|
| 3535 |
+
"@radix-ui/react-use-controllable-state": "1.2.2",
|
| 3536 |
+
"@radix-ui/react-visually-hidden": "1.2.3"
|
| 3537 |
+
},
|
| 3538 |
+
"peerDependencies": {
|
| 3539 |
+
"@types/react": "*",
|
| 3540 |
+
"@types/react-dom": "*",
|
| 3541 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 3542 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 3543 |
+
},
|
| 3544 |
+
"peerDependenciesMeta": {
|
| 3545 |
+
"@types/react": {
|
| 3546 |
+
"optional": true
|
| 3547 |
+
},
|
| 3548 |
+
"@types/react-dom": {
|
| 3549 |
+
"optional": true
|
| 3550 |
+
}
|
| 3551 |
+
}
|
| 3552 |
+
},
|
| 3553 |
"node_modules/@radix-ui/react-use-callback-ref": {
|
| 3554 |
"version": "1.1.1",
|
| 3555 |
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
|
|
|
|
| 3653 |
}
|
| 3654 |
}
|
| 3655 |
},
|
| 3656 |
+
"node_modules/@radix-ui/react-use-rect": {
|
| 3657 |
+
"version": "1.1.1",
|
| 3658 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
|
| 3659 |
+
"integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
|
| 3660 |
+
"license": "MIT",
|
| 3661 |
+
"dependencies": {
|
| 3662 |
+
"@radix-ui/rect": "1.1.1"
|
| 3663 |
+
},
|
| 3664 |
+
"peerDependencies": {
|
| 3665 |
+
"@types/react": "*",
|
| 3666 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 3667 |
+
},
|
| 3668 |
+
"peerDependenciesMeta": {
|
| 3669 |
+
"@types/react": {
|
| 3670 |
+
"optional": true
|
| 3671 |
+
}
|
| 3672 |
+
}
|
| 3673 |
+
},
|
| 3674 |
+
"node_modules/@radix-ui/react-use-size": {
|
| 3675 |
+
"version": "1.1.1",
|
| 3676 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
|
| 3677 |
+
"integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
|
| 3678 |
+
"license": "MIT",
|
| 3679 |
+
"dependencies": {
|
| 3680 |
+
"@radix-ui/react-use-layout-effect": "1.1.1"
|
| 3681 |
+
},
|
| 3682 |
+
"peerDependencies": {
|
| 3683 |
+
"@types/react": "*",
|
| 3684 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 3685 |
+
},
|
| 3686 |
+
"peerDependenciesMeta": {
|
| 3687 |
+
"@types/react": {
|
| 3688 |
+
"optional": true
|
| 3689 |
+
}
|
| 3690 |
+
}
|
| 3691 |
+
},
|
| 3692 |
+
"node_modules/@radix-ui/react-visually-hidden": {
|
| 3693 |
+
"version": "1.2.3",
|
| 3694 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
|
| 3695 |
+
"integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
|
| 3696 |
+
"license": "MIT",
|
| 3697 |
+
"dependencies": {
|
| 3698 |
+
"@radix-ui/react-primitive": "2.1.3"
|
| 3699 |
+
},
|
| 3700 |
+
"peerDependencies": {
|
| 3701 |
+
"@types/react": "*",
|
| 3702 |
+
"@types/react-dom": "*",
|
| 3703 |
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
| 3704 |
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
| 3705 |
+
},
|
| 3706 |
+
"peerDependenciesMeta": {
|
| 3707 |
+
"@types/react": {
|
| 3708 |
+
"optional": true
|
| 3709 |
+
},
|
| 3710 |
+
"@types/react-dom": {
|
| 3711 |
+
"optional": true
|
| 3712 |
+
}
|
| 3713 |
+
}
|
| 3714 |
+
},
|
| 3715 |
+
"node_modules/@radix-ui/rect": {
|
| 3716 |
+
"version": "1.1.1",
|
| 3717 |
+
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
|
| 3718 |
+
"integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
|
| 3719 |
+
"license": "MIT"
|
| 3720 |
+
},
|
| 3721 |
"node_modules/@react-router/dev": {
|
| 3722 |
"version": "7.9.4",
|
| 3723 |
"resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.9.4.tgz",
|
package.json
CHANGED
|
@@ -16,6 +16,7 @@
|
|
| 16 |
"@radix-ui/react-dialog": "^1.1.15",
|
| 17 |
"@radix-ui/react-separator": "^1.1.7",
|
| 18 |
"@radix-ui/react-slot": "^1.2.3",
|
|
|
|
| 19 |
"@react-router/node": "^7.9.2",
|
| 20 |
"@react-router/serve": "^7.9.2",
|
| 21 |
"class-variance-authority": "^0.7.1",
|
|
|
|
| 16 |
"@radix-ui/react-dialog": "^1.1.15",
|
| 17 |
"@radix-ui/react-separator": "^1.1.7",
|
| 18 |
"@radix-ui/react-slot": "^1.2.3",
|
| 19 |
+
"@radix-ui/react-tooltip": "^1.2.8",
|
| 20 |
"@react-router/node": "^7.9.2",
|
| 21 |
"@react-router/serve": "^7.9.2",
|
| 22 |
"class-variance-authority": "^0.7.1",
|