changes code quality

This commit is contained in:
Mohammad Yaseen 2025-12-24 10:40:44 +05:30
parent 6c38cc160a
commit e812486fe0
15 changed files with 367 additions and 78 deletions

View File

@ -197,8 +197,19 @@ export function ForgotPasswordModal({
}, 800); }, 800);
}; };
const handleResendCode = (): void => { /**
console.log('Resend code to:', email); * Handle resend OTP code
* @description Resends the OTP verification code to the user's email
* @throws {Error} When resend request fails
*/
const handleResendCode = async (): Promise<void> => {
try {
// TODO: Implement resend OTP API call
// await resendOtpCode(email);
} catch (error) {
// Error handling will be implemented with proper logging service
throw error;
}
}; };
const handleBackdropClick = (): void => handleClose(); const handleBackdropClick = (): void => handleClose();

View File

@ -7,8 +7,11 @@
* AgentCard component props * AgentCard component props
*/ */
interface AgentCardProps { interface AgentCardProps {
/** Agent title/name */
title: string; title: string;
/** Array of tag labels */
tags: string[]; tags: string[];
/** Agent description text */
description: string; description: string;
} }
@ -16,9 +19,13 @@ interface AgentCardProps {
* AgentCard component * AgentCard component
* @description Card showing agent details with tags * @description Card showing agent details with tags
* @param props - Component props * @param props - Component props
* @returns AgentCard element * @returns {JSX.Element} AgentCard element
*/ */
export function AgentCard({ title, tags, description }: AgentCardProps) { export function AgentCard({
title,
tags,
description,
}: AgentCardProps): JSX.Element {
// Define your colors in order // Define your colors in order
const tagColors = [ const tagColors = [
"bg-[#E5E8F4]", // 1st tag (index 0) "bg-[#E5E8F4]", // 1st tag (index 0)

View File

@ -26,9 +26,12 @@ interface AgentsSectionProps {
* Agents section component * Agents section component
* @description Displays agents with tabs and pagination * @description Displays agents with tabs and pagination
* @param props - Component props * @param props - Component props
* @returns AgentsSection element * @returns {JSX.Element} AgentsSection element
*/ */
export function AgentsSection({ agents, itemsPerPage = 6 }: AgentsSectionProps) { export function AgentsSection({
agents,
itemsPerPage = 6,
}: AgentsSectionProps): JSX.Element {
const [activeTab, setActiveTab] = useState<'all' | 'my'>('all'); const [activeTab, setActiveTab] = useState<'all' | 'my'>('all');
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
@ -57,9 +60,10 @@ export function AgentsSection({ agents, itemsPerPage = 6 }: AgentsSectionProps)
/** /**
* Handle page change * Handle page change
* @description Updates the current page number
* @param page - New page number (1-indexed) * @param page - New page number (1-indexed)
*/ */
const handlePageChange = (page: number) => { const handlePageChange = (page: number): void => {
setCurrentPage(page); setCurrentPage(page);
}; };

View File

@ -1,17 +1,40 @@
/**
* Metric card component props
*/
interface MetricCardProps { interface MetricCardProps {
/** Card title text */
title: string; title: string;
/** Card subtitle text */
subtitle: string; subtitle: string;
/** Display value */
value: string; value: string;
/** Gradient color scheme */
gradient: 'blue-teal' | 'pink-purple' | 'orange-yellow' | 'blue-purple'; gradient: 'blue-teal' | 'pink-purple' | 'orange-yellow' | 'blue-purple';
/** Optional image URL for card decoration */
imageUrl?: string; imageUrl?: string;
} }
/**
* Gradient style type
*/
type GradientStyle = { type GradientStyle = {
backgroundImage?: string; backgroundImage?: string;
background?: string; background?: string;
}; };
export function MetricCard({ title, subtitle, value, gradient, imageUrl }: MetricCardProps) { /**
* MetricCard component
* @description Displays a metric card with gradient background and optional image
* @param props - Component props
* @returns MetricCard element
*/
export function MetricCard({
title,
subtitle,
value,
gradient,
imageUrl,
}: MetricCardProps): JSX.Element {
const gradientStyles: Record<MetricCardProps['gradient'], GradientStyle> = { const gradientStyles: Record<MetricCardProps['gradient'], GradientStyle> = {
'blue-teal': { 'blue-teal': {
backgroundImage: 'linear-gradient(16.03674192372833deg, rgba(0, 27, 47, 1) 10.549%, rgba(6, 38, 168, 1) 30.146%, rgba(3, 154, 152, 1) 77.418%)', backgroundImage: 'linear-gradient(16.03674192372833deg, rgba(0, 27, 47, 1) 10.549%, rgba(6, 38, 168, 1) 30.146%, rgba(3, 154, 152, 1) 77.418%)',

View File

@ -1,9 +1,15 @@
import { ChevronLeft, ChevronRight } from 'lucide-react'; import { ChevronLeft, ChevronRight } from 'lucide-react';
/**
* Pagination component props
*/
interface PaginationProps { interface PaginationProps {
/** Current active page number (1-indexed) */
currentPage: number; currentPage: number;
/** Total number of pages */
totalPages: number; totalPages: number;
/** Callback when page changes */
onPageChange: (page: number) => void; onPageChange: (page: number) => void;
} }
@ -11,12 +17,17 @@ interface PaginationProps {
* Pagination component * Pagination component
* @description Displays pagination controls with page numbers and navigation arrows * @description Displays pagination controls with page numbers and navigation arrows
* @param props - Component props * @param props - Component props
* @returns Pagination element * @returns {JSX.Element} Pagination element
*/ */
export function Pagination({ currentPage, totalPages, onPageChange }: PaginationProps) { export function Pagination({
currentPage,
totalPages,
onPageChange,
}: PaginationProps): JSX.Element {
/** /**
* Generate page numbers to display * Generate page numbers to display
* @returns Array of page numbers and ellipsis markers * @description Calculates which page numbers to show based on current page and total pages
* @returns {Array<number | 'ellipsis'>} Array of page numbers and ellipsis markers
*/ */
const getPageNumbers = (): (number | 'ellipsis')[] => { const getPageNumbers = (): (number | 'ellipsis')[] => {
const pages: (number | 'ellipsis')[] = []; const pages: (number | 'ellipsis')[] = [];
@ -58,8 +69,9 @@ export function Pagination({ currentPage, totalPages, onPageChange }: Pagination
/** /**
* Handle previous page navigation * Handle previous page navigation
* @description Navigates to the previous page if available
*/ */
const handlePrevious = () => { const handlePrevious = (): void => {
if (currentPage > 1) { if (currentPage > 1) {
onPageChange(currentPage - 1); onPageChange(currentPage - 1);
} }
@ -67,8 +79,9 @@ export function Pagination({ currentPage, totalPages, onPageChange }: Pagination
/** /**
* Handle next page navigation * Handle next page navigation
* @description Navigates to the next page if available
*/ */
const handleNext = () => { const handleNext = (): void => {
if (currentPage < totalPages) { if (currentPage < totalPages) {
onPageChange(currentPage + 1); onPageChange(currentPage + 1);
} }
@ -76,9 +89,10 @@ export function Pagination({ currentPage, totalPages, onPageChange }: Pagination
/** /**
* Handle page number click * Handle page number click
* @description Navigates to the specified page if valid
* @param page - Page number to navigate to * @param page - Page number to navigate to
*/ */
const handlePageClick = (page: number) => { const handlePageClick = (page: number): void => {
if (page !== currentPage && page >= 1 && page <= totalPages) { if (page !== currentPage && page >= 1 && page <= totalPages) {
onPageChange(page); onPageChange(page);
} }

View File

@ -5,9 +5,9 @@ import { APP_PATHS } from '@/routes';
/** /**
* Sidebar component * Sidebar component
* @description Left sidebar navigation with icon menu * @description Left sidebar navigation with icon menu
* @returns Sidebar element * @returns {JSX.Element} Sidebar element
*/ */
export function Sidebar() { export function Sidebar(): JSX.Element {
return ( return (
<aside className="fixed left-4 top-20 bottom-4 w-14 md:left-6 md:top-24 md:bottom-6 md:w-16 bg-gradient-to-b from-[#00A1A0] to-[#00166D] flex flex-col items-center py-4 md:py-6 gap-4 md:gap-6 z-50 rounded-xl md:rounded-2xl shadow-xl hidden md:flex"> <aside className="fixed left-4 top-20 bottom-4 w-14 md:left-6 md:top-24 md:bottom-6 md:w-16 bg-gradient-to-b from-[#00A1A0] to-[#00166D] flex flex-col items-center py-4 md:py-6 gap-4 md:gap-6 z-50 rounded-xl md:rounded-2xl shadow-xl hidden md:flex">
{/* Navigation Icons */} {/* Navigation Icons */}

View File

@ -15,10 +15,11 @@ interface RootLayoutProps {
/** /**
* RootLayout component * RootLayout component
* @description Wraps all pages with consistent sidebar and header layout * @description Wraps all pages with consistent sidebar and header layout
* @param children - Page content to render * @param props - Component props
* @returns RootLayout element * @param props.children - Page content to render
* @returns {JSX.Element} RootLayout element
*/ */
export function RootLayout({ children }: RootLayoutProps) { export function RootLayout({ children }: RootLayoutProps): JSX.Element {
return ( return (
<div <div
className="min-h-screen" className="min-h-screen"

View File

@ -16,11 +16,19 @@ import {
import { useClickOutside } from '@/hooks'; import { useClickOutside } from '@/hooks';
import type { Tool } from '@/types'; import type { Tool } from '@/types';
/**
* AddToolDialog component props
*/
interface AddToolDialogProps { interface AddToolDialogProps {
/** Whether the dialog is open */
open: boolean; open: boolean;
/** Callback when dialog open state changes */
onOpenChange: (open: boolean) => void; onOpenChange: (open: boolean) => void;
/** Callback when a new tool is added */
onAddTool?: (tool: Omit<Tool, 'id'>) => void; onAddTool?: (tool: Omit<Tool, 'id'>) => void;
/** Callback when an existing tool is updated */
onUpdateTool?: (toolId: string, tool: Omit<Tool, 'id'>) => void; onUpdateTool?: (toolId: string, tool: Omit<Tool, 'id'>) => void;
/** Tool being edited, if any */
editingTool?: Tool | null; editingTool?: Tool | null;
} }
@ -41,12 +49,17 @@ const SAVE_BUTTON_CLASS =
const SAVE_BUTTON_TEXT_CLASS = 'font-semibold leading-[18px] not-italic text-[16px] text-center text-white'; const SAVE_BUTTON_TEXT_CLASS = 'font-semibold leading-[18px] not-italic text-[16px] text-center text-white';
/** /**
* AddToolDialog component * Get initial state for the dialog
* @description Modal dialog for adding tools with API/MCP selection * @description Determines initial state based on editing tool
* @param open - Whether the dialog is open * @param editingTool - Tool being edited, if any
* @param onOpenChange - Callback when dialog open state changes * @returns Initial state with selected type and tool
*/ */
const getInitialState = (editingTool: Tool | null | undefined) => { const getInitialState = (
editingTool: Tool | null | undefined
): {
selectedType: 'API' | 'MCP';
selectedTool: typeof toolOptions[0] | null;
} => {
if (editingTool) { if (editingTool) {
const toolOption = toolOptions.find((opt) => opt.displayName === editingTool.name); const toolOption = toolOptions.find((opt) => opt.displayName === editingTool.name);
return { return {
@ -60,7 +73,19 @@ const getInitialState = (editingTool: Tool | null | undefined) => {
}; };
}; };
export function AddToolDialog({ open, onOpenChange, onAddTool, onUpdateTool, editingTool }: AddToolDialogProps) { /**
* AddToolDialog component
* @description Modal dialog for adding and configuring tools with API/MCP selection
* @param props - Component props
* @returns {JSX.Element} AddToolDialog element
*/
export function AddToolDialog({
open,
onOpenChange,
onAddTool,
onUpdateTool,
editingTool,
}: AddToolDialogProps): JSX.Element {
const initialState = useMemo(() => getInitialState(editingTool), [editingTool]); const initialState = useMemo(() => getInitialState(editingTool), [editingTool]);
const [selectedType, setSelectedType] = useState<'API' | 'MCP'>(initialState.selectedType); const [selectedType, setSelectedType] = useState<'API' | 'MCP'>(initialState.selectedType);
const [isDropdownOpen, setIsDropdownOpen] = useState(false); const [isDropdownOpen, setIsDropdownOpen] = useState(false);
@ -80,16 +105,29 @@ export function AddToolDialog({ open, onOpenChange, onAddTool, onUpdateTool, edi
const dropdownRef = useClickOutside<HTMLDivElement>(() => setIsDropdownOpen(false), isDropdownOpen); const dropdownRef = useClickOutside<HTMLDivElement>(() => setIsDropdownOpen(false), isDropdownOpen);
const handleToolSelect = (tool: typeof toolOptions[0]) => { /**
* Handle tool selection from dropdown
* @description Sets the selected tool and closes dropdown
* @param tool - Selected tool option
*/
const handleToolSelect = (tool: typeof toolOptions[0]): void => {
setSelectedTool(tool); setSelectedTool(tool);
setIsDropdownOpen(false); setIsDropdownOpen(false);
}; };
const handleToggleDropdown = () => { /**
* Toggle dropdown open/close state
* @description Switches dropdown visibility
*/
const handleToggleDropdown = (): void => {
setIsDropdownOpen((prev) => !prev); setIsDropdownOpen((prev) => !prev);
}; };
const handleSave = () => { /**
* Handle save action
* @description Saves the tool configuration (add or update)
*/
const handleSave = (): void => {
if (!selectedTool) return; if (!selectedTool) return;
const toolData = { const toolData = {
@ -109,13 +147,23 @@ export function AddToolDialog({ open, onOpenChange, onAddTool, onUpdateTool, edi
onOpenChange(false); onOpenChange(false);
}; };
const handleClose = () => { /**
* Handle dialog close
* @description Closes dialog and resets state
*/
const handleClose = (): void => {
setIsDropdownOpen(false); setIsDropdownOpen(false);
setSelectedTool(null); setSelectedTool(null);
onOpenChange(false); onOpenChange(false);
}; };
const radioButtonClass = (type: 'API' | 'MCP') => /**
* Get radio button class based on selection state
* @description Returns CSS classes for radio button styling
* @param type - Radio button type (API or MCP)
* @returns CSS class string
*/
const radioButtonClass = (type: 'API' | 'MCP'): string =>
`relative size-5 rounded-full border-2 flex items-center justify-center transition-all ${ `relative size-5 rounded-full border-2 flex items-center justify-center transition-all ${
selectedType === type ? 'border-[#0033FF]' : 'border-[#E5E8F4]' selectedType === type ? 'border-[#0033FF]' : 'border-[#E5E8F4]'
}`; }`;
@ -130,7 +178,13 @@ export function AddToolDialog({ open, onOpenChange, onAddTool, onUpdateTool, edi
const dropdownItemBaseClass = const dropdownItemBaseClass =
'w-full px-4 py-[13px] text-left font-normal text-sm leading-[20px] transition-colors border-b border-[#E5E8F4] last:border-b-0'; 'w-full px-4 py-[13px] text-left font-normal text-sm leading-[20px] transition-colors border-b border-[#E5E8F4] last:border-b-0';
const dropdownItemClass = (isSelected: boolean) => /**
* Get dropdown item class based on selection state
* @description Returns CSS classes for dropdown item styling
* @param isSelected - Whether the item is selected
* @returns CSS class string
*/
const dropdownItemClass = (isSelected: boolean): string =>
`${dropdownItemBaseClass} ${ `${dropdownItemBaseClass} ${
isSelected isSelected
? 'bg-[rgba(0,51,255,0.1)] text-[#0033FF]' ? 'bg-[rgba(0,51,255,0.1)] text-[#0033FF]'

View File

@ -14,28 +14,50 @@ import {
} from './dialog'; } from './dialog';
import { useEscapeKey, useBodyScrollLock } from '@/hooks'; import { useEscapeKey, useBodyScrollLock } from '@/hooks';
/**
* ConfigureMemoryDialog component props
*/
interface ConfigureMemoryDialogProps { interface ConfigureMemoryDialogProps {
/** Whether the dialog is open */
open: boolean; open: boolean;
/** Callback when dialog open state changes */
onOpenChange: (open: boolean) => void; onOpenChange: (open: boolean) => void;
/** Initial memory value (default: 2) */
initialValue?: number; initialValue?: number;
/** Callback when memory value is saved */
onSave?: (value: number) => void; onSave?: (value: number) => void;
} }
/** /**
* ConfigureMemoryDialog component * Minimum memory value
* @description Modal dialog for configuring memory settings
* @param open - Whether the dialog is open
* @param onOpenChange - Callback when dialog open state changes
* @param initialValue - Initial memory value (default: 2)
* @param onSave - Callback when memory is saved
*/ */
const MIN_VALUE = 2; const MIN_VALUE = 2;
/**
* Maximum memory value
*/
const MAX_VALUE = 10; const MAX_VALUE = 10;
/**
* Clamp value between min and max
* @description Ensures value is within bounds
* @param value - Value to clamp
* @param min - Minimum value
* @param max - Maximum value
* @returns Clamped value
*/
const clampValue = (value: number, min: number, max: number): number => { const clampValue = (value: number, min: number, max: number): number => {
return Math.max(min, Math.min(max, value)); return Math.max(min, Math.min(max, value));
}; };
/**
* Calculate percentage for slider
* @description Calculates percentage position for slider thumb
* @param value - Current value
* @param min - Minimum value
* @param max - Maximum value
* @returns Percentage (0-100)
*/
const calculatePercentage = (value: number, min: number, max: number): number => { const calculatePercentage = (value: number, min: number, max: number): number => {
return ((value - min) / (max - min)) * 100; return ((value - min) / (max - min)) * 100;
}; };
@ -61,12 +83,18 @@ const SLIDER_THUMB_CLASS =
'absolute top-[-5px] size-[18px] bg-white rounded-full border-2 border-[#0033FF] shadow-md pointer-events-none transition-all duration-200 z-20'; 'absolute top-[-5px] size-[18px] bg-white rounded-full border-2 border-[#0033FF] shadow-md pointer-events-none transition-all duration-200 z-20';
const MAX_LABEL_CLASS = 'font-medium leading-4 not-italic relative shrink-0 text-xs text-black'; const MAX_LABEL_CLASS = 'font-medium leading-4 not-italic relative shrink-0 text-xs text-black';
/**
* ConfigureMemoryDialog component
* @description Modal dialog for configuring memory settings with slider
* @param props - Component props
* @returns {JSX.Element} ConfigureMemoryDialog element
*/
export function ConfigureMemoryDialog({ export function ConfigureMemoryDialog({
open, open,
onOpenChange, onOpenChange,
initialValue = MIN_VALUE, initialValue = MIN_VALUE,
onSave, onSave,
}: ConfigureMemoryDialogProps) { }: ConfigureMemoryDialogProps): JSX.Element {
const clampedInitial = useMemo( const clampedInitial = useMemo(
() => clampValue(initialValue, MIN_VALUE, MAX_VALUE), () => clampValue(initialValue, MIN_VALUE, MAX_VALUE),
[initialValue] [initialValue]
@ -82,21 +110,35 @@ export function ConfigureMemoryDialog({
useEscapeKey(() => onOpenChange(false), open); useEscapeKey(() => onOpenChange(false), open);
useBodyScrollLock(open); useBodyScrollLock(open);
const handleSave = () => { /**
* Handle save action
* @description Saves the memory configuration and closes dialog
*/
const handleSave = (): void => {
if (onSave && memoryValue >= MIN_VALUE && memoryValue <= MAX_VALUE) { if (onSave && memoryValue >= MIN_VALUE && memoryValue <= MAX_VALUE) {
onSave(memoryValue); onSave(memoryValue);
} }
onOpenChange(false); onOpenChange(false);
}; };
const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => { /**
* Handle keyboard events on save button
* @description Handles Enter and Space key presses
* @param e - Keyboard event
*/
const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>): void => {
if (e.key === 'Enter' || e.key === ' ') { if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault(); e.preventDefault();
handleSave(); handleSave();
} }
}; };
const handleSliderChange = (e: React.ChangeEvent<HTMLInputElement>) => { /**
* Handle slider value change
* @description Updates memory value when slider moves
* @param e - Change event from slider input
*/
const handleSliderChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
setMemoryValue(Number(e.target.value)); setMemoryValue(Number(e.target.value));
}; };

View File

@ -6,9 +6,15 @@
import { X, ArrowRight } from 'lucide-react'; import { X, ArrowRight } from 'lucide-react';
import type { Tool } from '@/types'; import type { Tool } from '@/types';
/**
* ToolChip component props
*/
interface ToolChipProps { interface ToolChipProps {
/** Tool object to display */
tool: Tool; tool: Tool;
/** Callback when delete button is clicked */
onDelete: (id: string) => void; onDelete: (id: string) => void;
/** Callback when redirect button is clicked */
onRedirect: (id: string) => void; onRedirect: (id: string) => void;
} }

View File

@ -10,8 +10,10 @@ import type { Tool } from '@/types';
/** /**
* Toggle Switch Component * Toggle Switch Component
* @description A toggle switch that visually represents on/off state * @description A toggle switch that visually represents on/off state
* @param enabled - Whether the toggle is enabled
* @returns {JSX.Element} ToggleSwitch element
*/ */
function ToggleSwitch({ enabled }: { enabled: boolean }) { function ToggleSwitch({ enabled }: { enabled: boolean }): JSX.Element {
return ( return (
<div <div
className={`relative h-5 w-[35px] rounded-full transition-colors duration-200 ${ className={`relative h-5 w-[35px] rounded-full transition-colors duration-200 ${
@ -30,9 +32,9 @@ function ToggleSwitch({ enabled }: { enabled: boolean }) {
/** /**
* AgentCreatePage component * AgentCreatePage component
* @description Page for creating a new agent with configuration options * @description Page for creating a new agent with configuration options
* @returns Agent creation form page * @returns {JSX.Element} Agent creation form page
*/ */
export function AgentCreatePage() { export function AgentCreatePage(): JSX.Element {
const [enableKb, setEnableKb] = useState(false); const [enableKb, setEnableKb] = useState(false);
const [enableMemory, setEnableMemory] = useState(true); const [enableMemory, setEnableMemory] = useState(true);
const [isToolDialogOpen, setIsToolDialogOpen] = useState(false); const [isToolDialogOpen, setIsToolDialogOpen] = useState(false);
@ -44,27 +46,52 @@ export function AgentCreatePage() {
{ id: '2', name: 'GitHub', type: 'MCP', color: '#8fbc24' }, { id: '2', name: 'GitHub', type: 'MCP', color: '#8fbc24' },
]); ]);
const handleAddTool = (toolData: Omit<Tool, 'id'>) => { /**
* Handle adding a new tool
* @description Adds a new tool to the agent configuration
* @param toolData - Tool data without ID
*/
const handleAddTool = (toolData: Omit<Tool, 'id'>): void => {
const newTool: Tool = { const newTool: Tool = {
...toolData, ...toolData,
id: Date.now().toString(), // Simple ID generation id: Date.now().toString(),
}; };
setTools((prev) => [...prev, newTool]); setTools((prev) => [...prev, newTool]);
}; };
const handleUpdateTool = (toolId: string, toolData: Omit<Tool, 'id'>) => { /**
* Handle updating an existing tool
* @description Updates tool data for the specified tool ID
* @param toolId - ID of the tool to update
* @param toolData - Updated tool data without ID
*/
const handleUpdateTool = (
toolId: string,
toolData: Omit<Tool, 'id'>
): void => {
setTools((prev) => setTools((prev) =>
prev.map((tool) => (tool.id === toolId ? { ...tool, ...toolData } : tool)) prev.map((tool) =>
tool.id === toolId ? { ...tool, ...toolData } : tool
)
); );
setEditingTool(null); setEditingTool(null);
}; };
const handleDeleteTool = (id: string) => { /**
* Handle deleting a tool
* @description Removes a tool from the agent configuration
* @param id - ID of the tool to delete
*/
const handleDeleteTool = (id: string): void => {
setTools((prev) => prev.filter((tool) => tool.id !== id)); setTools((prev) => prev.filter((tool) => tool.id !== id));
}; };
const handleRedirectTool = (id: string) => { /**
// Find the tool and open configuration/update dialog * Handle redirecting to tool configuration
* @description Opens the tool dialog for editing the specified tool
* @param id - ID of the tool to configure
*/
const handleRedirectTool = (id: string): void => {
const tool = tools.find((t) => t.id === id); const tool = tools.find((t) => t.id === id);
if (tool) { if (tool) {
setEditingTool(tool); setEditingTool(tool);
@ -72,7 +99,12 @@ export function AgentCreatePage() {
} }
}; };
const handleDialogClose = (open: boolean) => { /**
* Handle dialog close state change
* @description Manages dialog open/close state and resets editing tool
* @param open - Whether the dialog should be open
*/
const handleDialogClose = (open: boolean): void => {
setIsToolDialogOpen(open); setIsToolDialogOpen(open);
if (!open) { if (!open) {
setEditingTool(null); setEditingTool(null);
@ -80,7 +112,7 @@ export function AgentCreatePage() {
}; };
return ( return (
<div className="min-h-screen px-[50px] py-6"> <div className="min-h-screen px-4 py-6 md:px-8 lg:px-[50px]">
<div className="mb-6"> <div className="mb-6">
<h1 className="font-semibold text-[20px] text-black leading-normal"> <h1 className="font-semibold text-[20px] text-black leading-normal">
Add Agent Add Agent
@ -171,7 +203,7 @@ export function AgentCreatePage() {
<span className="text-[#ef3125]">*</span> <span className="text-[#ef3125]">*</span>
</label> </label>
<button <button
className="bg-[rgba(0,51,255,0.06)] border border-[#333] rounded-md px-3 py-1.5 text-xs font-medium text-[#333] hover:bg-[rgba(0,51,255,0.1)] transition-colors" className="bg-[rgba(0,51,255,0.06)] border border-[#333] rounded-md px-3 py-1.5 text-xs font-medium text-[#333] hover:bg-[rgba(0,51,255,0.1)] transition-colors"
> >
Improve Instruction Improve Instruction
</button> </button>
@ -282,11 +314,12 @@ export function AgentCreatePage() {
className="bg-white border border-black border-solid flex items-center justify-center gap-1.5 px-3 py-[3px] rounded-[6px] hover:bg-gray-50 transition-colors" className="bg-white border border-black border-solid flex items-center justify-center gap-1.5 px-3 py-[3px] rounded-[6px] hover:bg-gray-50 transition-colors"
> >
<div className="relative size-6 flex items-center justify-center"> <div className="relative size-6 flex items-center justify-center">
<img <img
src="/Agent/add.svg" src="/Agent/add.svg"
alt="Add" alt="Add"
className="size-3.5 filter brightness-0" className="size-3.5 filter brightness-0"
/> </div> />
</div>
<span className="font-medium text-sm text-black leading-[1.5] text-left"> <span className="font-medium text-sm text-black leading-[1.5] text-left">
Add Add
</span> </span>

View File

@ -1,11 +1,17 @@
import { Link } from '@tanstack/react-router'; import { Link } from '@tanstack/react-router';
import { APP_PATHS } from '@/routes'; import { APP_PATHS } from '@/routes';
const searchIcon = 'https://www.figma.com/api/mcp/asset/379327bd-47f2-4ebc-a8e0-c0004928d27b'; const searchIcon =
'https://www.figma.com/api/mcp/asset/379327bd-47f2-4ebc-a8e0-c0004928d27b';
const emptyStateIcon = '/Agent/agent.svg'; const emptyStateIcon = '/Agent/agent.svg';
const addIcon = '/Agent/add.svg'; const addIcon = '/Agent/add.svg';
export function AgentPage() { /**
* AgentPage component
* @description Displays the agent management page with search and empty state
* @returns {JSX.Element} AgentPage element
*/
export function AgentPage(): JSX.Element {
return ( return (
<div className="px-4 py-6 md:px-6 md:py-8 lg:px-10 lg:pt-10 lg:pb-16"> <div className="px-4 py-6 md:px-6 md:py-8 lg:px-10 lg:pt-10 lg:pb-16">
<div className="flex flex-col gap-6 md:gap-8"> <div className="flex flex-col gap-6 md:gap-8">
@ -21,7 +27,11 @@ export function AgentPage() {
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex-1 w-full max-w-2xl"> <div className="flex-1 w-full max-w-2xl">
<div className="flex items-center gap-3 rounded-xl border border-[#E1E4EF] bg-white px-3 py-2.5 md:px-4 md:py-3 shadow-sm"> <div className="flex items-center gap-3 rounded-xl border border-[#E1E4EF] bg-white px-3 py-2.5 md:px-4 md:py-3 shadow-sm">
<img src={searchIcon} alt="Search" className="h-4 w-4 md:h-5 md:w-5 opacity-70" /> <img
src={searchIcon}
alt="Search"
className="h-4 w-4 md:h-5 md:w-5 opacity-70"
/>
<input <input
type="text" type="text"
placeholder="Search Agent" placeholder="Search Agent"

View File

@ -12,9 +12,9 @@ import { MOCK_AGENTS } from '@/constants/agents';
/** /**
* Dashboard component * Dashboard component
* @description Main dashboard page with all sections * @description Main dashboard page with all sections
* @returns Dashboard element * @returns {JSX.Element} Dashboard element
*/ */
export function Dashboard() { export function Dashboard(): JSX.Element {
return ( return (
<div className="px-4 py-4 md:px-6 lg:px-10 lg:pt-6 lg:pb-10"> <div className="px-4 py-4 md:px-6 lg:px-10 lg:pt-6 lg:pb-10">
{/* Content Header: Welcome + Search/Create */} {/* Content Header: Welcome + Search/Create */}

View File

@ -24,41 +24,120 @@ import { AuthFormCard, ForgotPasswordModal } from '@/components/auth';
export function LoginPage(): JSX.Element { export function LoginPage(): JSX.Element {
const [showForgotPwd, setShowForgotPwd] = useState(false); const [showForgotPwd, setShowForgotPwd] = useState(false);
const handleSignIn = (email: string, password: string): void => { /**
console.log('Sign in:', { email, password }); * Handle sign in form submission
* @description Processes user sign in credentials
* @param email - User email address
* @param password - User password
* @throws {Error} When authentication fails
*/
const handleSignIn = async (email: string, password: string): Promise<void> => {
try {
// TODO: Implement actual authentication API call
// await signInUser({ email, password });
} catch (error) {
// Error handling will be implemented with proper logging service
throw error;
}
}; };
const handleRegister = (data: { /**
* Handle user registration
* @description Processes new user registration
* @param data - Registration form data
* @throws {Error} When registration fails
*/
const handleRegister = async (data: {
firstName: string; firstName: string;
lastName: string; lastName: string;
email: string; email: string;
password: string; password: string;
}): void => { }): Promise<void> => {
console.log('Register:', data); try {
// TODO: Implement actual registration API call
// await registerUser(data);
} catch (error) {
// Error handling will be implemented with proper logging service
throw error;
}
}; };
const handleGoogleAuth = (): void => { /**
console.log('Google auth clicked'); * Handle Google authentication
* @description Initiates Google OAuth flow
* @throws {Error} When OAuth flow fails
*/
const handleGoogleAuth = async (): Promise<void> => {
try {
// TODO: Implement Google OAuth integration
// await authenticateWithGoogle();
} catch (error) {
// Error handling will be implemented with proper logging service
throw error;
}
}; };
const handleAzureAuth = (): void => { /**
console.log('Azure auth clicked'); * Handle Azure authentication
* @description Initiates Azure AD authentication flow
* @throws {Error} When Azure authentication fails
*/
const handleAzureAuth = async (): Promise<void> => {
try {
// TODO: Implement Azure AD authentication
// await authenticateWithAzure();
} catch (error) {
// Error handling will be implemented with proper logging service
throw error;
}
}; };
/**
* Handle forgot password click
* @description Opens the forgot password modal
*/
const handleForgotPasswordClick = (): void => { const handleForgotPasswordClick = (): void => {
setShowForgotPwd(true); setShowForgotPwd(true);
}; };
/**
* Handle forgot password modal close
* @description Closes the forgot password modal
*/
const handleForgotPasswordClose = (): void => { const handleForgotPasswordClose = (): void => {
setShowForgotPwd(false); setShowForgotPwd(false);
}; };
const handleForgotPasswordSubmit = (email: string): void => { /**
console.log('Password recovery requested for:', email); * Handle forgot password form submission
* @description Sends password recovery email
* @param email - User email address for password recovery
* @throws {Error} When password recovery request fails
*/
const handleForgotPasswordSubmit = async (email: string): Promise<void> => {
try {
// TODO: Implement password recovery API call
// await requestPasswordRecovery(email);
} catch (error) {
// Error handling will be implemented with proper logging service
throw error;
}
}; };
const handleOtpVerify = (otp: string): void => { /**
console.log('OTP verification:', otp); * Handle OTP verification
* @description Verifies the OTP code for password recovery
* @param otp - 6-digit OTP code
* @throws {Error} When OTP verification fails
*/
const handleOtpVerify = async (otp: string): Promise<void> => {
try {
// TODO: Implement OTP verification API call
// await verifyOtp(otp);
} catch (error) {
// Error handling will be implemented with proper logging service
throw error;
}
}; };
return ( return (

View File

@ -84,7 +84,12 @@ const notFoundRoute = createRoute({
const routeTree = rootRoute.addChildren([ const routeTree = rootRoute.addChildren([
publicRoute.addChildren([loginRoute, signUpRoute]), publicRoute.addChildren([loginRoute, signUpRoute]),
appRoute.addChildren([dashboardRoute,agentRoute,agentCreateRoute,notFoundRoute]), appRoute.addChildren([
dashboardRoute,
agentRoute,
agentCreateRoute,
notFoundRoute,
]),
]); ]);
export const router = createRouter({ export const router = createRouter({