chore(frontend): improve code formatting for readability
Standardize multiline formatting across components, tests, and API hooks for better consistency and clarity: - Adjusted function and object property indentation. - Updated tests and components to align with clean coding practices.
This commit is contained in:
@@ -25,7 +25,11 @@ export interface DashboardQuickStatsProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DashboardQuickStats({ stats, isLoading = false, className }: DashboardQuickStatsProps) {
|
export function DashboardQuickStats({
|
||||||
|
stats,
|
||||||
|
isLoading = false,
|
||||||
|
className,
|
||||||
|
}: DashboardQuickStatsProps) {
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ export function EmptyState({ userName = 'there', className }: EmptyStateProps) {
|
|||||||
|
|
||||||
<h2 className="text-2xl font-bold">Welcome to Syndarix, {userName}!</h2>
|
<h2 className="text-2xl font-bold">Welcome to Syndarix, {userName}!</h2>
|
||||||
<p className="mx-auto mt-2 max-w-md text-muted-foreground">
|
<p className="mx-auto mt-2 max-w-md text-muted-foreground">
|
||||||
Get started by creating your first project. Our AI agents will help you
|
Get started by creating your first project. Our AI agents will help you turn your ideas
|
||||||
turn your ideas into reality.
|
into reality.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<Button size="lg" asChild className="mt-6">
|
<Button size="lg" asChild className="mt-6">
|
||||||
|
|||||||
@@ -66,7 +66,10 @@ const typeConfig: Record<
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const priorityConfig: Record<PendingApproval['priority'], { label: string; variant: 'default' | 'secondary' | 'destructive' | 'outline' }> = {
|
const priorityConfig: Record<
|
||||||
|
PendingApproval['priority'],
|
||||||
|
{ label: string; variant: 'default' | 'secondary' | 'destructive' | 'outline' }
|
||||||
|
> = {
|
||||||
low: { label: 'Low', variant: 'outline' },
|
low: { label: 'Low', variant: 'outline' },
|
||||||
medium: { label: 'Medium', variant: 'secondary' },
|
medium: { label: 'Medium', variant: 'secondary' },
|
||||||
high: { label: 'High', variant: 'default' },
|
high: { label: 'High', variant: 'default' },
|
||||||
@@ -105,7 +108,12 @@ function ApprovalItem({ approval, onApprove, onReject }: ApprovalItemProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4 rounded-lg border p-4 sm:flex-row sm:items-start">
|
<div className="flex flex-col gap-4 rounded-lg border p-4 sm:flex-row sm:items-start">
|
||||||
<div className={cn('flex h-10 w-10 items-center justify-center rounded-full bg-muted', config.color)}>
|
<div
|
||||||
|
className={cn(
|
||||||
|
'flex h-10 w-10 items-center justify-center rounded-full bg-muted',
|
||||||
|
config.color
|
||||||
|
)}
|
||||||
|
>
|
||||||
<Icon className="h-5 w-5" />
|
<Icon className="h-5 w-5" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -118,10 +118,7 @@ export function RecentProjects({ projects, isLoading = false, className }: Recen
|
|||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
{[1, 2, 3, 4, 5, 6].map((i) => (
|
{[1, 2, 3, 4, 5, 6].map((i) => (
|
||||||
<div
|
<div key={i} className={cn(i > 3 && 'hidden lg:block')}>
|
||||||
key={i}
|
|
||||||
className={cn(i > 3 && 'hidden lg:block')}
|
|
||||||
>
|
|
||||||
<ProjectCardSkeleton />
|
<ProjectCardSkeleton />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -138,10 +135,7 @@ export function RecentProjects({ projects, isLoading = false, className }: Recen
|
|||||||
) : (
|
) : (
|
||||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
{displayProjects.map((project, index) => (
|
{displayProjects.map((project, index) => (
|
||||||
<div
|
<div key={project.id} className={cn(index >= 3 && 'hidden lg:block')}>
|
||||||
key={project.id}
|
|
||||||
className={cn(index >= 3 && 'hidden lg:block')}
|
|
||||||
>
|
|
||||||
<ProjectCard project={project} />
|
<ProjectCard project={project} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -49,10 +49,7 @@ function ComplexityIndicator({ complexity }: { complexity: 'low' | 'medium' | 'h
|
|||||||
{[1, 2, 3].map((i) => (
|
{[1, 2, 3].map((i) => (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className={cn(
|
className={cn('h-1.5 w-1.5 rounded-full', i <= level ? 'bg-primary' : 'bg-muted')}
|
||||||
'h-1.5 w-1.5 rounded-full',
|
|
||||||
i <= level ? 'bg-primary' : 'bg-muted'
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -140,10 +137,7 @@ export function ProjectCard({ project, onClick, onAction, className }: ProjectCa
|
|||||||
Archive Project
|
Archive Project
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem className="text-destructive" onClick={() => onAction('delete')}>
|
||||||
className="text-destructive"
|
|
||||||
onClick={() => onAction('delete')}
|
|
||||||
>
|
|
||||||
Delete Project
|
Delete Project
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|||||||
@@ -14,14 +14,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import {
|
import { Search, Filter, LayoutGrid, List, ChevronDown, X } from 'lucide-react';
|
||||||
Search,
|
|
||||||
Filter,
|
|
||||||
LayoutGrid,
|
|
||||||
List,
|
|
||||||
ChevronDown,
|
|
||||||
X,
|
|
||||||
} from 'lucide-react';
|
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
|||||||
@@ -27,7 +27,10 @@ export interface ProjectsGridProps {
|
|||||||
/** Called when a project card is clicked */
|
/** Called when a project card is clicked */
|
||||||
onProjectClick?: (project: ProjectListItem) => void;
|
onProjectClick?: (project: ProjectListItem) => void;
|
||||||
/** Called when a project action is selected */
|
/** Called when a project action is selected */
|
||||||
onProjectAction?: (project: ProjectListItem, action: 'archive' | 'pause' | 'resume' | 'delete') => void;
|
onProjectAction?: (
|
||||||
|
project: ProjectListItem,
|
||||||
|
action: 'archive' | 'pause' | 'resume' | 'delete'
|
||||||
|
) => void;
|
||||||
/** Whether filters are currently applied (affects empty state message) */
|
/** Whether filters are currently applied (affects empty state message) */
|
||||||
hasFilters?: boolean;
|
hasFilters?: boolean;
|
||||||
/** Additional CSS classes */
|
/** Additional CSS classes */
|
||||||
@@ -67,11 +70,7 @@ function EmptyState({ hasFilters }: { hasFilters: boolean }) {
|
|||||||
function LoadingSkeleton({ viewMode }: { viewMode: ViewMode }) {
|
function LoadingSkeleton({ viewMode }: { viewMode: ViewMode }) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(viewMode === 'grid' ? 'grid gap-4 sm:grid-cols-2 lg:grid-cols-3' : 'space-y-4')}
|
||||||
viewMode === 'grid'
|
|
||||||
? 'grid gap-4 sm:grid-cols-2 lg:grid-cols-3'
|
|
||||||
: 'space-y-4'
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{[1, 2, 3, 4, 5, 6].map((i) => (
|
{[1, 2, 3, 4, 5, 6].map((i) => (
|
||||||
<ProjectCardSkeleton key={i} />
|
<ProjectCardSkeleton key={i} />
|
||||||
@@ -100,9 +99,7 @@ export function ProjectsGrid({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
viewMode === 'grid'
|
viewMode === 'grid' ? 'grid gap-4 sm:grid-cols-2 lg:grid-cols-3' : 'space-y-4',
|
||||||
? 'grid gap-4 sm:grid-cols-2 lg:grid-cols-3'
|
|
||||||
: 'space-y-4',
|
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -51,5 +51,11 @@ export type {
|
|||||||
} from './wizard';
|
} from './wizard';
|
||||||
|
|
||||||
export type { ProjectCardProps } from './ProjectCard';
|
export type { ProjectCardProps } from './ProjectCard';
|
||||||
export type { ProjectFiltersProps, ViewMode, SortBy, SortOrder, Complexity } from './ProjectFilters';
|
export type {
|
||||||
|
ProjectFiltersProps,
|
||||||
|
ViewMode,
|
||||||
|
SortBy,
|
||||||
|
SortOrder,
|
||||||
|
Complexity,
|
||||||
|
} from './ProjectFilters';
|
||||||
export type { ProjectsGridProps } from './ProjectsGrid';
|
export type { ProjectsGridProps } from './ProjectsGrid';
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ const mockProjects: ProjectListItem[] = [
|
|||||||
{
|
{
|
||||||
id: 'proj-001',
|
id: 'proj-001',
|
||||||
name: 'E-Commerce Platform Redesign',
|
name: 'E-Commerce Platform Redesign',
|
||||||
description: 'Complete redesign of the e-commerce platform with modern UI/UX and improved checkout flow',
|
description:
|
||||||
|
'Complete redesign of the e-commerce platform with modern UI/UX and improved checkout flow',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
complexity: 'high',
|
complexity: 'high',
|
||||||
progress: 67,
|
progress: 67,
|
||||||
@@ -78,7 +79,8 @@ const mockProjects: ProjectListItem[] = [
|
|||||||
{
|
{
|
||||||
id: 'proj-002',
|
id: 'proj-002',
|
||||||
name: 'Mobile Banking App',
|
name: 'Mobile Banking App',
|
||||||
description: 'Native mobile app for banking services with biometric authentication and real-time notifications',
|
description:
|
||||||
|
'Native mobile app for banking services with biometric authentication and real-time notifications',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
complexity: 'high',
|
complexity: 'high',
|
||||||
progress: 45,
|
progress: 45,
|
||||||
@@ -93,7 +95,8 @@ const mockProjects: ProjectListItem[] = [
|
|||||||
{
|
{
|
||||||
id: 'proj-003',
|
id: 'proj-003',
|
||||||
name: 'Internal HR Portal',
|
name: 'Internal HR Portal',
|
||||||
description: 'Employee self-service portal for HR operations including leave requests and performance reviews',
|
description:
|
||||||
|
'Employee self-service portal for HR operations including leave requests and performance reviews',
|
||||||
status: 'paused',
|
status: 'paused',
|
||||||
complexity: 'medium',
|
complexity: 'medium',
|
||||||
progress: 23,
|
progress: 23,
|
||||||
@@ -108,7 +111,8 @@ const mockProjects: ProjectListItem[] = [
|
|||||||
{
|
{
|
||||||
id: 'proj-004',
|
id: 'proj-004',
|
||||||
name: 'API Gateway Modernization',
|
name: 'API Gateway Modernization',
|
||||||
description: 'Migrate legacy API gateway to cloud-native architecture with improved rate limiting and caching',
|
description:
|
||||||
|
'Migrate legacy API gateway to cloud-native architecture with improved rate limiting and caching',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
complexity: 'high',
|
complexity: 'high',
|
||||||
progress: 82,
|
progress: 82,
|
||||||
@@ -123,7 +127,8 @@ const mockProjects: ProjectListItem[] = [
|
|||||||
{
|
{
|
||||||
id: 'proj-005',
|
id: 'proj-005',
|
||||||
name: 'Customer Analytics Dashboard',
|
name: 'Customer Analytics Dashboard',
|
||||||
description: 'Real-time analytics dashboard for customer behavior insights with ML-powered predictions',
|
description:
|
||||||
|
'Real-time analytics dashboard for customer behavior insights with ML-powered predictions',
|
||||||
status: 'completed',
|
status: 'completed',
|
||||||
complexity: 'medium',
|
complexity: 'medium',
|
||||||
progress: 100,
|
progress: 100,
|
||||||
|
|||||||
@@ -244,7 +244,9 @@ describe('AgentTypeForm', () => {
|
|||||||
await user.click(screen.getByRole('tab', { name: /model/i }));
|
await user.click(screen.getByRole('tab', { name: /model/i }));
|
||||||
|
|
||||||
expect(screen.getByText('Model Selection')).toBeInTheDocument();
|
expect(screen.getByText('Model Selection')).toBeInTheDocument();
|
||||||
expect(screen.getByText('Choose the AI models that power this agent type')).toBeInTheDocument();
|
expect(
|
||||||
|
screen.getByText('Choose the AI models that power this agent type')
|
||||||
|
).toBeInTheDocument();
|
||||||
expect(screen.getByLabelText(/primary model/i)).toBeInTheDocument();
|
expect(screen.getByLabelText(/primary model/i)).toBeInTheDocument();
|
||||||
expect(screen.getByLabelText(/fallover model/i)).toBeInTheDocument();
|
expect(screen.getByLabelText(/fallover model/i)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
@@ -496,7 +498,9 @@ describe('AgentTypeForm', () => {
|
|||||||
const user = userEvent.setup();
|
const user = userEvent.setup();
|
||||||
render(<AgentTypeForm {...defaultProps} />);
|
render(<AgentTypeForm {...defaultProps} />);
|
||||||
|
|
||||||
const expertiseInput = screen.getByPlaceholderText(/e.g., system design/i) as HTMLInputElement;
|
const expertiseInput = screen.getByPlaceholderText(
|
||||||
|
/e.g., system design/i
|
||||||
|
) as HTMLInputElement;
|
||||||
await user.type(expertiseInput, 'new skill');
|
await user.type(expertiseInput, 'new skill');
|
||||||
await user.click(screen.getByRole('button', { name: /^add$/i }));
|
await user.click(screen.getByRole('button', { name: /^add$/i }));
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,9 @@ describe('RecentProjects', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('applies custom className', () => {
|
it('applies custom className', () => {
|
||||||
const { container } = render(<RecentProjects projects={mockProjects} className="custom-class" />);
|
const { container } = render(
|
||||||
|
<RecentProjects projects={mockProjects} className="custom-class" />
|
||||||
|
);
|
||||||
|
|
||||||
expect(container.firstChild).toHaveClass('custom-class');
|
expect(container.firstChild).toHaveClass('custom-class');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -27,7 +27,14 @@ describe('WelcomeHeader', () => {
|
|||||||
|
|
||||||
it('displays greeting with user first name', () => {
|
it('displays greeting with user first name', () => {
|
||||||
mockUseAuth.mockReturnValue({
|
mockUseAuth.mockReturnValue({
|
||||||
user: { id: '1', email: 'john@example.com', first_name: 'John', is_active: true, is_superuser: false, created_at: '' },
|
user: {
|
||||||
|
id: '1',
|
||||||
|
email: 'john@example.com',
|
||||||
|
first_name: 'John',
|
||||||
|
is_active: true,
|
||||||
|
is_superuser: false,
|
||||||
|
created_at: '',
|
||||||
|
},
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
@@ -44,7 +51,14 @@ describe('WelcomeHeader', () => {
|
|||||||
|
|
||||||
it('falls back to email prefix when first_name is empty', () => {
|
it('falls back to email prefix when first_name is empty', () => {
|
||||||
mockUseAuth.mockReturnValue({
|
mockUseAuth.mockReturnValue({
|
||||||
user: { id: '1', email: 'jane@example.com', first_name: '', is_active: true, is_superuser: false, created_at: '' },
|
user: {
|
||||||
|
id: '1',
|
||||||
|
email: 'jane@example.com',
|
||||||
|
first_name: '',
|
||||||
|
is_active: true,
|
||||||
|
is_superuser: false,
|
||||||
|
created_at: '',
|
||||||
|
},
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
@@ -78,7 +92,14 @@ describe('WelcomeHeader', () => {
|
|||||||
|
|
||||||
it('displays subtitle text', () => {
|
it('displays subtitle text', () => {
|
||||||
mockUseAuth.mockReturnValue({
|
mockUseAuth.mockReturnValue({
|
||||||
user: { id: '1', email: 'test@example.com', first_name: 'Test', is_active: true, is_superuser: false, created_at: '' },
|
user: {
|
||||||
|
id: '1',
|
||||||
|
email: 'test@example.com',
|
||||||
|
first_name: 'Test',
|
||||||
|
is_active: true,
|
||||||
|
is_superuser: false,
|
||||||
|
created_at: '',
|
||||||
|
},
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
@@ -95,7 +116,14 @@ describe('WelcomeHeader', () => {
|
|||||||
|
|
||||||
it('displays Create Project button', () => {
|
it('displays Create Project button', () => {
|
||||||
mockUseAuth.mockReturnValue({
|
mockUseAuth.mockReturnValue({
|
||||||
user: { id: '1', email: 'test@example.com', first_name: 'Test', is_active: true, is_superuser: false, created_at: '' },
|
user: {
|
||||||
|
id: '1',
|
||||||
|
email: 'test@example.com',
|
||||||
|
first_name: 'Test',
|
||||||
|
is_active: true,
|
||||||
|
is_superuser: false,
|
||||||
|
created_at: '',
|
||||||
|
},
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ describe('ProjectCard', () => {
|
|||||||
|
|
||||||
// Menu button should exist with sr-only text
|
// Menu button should exist with sr-only text
|
||||||
const menuButtons = screen.getAllByRole('button');
|
const menuButtons = screen.getAllByRole('button');
|
||||||
const menuButton = menuButtons.find(btn => btn.querySelector('.sr-only'));
|
const menuButton = menuButtons.find((btn) => btn.querySelector('.sr-only'));
|
||||||
expect(menuButton).toBeDefined();
|
expect(menuButton).toBeDefined();
|
||||||
expect(menuButton!.querySelector('.sr-only')).toHaveTextContent('Project actions');
|
expect(menuButton!.querySelector('.sr-only')).toHaveTextContent('Project actions');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -98,9 +98,7 @@ describe('ProjectsGrid', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('applies custom className', () => {
|
it('applies custom className', () => {
|
||||||
const { container } = render(
|
const { container } = render(<ProjectsGrid projects={mockProjects} className="custom-class" />);
|
||||||
<ProjectsGrid projects={mockProjects} className="custom-class" />
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(container.firstChild).toHaveClass('custom-class');
|
expect(container.firstChild).toHaveClass('custom-class');
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user