forked from cardosofelipe/fast-next-template
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;
|
||||
}
|
||||
|
||||
export function DashboardQuickStats({ stats, isLoading = false, className }: DashboardQuickStatsProps) {
|
||||
export function DashboardQuickStats({
|
||||
stats,
|
||||
isLoading = false,
|
||||
className,
|
||||
}: DashboardQuickStatsProps) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<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>
|
||||
<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
|
||||
turn your ideas into reality.
|
||||
Get started by creating your first project. Our AI agents will help you turn your ideas
|
||||
into reality.
|
||||
</p>
|
||||
|
||||
<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' },
|
||||
medium: { label: 'Medium', variant: 'secondary' },
|
||||
high: { label: 'High', variant: 'default' },
|
||||
@@ -105,7 +108,12 @@ function ApprovalItem({ approval, onApprove, onReject }: ApprovalItemProps) {
|
||||
|
||||
return (
|
||||
<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" />
|
||||
</div>
|
||||
|
||||
|
||||
@@ -118,10 +118,7 @@ export function RecentProjects({ projects, isLoading = false, className }: Recen
|
||||
{isLoading ? (
|
||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{[1, 2, 3, 4, 5, 6].map((i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={cn(i > 3 && 'hidden lg:block')}
|
||||
>
|
||||
<div key={i} className={cn(i > 3 && 'hidden lg:block')}>
|
||||
<ProjectCardSkeleton />
|
||||
</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">
|
||||
{displayProjects.map((project, index) => (
|
||||
<div
|
||||
key={project.id}
|
||||
className={cn(index >= 3 && 'hidden lg:block')}
|
||||
>
|
||||
<div key={project.id} className={cn(index >= 3 && 'hidden lg:block')}>
|
||||
<ProjectCard project={project} />
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -49,10 +49,7 @@ function ComplexityIndicator({ complexity }: { complexity: 'low' | 'medium' | 'h
|
||||
{[1, 2, 3].map((i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={cn(
|
||||
'h-1.5 w-1.5 rounded-full',
|
||||
i <= level ? 'bg-primary' : 'bg-muted'
|
||||
)}
|
||||
className={cn('h-1.5 w-1.5 rounded-full', i <= level ? 'bg-primary' : 'bg-muted')}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
@@ -140,10 +137,7 @@ export function ProjectCard({ project, onClick, onAction, className }: ProjectCa
|
||||
Archive Project
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
className="text-destructive"
|
||||
onClick={() => onAction('delete')}
|
||||
>
|
||||
<DropdownMenuItem className="text-destructive" onClick={() => onAction('delete')}>
|
||||
Delete Project
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
|
||||
@@ -14,14 +14,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
Search,
|
||||
Filter,
|
||||
LayoutGrid,
|
||||
List,
|
||||
ChevronDown,
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
import { Search, Filter, LayoutGrid, List, ChevronDown, X } from 'lucide-react';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
|
||||
@@ -27,7 +27,10 @@ export interface ProjectsGridProps {
|
||||
/** Called when a project card is clicked */
|
||||
onProjectClick?: (project: ProjectListItem) => void;
|
||||
/** 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) */
|
||||
hasFilters?: boolean;
|
||||
/** Additional CSS classes */
|
||||
@@ -67,11 +70,7 @@ function EmptyState({ hasFilters }: { hasFilters: boolean }) {
|
||||
function LoadingSkeleton({ viewMode }: { viewMode: ViewMode }) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
viewMode === 'grid'
|
||||
? 'grid gap-4 sm:grid-cols-2 lg:grid-cols-3'
|
||||
: 'space-y-4'
|
||||
)}
|
||||
className={cn(viewMode === 'grid' ? 'grid gap-4 sm:grid-cols-2 lg:grid-cols-3' : 'space-y-4')}
|
||||
>
|
||||
{[1, 2, 3, 4, 5, 6].map((i) => (
|
||||
<ProjectCardSkeleton key={i} />
|
||||
@@ -100,9 +99,7 @@ export function ProjectsGrid({
|
||||
return (
|
||||
<div
|
||||
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',
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -51,5 +51,11 @@ export type {
|
||||
} from './wizard';
|
||||
|
||||
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';
|
||||
|
||||
@@ -63,7 +63,8 @@ const mockProjects: ProjectListItem[] = [
|
||||
{
|
||||
id: 'proj-001',
|
||||
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',
|
||||
complexity: 'high',
|
||||
progress: 67,
|
||||
@@ -78,7 +79,8 @@ const mockProjects: ProjectListItem[] = [
|
||||
{
|
||||
id: 'proj-002',
|
||||
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',
|
||||
complexity: 'high',
|
||||
progress: 45,
|
||||
@@ -93,7 +95,8 @@ const mockProjects: ProjectListItem[] = [
|
||||
{
|
||||
id: 'proj-003',
|
||||
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',
|
||||
complexity: 'medium',
|
||||
progress: 23,
|
||||
@@ -108,7 +111,8 @@ const mockProjects: ProjectListItem[] = [
|
||||
{
|
||||
id: 'proj-004',
|
||||
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',
|
||||
complexity: 'high',
|
||||
progress: 82,
|
||||
@@ -123,7 +127,8 @@ const mockProjects: ProjectListItem[] = [
|
||||
{
|
||||
id: 'proj-005',
|
||||
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',
|
||||
complexity: 'medium',
|
||||
progress: 100,
|
||||
|
||||
@@ -244,7 +244,9 @@ describe('AgentTypeForm', () => {
|
||||
await user.click(screen.getByRole('tab', { name: /model/i }));
|
||||
|
||||
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(/fallover model/i)).toBeInTheDocument();
|
||||
});
|
||||
@@ -496,7 +498,9 @@ describe('AgentTypeForm', () => {
|
||||
const user = userEvent.setup();
|
||||
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.click(screen.getByRole('button', { name: /^add$/i }));
|
||||
|
||||
|
||||
@@ -113,7 +113,9 @@ describe('RecentProjects', () => {
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
|
||||
@@ -27,7 +27,14 @@ describe('WelcomeHeader', () => {
|
||||
|
||||
it('displays greeting with user first name', () => {
|
||||
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,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
@@ -44,7 +51,14 @@ describe('WelcomeHeader', () => {
|
||||
|
||||
it('falls back to email prefix when first_name is empty', () => {
|
||||
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,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
@@ -78,7 +92,14 @@ describe('WelcomeHeader', () => {
|
||||
|
||||
it('displays subtitle text', () => {
|
||||
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,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
@@ -95,7 +116,14 @@ describe('WelcomeHeader', () => {
|
||||
|
||||
it('displays Create Project button', () => {
|
||||
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,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('ProjectCard', () => {
|
||||
|
||||
// Menu button should exist with sr-only text
|
||||
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!.querySelector('.sr-only')).toHaveTextContent('Project actions');
|
||||
});
|
||||
|
||||
@@ -98,9 +98,7 @@ describe('ProjectsGrid', () => {
|
||||
});
|
||||
|
||||
it('applies custom className', () => {
|
||||
const { container } = render(
|
||||
<ProjectsGrid projects={mockProjects} className="custom-class" />
|
||||
);
|
||||
const { container } = render(<ProjectsGrid projects={mockProjects} className="custom-class" />);
|
||||
|
||||
expect(container.firstChild).toHaveClass('custom-class');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user