From 49d020c312f4fb1abe7b65c5e491b6c180137724 Mon Sep 17 00:00:00 2001 From: Rill Date: Sun, 22 Sep 2024 01:21:12 +0700 Subject: [PATCH] Feat: add healthcheck button --- bun.lockb | Bin 259005 -> 261502 bytes package.json | 1 + src/components/ui/alert.tsx | 59 ++++++++ src/components/ui/dropdown-menu.tsx | 198 +++++++++++++++++++++++++ src/components/widgets/Client.tsx | 75 +++++----- src/components/widgets/HealthCheck.tsx | 69 +++++++++ src/components/widgets/ModeToggle.tsx | 52 +++++++ src/pages/index.astro | 7 + 8 files changed, 427 insertions(+), 34 deletions(-) create mode 100644 src/components/ui/alert.tsx create mode 100644 src/components/ui/dropdown-menu.tsx create mode 100644 src/components/widgets/HealthCheck.tsx create mode 100644 src/components/widgets/ModeToggle.tsx diff --git a/bun.lockb b/bun.lockb index 569a8da375388b940c63005f92995b20a643949b..cdb349e99bef3dec006f2b14e71342c3e6108f61 100755 GIT binary patch delta 41460 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 delta 40956 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 qoR$Z&Fl(jl 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 VG(PK9M4Y_j)qY#K&%I(@{|jx&Ff0H7 diff --git a/package.json b/package.json index 3a72679..49d2522 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-slot": "^1.1.0", diff --git a/src/components/ui/alert.tsx b/src/components/ui/alert.tsx new file mode 100644 index 0000000..41fa7e0 --- /dev/null +++ b/src/components/ui/alert.tsx @@ -0,0 +1,59 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const alertVariants = cva( + "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)) +Alert.displayName = "Alert" + +const AlertTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertTitle.displayName = "AlertTitle" + +const AlertDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = "AlertDescription" + +export { Alert, AlertTitle, AlertDescription } diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..769ff7a --- /dev/null +++ b/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,198 @@ +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/src/components/widgets/Client.tsx b/src/components/widgets/Client.tsx index 2d1a877..d5f3b7d 100644 --- a/src/components/widgets/Client.tsx +++ b/src/components/widgets/Client.tsx @@ -11,7 +11,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover import { Input } from "@/components/ui/input.tsx"; import { SearchIcon } from "lucide-react"; import timeRangesData from '@/lib/time.json'; -import {cn} from "@/lib/utils.ts"; +import { cn } from "@/lib/utils.ts"; interface Schedule { dosen: string; @@ -149,7 +149,12 @@ const Client = () => {

{result.hari}

- Jam{result.jam} + + Jam + + {result.jam} + +

{timeRange}

@@ -193,41 +198,43 @@ const Client = () => { ); return ( -
- - - - Smrv2 - - Sebuah website untuk mencari jadwal kuliah, info ruangan, dll berdasarkan simeru. - - - - -
-
- - -
-
- - +
+
+ + + + Smrv2 + + Sebuah website untuk mencari jadwal kuliah, info ruangan, dll berdasarkan simeru. + + + + +
+
+ + +
+
+ + +
+
- -
- - + + +
{(state.isLoading || state.results || state.errorMessage) && ( -
+
-

Search Results

+

Search Results

{state.errorMessage ? ( <> ) : ( @@ -266,7 +273,7 @@ const Client = () => { )}
)} -
+ ); }; diff --git a/src/components/widgets/HealthCheck.tsx b/src/components/widgets/HealthCheck.tsx new file mode 100644 index 0000000..ba75a0c --- /dev/null +++ b/src/components/widgets/HealthCheck.tsx @@ -0,0 +1,69 @@ +import React, { useState, useEffect } from 'react'; +import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; +import { Activity, CheckCircle2, XCircle } from 'lucide-react'; +import { fetchData } from "@/lib/fetch.ts"; +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover.tsx"; +import {Button} from "@/components/ui/button.tsx"; + +interface HealthStatus { + livez: boolean; + readyz: boolean; +} + +const HealthCheck: React.FC = () => { + const [health, setHealth] = useState({ livez: false, readyz: false }); + + const checkEndpoint = async (endpoint: string): Promise => { + try { + const response = await fetch(`${import.meta.env.PUBLIC_API}${endpoint}`); + return response.status === 200; + } catch (error) { + console.error(`Health check failed for ${endpoint}:`, error); + return false; + } + }; + + const checkHealth = async () => { + const livezStatus = await checkEndpoint('/livez'); + const readyzStatus = await checkEndpoint('/readyz'); + + setHealth({ + livez: livezStatus, + readyz: readyzStatus + }); + }; + + useEffect(() => { + checkHealth(); + const interval = setInterval(checkHealth, 60*1000); + return () => clearInterval(interval); + }, []); + + return ( + + + + + +
+
+ {health.livez ? : } + Server Status +
+
+ {health.readyz ? : } + Apps Status +
+
+
+
+ ); +}; + +export default HealthCheck; diff --git a/src/components/widgets/ModeToggle.tsx b/src/components/widgets/ModeToggle.tsx new file mode 100644 index 0000000..d760a04 --- /dev/null +++ b/src/components/widgets/ModeToggle.tsx @@ -0,0 +1,52 @@ +import * as React from "react" +import { Moon, Sun } from "lucide-react" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" + +export function ModeToggle() { + const [theme, setThemeState] = React.useState< + "theme-light" | "dark" | "system" + >("theme-light") + + React.useEffect(() => { + const isDarkMode = document.documentElement.classList.contains("dark") + setThemeState(isDarkMode ? "dark" : "theme-light") + }, []) + + React.useEffect(() => { + const isDark = + theme === "dark" || + (theme === "system" && + window.matchMedia("(prefers-color-scheme: dark)").matches) + document.documentElement.classList[isDark ? "add" : "remove"]("dark") + }, [theme]) + + return ( + + + + + + setThemeState("theme-light")}> + Light + + setThemeState("dark")}> + Dark + + setThemeState("system")}> + System + + + + ) +} diff --git a/src/pages/index.astro b/src/pages/index.astro index 7cbd11d..8072d23 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -5,6 +5,9 @@ import Footer from '@/components/widgets/Footer.astro'; import ScrollUp from '@/components/widgets/ScrollUp'; import { Toaster } from "@/components/ui/toaster" import Client from "@/components/widgets/Client"; +import HealthCheck from "../components/widgets/HealthCheck"; +import {ModeToggle} from "../components/widgets/ModeToggle"; +import React from "react"; --- +
+ + +