refactor: clean up code formatting and improve consistency across multiple components
Deploy to VPS / deploy (push) Failing after 1m59s

This commit is contained in:
asepharyana
2026-07-26 15:39:41 +07:00
parent c2502a0e5f
commit 300512b2cb
12 changed files with 47 additions and 108 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.5/schema.json",
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
@@ -30,7 +30,6 @@
"linter": {
"enabled": true,
"rules": {
"preset": "recommended",
"style": {
"noNonNullAssertion": "warn",
"useNodejsImportProtocol": "warn"
@@ -41,6 +40,7 @@
"noArrayIndexKey": "warn"
},
"a11y": {
"useSemanticElements": "off",
"useButtonType": "off",
"noAutofocus": "off"
},
@@ -111,10 +111,8 @@ export default function AnalysisPage() {
variant="outline"
className={cn(
"text-[10px] px-1.5 py-0 h-4",
msg.ai_status === "clean" &&
"text-green-500",
msg.ai_status === "flagged" &&
"text-red-500",
msg.ai_status === "clean" && "text-green-500",
msg.ai_status === "flagged" && "text-red-500",
)}
>
{msg.ai_status}
@@ -127,9 +125,8 @@ export default function AnalysisPage() {
{msg.ai_moderation_flags &&
msg.ai_moderation_flags !== "[]" && (
<div className="flex flex-wrap gap-1">
{safeParseJsonArray(
msg.ai_moderation_flags,
).map((flag) => (
{safeParseJsonArray(msg.ai_moderation_flags).map(
(flag) => (
<Badge
key={flag}
variant="destructive"
@@ -137,7 +134,8 @@ export default function AnalysisPage() {
>
{flag}
</Badge>
))}
),
)}
</div>
)}
@@ -15,7 +15,7 @@ import {
} from "lucide-react";
import Image from "next/image";
import { useCallback, useEffect, useState } from "react";
import { GuildSelector } from "@/components/shared/guild-selector";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
@@ -23,7 +23,6 @@ import { Input } from "@/components/ui/input";
import { Progress } from "@/components/ui/progress";
import { Skeleton } from "@/components/ui/skeleton";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { GuildSelector } from "@/components/shared/guild-selector";
import { dashboardApi } from "@/lib/api";
import { formatNumber } from "@/lib/format";
import type {
@@ -189,11 +188,7 @@ function StatsView() {
value={stats.total_messages}
icon={Hash}
/>
<StatCard
label="Today"
value={stats.today_messages}
icon={Clock}
/>
<StatCard label="Today" value={stats.today_messages} icon={Clock} />
<StatCard label="Users" value={stats.total_users} icon={Users} />
<StatCard
label="Active 24h"
@@ -239,19 +234,15 @@ function StatsView() {
</p>
) : (
<div className="space-y-2">
{stats.top_channels.map((ch, i) => {
{stats.top_channels.map((ch, _i) => {
const maxCount = stats.top_channels[0].message_count;
const pct =
maxCount > 0
? (ch.message_count / maxCount) * 100
: 0;
maxCount > 0 ? (ch.message_count / maxCount) * 100 : 0;
return (
<div key={ch.channel_id} className="space-y-1">
<div className="flex items-center justify-between text-sm">
<span className="truncate font-medium">
#
{ch.channel_name ??
ch.channel_id.slice(0, 8)}
#{ch.channel_name ?? ch.channel_id.slice(0, 8)}
</span>
<span className="text-muted-foreground tabular-nums">
{formatNumber(ch.message_count)}
@@ -279,9 +270,7 @@ function StatsView() {
<div className="text-2xl font-bold tabular-nums">
{stats.moderation_overview.pending}
</div>
<div className="text-xs text-muted-foreground">
Pending
</div>
<div className="text-xs text-muted-foreground">Pending</div>
</div>
<div className="rounded-lg bg-yellow-500/10 p-3 text-center space-y-1.5">
<div className="text-2xl font-bold tabular-nums text-yellow-500">
@@ -5,8 +5,8 @@ import { Suspense } from "react";
import { Header } from "@/components/layout/header";
import { MobileTabBar } from "@/components/layout/mobile-tab-bar";
import { Sidebar } from "@/components/layout/sidebar";
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
import { MascotChatbot } from "@/components/mascot/mascot-chatbot";
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
import { WsProvider } from "@/lib/ws/context";
function LoadingFallback() {
@@ -1,13 +1,6 @@
"use client";
import {
Disc3,
Music,
Play,
SkipForward,
Square,
Volume2,
} from "lucide-react";
import { Disc3, Music, Play, SkipForward, Square, Volume2 } from "lucide-react";
import Image from "next/image";
import { useCallback, useEffect, useState } from "react";
@@ -12,7 +12,7 @@ import {
} from "lucide-react";
import Image from "next/image";
import { useCallback, useEffect, useState } from "react";
import { GuildSelector } from "@/components/shared/guild-selector";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
@@ -35,7 +35,6 @@ import {
} from "@/components/ui/select";
import { Skeleton } from "@/components/ui/skeleton";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { GuildSelector } from "@/components/shared/guild-selector";
import { messagesApi, voiceApi } from "@/lib/api";
import { formatBytes, safeParseJsonArray } from "@/lib/format";
import type { AttachmentRecord, Channel, MessageRecord } from "@/lib/types";
@@ -244,9 +243,7 @@ export default function MessagesPage() {
<GuildSelector value={guildId} onChange={setGuildId} />
<div className="flex flex-col items-center justify-center py-20 text-center">
<AlertCircle className="size-10 text-destructive mb-3" />
<p className="text-sm text-muted-foreground mb-4 max-w-sm">
{error}
</p>
<p className="text-sm text-muted-foreground mb-4 max-w-sm">{error}</p>
<Button variant="outline" onClick={fetchMessages}>
<RefreshCw className="size-4 mr-2" />
Retry
@@ -490,9 +487,7 @@ export default function MessagesPage() {
{detailMessage.username}
</span>
<span className="text-xs text-muted-foreground">
{new Date(
detailMessage.created_at,
).toLocaleString()}
{new Date(detailMessage.created_at).toLocaleString()}
</span>
{detailMessage.type === "deleted" && (
<Badge variant="destructive" className="text-[10px]">
@@ -787,13 +782,9 @@ function MessageCard({
</p>
)}
{msg.ai_confidence !== undefined &&
msg.ai_confidence !== null && (
{msg.ai_confidence !== undefined && msg.ai_confidence !== null && (
<div className="flex items-center gap-2 max-w-40">
<Progress
value={msg.ai_confidence * 100}
className="h-1.5"
/>
<Progress value={msg.ai_confidence * 100} className="h-1.5" />
<span className="text-[11px] text-muted-foreground tabular-nums shrink-0">
{(msg.ai_confidence * 100).toFixed(0)}%
</span>
@@ -91,9 +91,7 @@ export default function RecordingsPage() {
{rec.username}
</p>
<p className="text-xs text-muted-foreground">
{rec.channel_name ??
rec.channel_id ??
"Unknown channel"}
{rec.channel_name ?? rec.channel_id ?? "Unknown channel"}
{" — "}
{new Date(rec.created_at).toLocaleString()}
</p>
@@ -108,9 +106,7 @@ export default function RecordingsPage() {
<Button
variant="ghost"
size="icon"
onClick={() =>
window.open(rec.download_url!, "_blank")
}
onClick={() => window.open(rec.download_url, "_blank")}
>
<Download className="size-4" />
</Button>
@@ -1,12 +1,6 @@
"use client";
import {
Moon,
Server,
Shield,
Sun,
Wifi,
} from "lucide-react";
import { Moon, Server, Shield, Sun, Wifi } from "lucide-react";
import { useEffect, useState } from "react";
import { Badge } from "@/components/ui/badge";
@@ -85,9 +79,7 @@ export default function SettingsPage() {
variant={statusConfig.variant}
className="gap-1.5 px-2.5 py-1"
>
<span
className={cn("size-1.5 rounded-full", statusConfig.dot)}
/>
<span className={cn("size-1.5 rounded-full", statusConfig.dot)} />
{statusConfig.label}
</Badge>
</div>
@@ -159,9 +151,7 @@ export default function SettingsPage() {
<Separator />
<ConfigRow
label="Auto-Delete Flagged"
value={
config.autoDeleteFlaggedEnabled ? "Enabled" : "Disabled"
}
value={config.autoDeleteFlaggedEnabled ? "Enabled" : "Disabled"}
/>
</div>
) : (
@@ -197,13 +187,7 @@ export default function SettingsPage() {
);
}
function ConfigRow({
label,
value,
}: {
label: string;
value: string;
}) {
function ConfigRow({ label, value }: { label: string; value: string }) {
return (
<div className="flex items-center justify-between py-1">
<span className="text-muted-foreground">{label}</span>
@@ -31,9 +31,7 @@ export default function VoicePage() {
const [voiceStatus, setVoiceStatus] = useState<VoiceStatus | null>(null);
const [speakers, setSpeakers] = useState<ActiveSpeaker[]>([]);
const [guilds, setGuilds] = useState<
Array<{ id: string; name: string }>
>([]);
const [guilds, setGuilds] = useState<Array<{ id: string; name: string }>>([]);
const [voiceChannels, setVoiceChannels] = useState<
Array<{ id: string; name: string }>
>([]);
@@ -74,9 +72,7 @@ export default function VoicePage() {
const unsubSpeaker = ws.on("voice_active_user", (user) => {
const speaker = user as ActiveSpeaker;
setSpeakers((prev) => {
const existing = prev.findIndex(
(s) => s.userId === speaker.userId,
);
const existing = prev.findIndex((s) => s.userId === speaker.userId);
if (existing >= 0) {
const next = [...prev];
next[existing] = speaker;
@@ -224,9 +220,7 @@ export default function VoicePage() {
) : (
<Button
onClick={handleConnect}
disabled={
voiceLoading || !selectedGuild || !selectedChannel
}
disabled={voiceLoading || !selectedGuild || !selectedChannel}
>
{voiceLoading ? (
<Loader2 className="size-4 animate-spin mr-1.5" />
@@ -286,9 +280,7 @@ export default function VoicePage() {
setMicActive(checked);
try {
await voiceApi.sendCommand(
checked
? "voice:transmit:start"
: "voice:transmit:stop",
checked ? "voice:transmit:start" : "voice:transmit:stop",
);
} catch {
setMicActive(!checked);
@@ -45,9 +45,7 @@ export function GuildSelector({
.getGuilds()
.then(setGuilds)
.catch((err) =>
setError(
err instanceof Error ? err.message : "Failed to load guilds",
),
setError(err instanceof Error ? err.message : "Failed to load guilds"),
)
.finally(() => setLoading(false));
}, []);
+1 -3
View File
@@ -17,9 +17,7 @@ export function formatBytes(bytes: number): string {
/**
* Safely parse a JSON string into an array.
*/
export function safeParseJsonArray(
value: string | null | undefined,
): string[] {
export function safeParseJsonArray(value: string | null | undefined): string[] {
if (!value) return [];
try {
const parsed = JSON.parse(value);
+1 -1
View File
@@ -2,11 +2,11 @@ import {
BarChart3,
Headphones,
LayoutDashboard,
type LucideIcon,
MessageSquare,
Mic,
Music,
Search,
type LucideIcon,
} from "lucide-react";
export interface NavItem {