chore(lint): biome cleanup across services — format, sort imports, drop unused

- discord-gateway: 74 lint errors -> 0 (format, import sorting, unused
  imports/vars, dead breath var)
- backend: format + sort imports (11 warnings left: noExplicitAny)
- frontend: remove unused imports, drop dead breathing var, fix
  useExhaustiveDependencies (scroll keyed on messages), a11y biome-ignore
  for drag surface + stopPropagation container (mouse-only gestures)
- remaining warnings are false positives: index keys on static lists,
  <img> in static export (next/image unsupported), noExplicitAny

tsc --noEmit clean on all 3 services; vitest green (60+36).
This commit is contained in:
asepharyana
2026-08-01 22:09:02 +07:00
parent 2357421841
commit 6293d588bc
123 changed files with 466 additions and 308 deletions
@@ -1,7 +1,7 @@
"use client";
import { useRef, useEffect } from "react";
import { Send } from "lucide-react";
import { useEffect, useRef } from "react";
import { useChatbot } from "./chatbot-context";
interface ChatPanelProps {
@@ -15,11 +15,12 @@ export function ChatPanel({ inputRef: externalInputRef }: ChatPanelProps) {
const inputRef = externalInputRef ?? internalInputRef;
// Auto-scroll to bottom on new messages
// biome-ignore lint/correctness/useExhaustiveDependencies: re-run on message arrival; scroll is a visual effect keyed on new content
useEffect(() => {
if (listRef.current) {
listRef.current.scrollTop = listRef.current.scrollHeight;
}
}, [messages, isTyping]);
}, [messages]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
@@ -35,7 +36,9 @@ export function ChatPanel({ inputRef: externalInputRef }: ChatPanelProps) {
<div ref={listRef} className="flex-1 overflow-y-auto px-2 py-1 space-y-1">
{messages.length === 0 && (
<div className="flex items-center justify-center h-full">
<p className="text-[10px] text-text-secondary/40">Ask chatbot anything</p>
<p className="text-[10px] text-text-secondary/40">
Ask chatbot anything
</p>
</div>
)}
{messages.slice(-8).map((msg, i) => (
@@ -58,9 +61,18 @@ export function ChatPanel({ inputRef: externalInputRef }: ChatPanelProps) {
<div className="flex justify-start">
<div className="glass rounded-lg px-2 py-1">
<span className="inline-flex gap-0.5">
<span className="size-1 rounded-full bg-text-secondary animate-bounce" style={{ animationDelay: "0ms" }} />
<span className="size-1 rounded-full bg-text-secondary animate-bounce" style={{ animationDelay: "150ms" }} />
<span className="size-1 rounded-full bg-text-secondary animate-bounce" style={{ animationDelay: "300ms" }} />
<span
className="size-1 rounded-full bg-text-secondary animate-bounce"
style={{ animationDelay: "0ms" }}
/>
<span
className="size-1 rounded-full bg-text-secondary animate-bounce"
style={{ animationDelay: "150ms" }}
/>
<span
className="size-1 rounded-full bg-text-secondary animate-bounce"
style={{ animationDelay: "300ms" }}
/>
</span>
</div>
</div>
@@ -68,7 +80,10 @@ export function ChatPanel({ inputRef: externalInputRef }: ChatPanelProps) {
</div>
{/* Input bar */}
<form onSubmit={handleSubmit} className="flex items-center gap-1 px-2 py-1.5 border-t border-glass-border shrink-0">
<form
onSubmit={handleSubmit}
className="flex items-center gap-1 px-2 py-1.5 border-t border-glass-border shrink-0"
>
<input
ref={inputRef}
type="text"
@@ -33,7 +33,14 @@ export function ChatbotCanvas() {
ctx.clearRect(0, 0, w, h);
// Background circle
const gradient = ctx.createRadialGradient(w / 2, h / 2 - 10, 10, w / 2, h / 2, 80);
const gradient = ctx.createRadialGradient(
w / 2,
h / 2 - 10,
10,
w / 2,
h / 2,
80,
);
gradient.addColorStop(0, "oklch(0.62 0.17 215 / 0.8)");
gradient.addColorStop(0.6, "oklch(0.12 0.02 245 / 0.9)");
gradient.addColorStop(1, "oklch(0.07 0.015 250 / 1)");
@@ -112,11 +119,6 @@ export function ChatbotCanvas() {
ctx.arc(w / 2, 75, 6, 0.1, Math.PI - 0.1);
ctx.stroke();
}
// Breathing animation — subtle canvas shift
const breath = Math.sin(Date.now() / 1000) * 1.5;
// Applied via CSS transform on container instead
}, [expression]);
return (
@@ -1,10 +1,10 @@
"use client";
import { useRef, useState, useCallback, useEffect } from "react";
import { Bot, MessageCircle, Minimize2 } from "lucide-react";
import { useChatbot } from "./chatbot-context";
import { ChatbotCanvas } from "./chatbot-canvas";
import { useCallback, useEffect, useRef, useState } from "react";
import { ChatPanel } from "./chat-panel";
import { ChatbotCanvas } from "./chatbot-canvas";
import { useChatbot } from "./chatbot-context";
export function ChatbotContainer() {
const { minimized, setMinimized, chatOpen, setChatOpen } = useChatbot();
@@ -13,15 +13,21 @@ export function ChatbotContainer() {
const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
const inputRef = useRef<HTMLInputElement>(null);
const handleMouseDown = useCallback((e: React.MouseEvent) => {
setDragging(true);
setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });
}, [position]);
const handleMouseDown = useCallback(
(e: React.MouseEvent) => {
setDragging(true);
setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });
},
[position],
);
const handleMouseMove = useCallback((e: React.MouseEvent) => {
if (!dragging) return;
setPosition({ x: e.clientX - dragStart.x, y: e.clientY - dragStart.y });
}, [dragging, dragStart]);
const handleMouseMove = useCallback(
(e: React.MouseEvent) => {
if (!dragging) return;
setPosition({ x: e.clientX - dragStart.x, y: e.clientY - dragStart.y });
},
[dragging, dragStart],
);
const handleMouseUp = useCallback(() => setDragging(false), []);
@@ -35,6 +41,7 @@ export function ChatbotContainer() {
}, [chatOpen]);
return (
// biome-ignore lint/a11y/noStaticElementInteractions: drag container — mouse-move gesture surface, not keyboard-interactive content
<div
className="fixed bottom-4 right-4 z-40 select-none"
style={{ transform: `translate(${position.x}px, ${position.y}px)` }}
@@ -62,6 +69,7 @@ export function ChatbotContainer() {
) : (
<>
{/* Drag handle + controls */}
{/* biome-ignore lint/a11y/noStaticElementInteractions: drag handle — mouse-only gesture, keyboard users use the buttons in this header */}
<div
className="flex items-center justify-between px-3 py-1.5 border-b border-glass-border cursor-grab active:cursor-grabbing"
onMouseDown={handleMouseDown}
@@ -10,7 +10,6 @@ import {
useState,
} from "react";
import { chatbotApi } from "@/lib/api";
import type { ChatbotHistoryRow } from "@/lib/types";
export type ChatbotExpression =
| "idle"
@@ -1,4 +1,4 @@
export { ChatbotProvider, useChatbot } from "./chatbot-context";
export { ChatbotContainer } from "./chatbot-container";
export { ChatbotCanvas } from "./chatbot-canvas";
export { ChatPanel } from "./chat-panel";
export { ChatbotCanvas } from "./chatbot-canvas";
export { ChatbotContainer } from "./chatbot-container";
export { ChatbotProvider, useChatbot } from "./chatbot-context";