Claude Code Plugins

Community-maintained marketplace

Feedback

construction-ui-components

@CBoser/ConstructionPlatform
0
0

Specialized skill for building React UI components for the construction project management platform. Use when creating interfaces for dashboard, job management, plan specification (40 plans, 567 options selector), schedule board, PDSS tracking, subdivision portfolio (31 subdivisions), or contract management. Includes component patterns, state management, form handling, real-time updates, and mobile-responsive designs specific to construction workflows.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name construction-ui-components
description Specialized skill for building React UI components for the construction project management platform. Use when creating interfaces for dashboard, job management, plan specification (40 plans, 567 options selector), schedule board, PDSS tracking, subdivision portfolio (31 subdivisions), or contract management. Includes component patterns, state management, form handling, real-time updates, and mobile-responsive designs specific to construction workflows.

Construction UI Components

Comprehensive guide for building the frontend React components for the integrated construction project management platform.

Technology Stack

Core Libraries

  • Framework: React 18+ with TypeScript
  • State Management: Redux Toolkit with RTK Query
  • Routing: React Router v6
  • UI Framework: Material-UI (MUI) v5
  • Forms: React Hook Form with Yup validation
  • Charts: Recharts
  • Date Handling: date-fns
  • Real-time: Socket.io-client
  • Testing: Jest + React Testing Library

Project Structure

/frontend
├── /src
│   ├── /components
│   │   ├── /common         # Reusable components
│   │   ├── /dashboard      # Dashboard widgets
│   │   ├── /jobs           # Job management
│   │   ├── /plans          # Plan/option selection
│   │   ├── /schedule       # Schedule board
│   │   └── /subdivisions   # Subdivision management
│   ├── /features           # Redux slices
│   ├── /hooks              # Custom hooks
│   ├── /services           # API services
│   ├── /utils              # Helper functions
│   ├── /types              # TypeScript types
│   └── /styles             # Global styles
└── /public

Component Design System

Color Palette

// theme/palette.ts
export const palette = {
  primary: {
    main: '#1976d2',      // Professional blue
    light: '#42a5f5',
    dark: '#1565c0',
  },
  secondary: {
    main: '#ff9800',      // Construction orange
    light: '#ffb74d',
    dark: '#f57c00',
  },
  status: {
    planStart: '#9c27b0',       // Purple
    pdssInitiated: '#3f51b5',   // Indigo
    planReview: '#2196f3',      // Blue
    approved: '#4caf50',        // Green
    inProduction: '#ff9800',    // Orange
    qualityCheck: '#ff5722',    // Deep Orange
    completed: '#8bc34a',       // Light Green
    onHold: '#ffc107',          // Amber
    cancelled: '#9e9e9e',       // Grey
  },
  priority: {
    low: '#9e9e9e',
    medium: '#ff9800',
    high: '#ff5722',
    urgent: '#f44336',
  },
};

Typography

// theme/typography.ts
export const typography = {
  fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
  h1: {
    fontSize: '2.5rem',
    fontWeight: 500,
  },
  h2: {
    fontSize: '2rem',
    fontWeight: 500,
  },
  h3: {
    fontSize: '1.75rem',
    fontWeight: 500,
  },
  body1: {
    fontSize: '1rem',
    lineHeight: 1.5,
  },
  button: {
    textTransform: 'none' as const,  // Don't uppercase buttons
  },
};

Core Components

1. Dashboard Component

// components/dashboard/Dashboard.tsx
import React, { useEffect } from 'react';
import { Grid, Paper, Typography, Box } from '@mui/material';
import { useSelector, useDispatch } from 'react-redux';
import { fetchDashboardData } from '../../features/dashboard/dashboardSlice';
import JobStatusChart from './JobStatusChart';
import ActiveJobsWidget from './ActiveJobsWidget';
import SubdivisionOverview from './SubdivisionOverview';
import RecentActivity from './RecentActivity';
import PerformanceMetrics from './PerformanceMetrics';

const Dashboard: React.FC = () => {
  const dispatch = useDispatch();
  const { data, loading, error } = useSelector((state: RootState) => state.dashboard);

  useEffect(() => {
    dispatch(fetchDashboardData());
  }, [dispatch]);

  if (loading) return <LoadingSpinner />;
  if (error) return <ErrorDisplay error={error} />;

  return (
    <Box sx={{ p: 3 }}>
      <Typography variant="h3" sx={{ mb: 3 }}>
        Dashboard
      </Typography>

      <Grid container spacing={3}>
        {/* Key Metrics Row */}
        <Grid item xs={12} md={3}>
          <MetricCard
            title="Active Jobs"
            value={data.activeJobs}
            icon={<WorkIcon />}
            trend={data.jobsTrend}
          />
        </Grid>
        <Grid item xs={12} md={3}>
          <MetricCard
            title="Plans in Review"
            value={data.plansInReview}
            icon={<DescriptionIcon />}
            trend={data.reviewTrend}
          />
        </Grid>
        <Grid item xs={12} md={3}>
          <MetricCard
            title="Subdivisions"
            value="31"
            icon={<LocationCityIcon />}
          />
        </Grid>
        <Grid item xs={12} md={3}>
          <MetricCard
            title="Completion Rate"
            value={`${data.completionRate}%`}
            icon={<CheckCircleIcon />}
            trend={data.completionTrend}
          />
        </Grid>

        {/* Job Status Distribution */}
        <Grid item xs={12} md={8}>
          <Paper sx={{ p: 2, height: 400 }}>
            <Typography variant="h6" sx={{ mb: 2 }}>
              Job Status Distribution
            </Typography>
            <JobStatusChart data={data.statusDistribution} />
          </Paper>
        </Grid>

        {/* Recent Activity */}
        <Grid item xs={12} md={4}>
          <Paper sx={{ p: 2, height: 400, overflow: 'auto' }}>
            <Typography variant="h6" sx={{ mb: 2 }}>
              Recent Activity
            </Typography>
            <RecentActivity activities={data.recentActivities} />
          </Paper>
        </Grid>

        {/* Active Jobs Table */}
        <Grid item xs={12}>
          <Paper sx={{ p: 2 }}>
            <Typography variant="h6" sx={{ mb: 2 }}>
              Active Jobs
            </Typography>
            <ActiveJobsWidget jobs={data.activeJobsList} />
          </Paper>
        </Grid>

        {/* Subdivision Overview */}
        <Grid item xs={12} md={6}>
          <Paper sx={{ p: 2 }}>
            <Typography variant="h6" sx={{ mb: 2 }}>
              Subdivision Portfolio
            </Typography>
            <SubdivisionOverview subdivisions={data.subdivisions} />
          </Paper>
        </Grid>

        {/* Performance Metrics */}
        <Grid item xs={12} md={6}>
          <Paper sx={{ p: 2 }}>
            <Typography variant="h6" sx={{ mb: 2 }}>
              Performance Metrics
            </Typography>
            <PerformanceMetrics metrics={data.performance} />
          </Paper>
        </Grid>
      </Grid>
    </Box>
  );
};

export default Dashboard;

2. Plan Option Selector Component

// components/plans/PlanOptionSelector.tsx
import React, { useState, useEffect } from 'react';
import {
  Box,
  Card,
  CardContent,
  Chip,
  Typography,
  Alert,
  Accordion,
  AccordionSummary,
  AccordionDetails,
  FormControlLabel,
  Checkbox,
  Grid,
  Button,
  Dialog,
} from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { usePlanOptions } from '../../hooks/usePlanOptions';
import { validateOptions } from '../../services/planService';

interface PlanOptionSelectorProps {
  planId: string;
  elevation: string;
  initialSelectedOptions?: string[];
  onSelectionChange: (selectedOptions: string[]) => void;
}

const PlanOptionSelector: React.FC<PlanOptionSelectorProps> = ({
  planId,
  elevation,
  initialSelectedOptions = [],
  onSelectionChange,
}) => {
  const { options, loading } = usePlanOptions(planId);
  const [selectedOptions, setSelectedOptions] = useState<string[]>(initialSelectedOptions);
  const [validation, setValidation] = useState<any>(null);
  const [showRecommendations, setShowRecommendations] = useState(false);

  // Group options by category
  const optionsByCategory = options.reduce((acc, option) => {
    if (!acc[option.category]) {
      acc[option.category] = [];
    }
    acc[option.category].push(option);
    return acc;
  }, {} as Record<string, typeof options>);

  // Validate selections whenever they change
  useEffect(() => {
    const validate = async () => {
      if (selectedOptions.length > 0) {
        const result = await validateOptions(planId, selectedOptions, elevation);
        setValidation(result);
      } else {
        setValidation(null);
      }
    };
    validate();
  }, [selectedOptions, planId, elevation]);

  const handleOptionToggle = (optionCode: string) => {
    const newSelection = selectedOptions.includes(optionCode)
      ? selectedOptions.filter(code => code !== optionCode)
      : [...selectedOptions, optionCode];
    
    setSelectedOptions(newSelection);
    onSelectionChange(newSelection);
  };

  const isOptionDisabled = (option: any): boolean => {
    // Disable if not available for selected elevation
    if (option.availableElevations.length > 0 && 
        !option.availableElevations.includes(elevation)) {
      return true;
    }

    // Disable if conflicts with selected options
    const hasConflict = option.conflictingOptions.some(code =>
      selectedOptions.includes(code)
    );
    if (hasConflict) return true;

    return false;
  };

  const getOptionStatus = (option: any): string | null => {
    // Check if unavailable for elevation
    if (option.availableElevations.length > 0 && 
        !option.availableElevations.includes(elevation)) {
      return `Not available for elevation ${elevation}`;
    }

    // Check for conflicts
    const conflicts = option.conflictingOptions.filter(code =>
      selectedOptions.includes(code)
    );
    if (conflicts.length > 0) {
      return `Conflicts with: ${conflicts.join(', ')}`;
    }

    // Check for missing requirements
    const missingReqs = option.requiredOptions.filter(code =>
      !selectedOptions.includes(code)
    );
    if (missingReqs.length > 0) {
      return `Requires: ${missingReqs.join(', ')}`;
    }

    return null;
  };

  if (loading) return <LoadingSpinner />;

  return (
    <Box>
      {/* Validation Messages */}
      {validation && !validation.isValid && (
        <Alert severity="error" sx={{ mb: 2 }}>
          <Typography variant="subtitle2">
            Please resolve the following issues:
          </Typography>
          <ul>
            {validation.errors.map((error: any, idx: number) => (
              <li key={idx}>{error.message}</li>
            ))}
          </ul>
        </Alert>
      )}

      {validation && validation.warnings.length > 0 && (
        <Alert severity="warning" sx={{ mb: 2 }}>
          <Typography variant="subtitle2">Warnings:</Typography>
          <ul>
            {validation.warnings.map((warning: any, idx: number) => (
              <li key={idx}>{warning.message}</li>
            ))}
          </ul>
        </Alert>
      )}

      {/* Recommendations */}
      {validation && validation.recommendations.length > 0 && (
        <Alert 
          severity="info" 
          sx={{ mb: 2 }}
          action={
            <Button 
              color="inherit" 
              size="small"
              onClick={() => setShowRecommendations(true)}
            >
              VIEW
            </Button>
          }
        >
          {validation.recommendations.length} recommended options available
        </Alert>
      )}

      {/* Option Selection by Category */}
      {Object.entries(optionsByCategory).map(([category, categoryOptions]) => (
        <Accordion key={category} defaultExpanded={category === 'exterior'}>
          <AccordionSummary expandIcon={<ExpandMoreIcon />}>
            <Typography variant="h6" sx={{ textTransform: 'capitalize' }}>
              {category.replace('_', ' ')}
              <Chip 
                label={categoryOptions.filter(opt => 
                  selectedOptions.includes(opt.optionCode)
                ).length}
                size="small"
                sx={{ ml: 2 }}
              />
            </Typography>
          </AccordionSummary>
          <AccordionDetails>
            <Grid container spacing={2}>
              {categoryOptions.map(option => {
                const isDisabled = isOptionDisabled(option);
                const isSelected = selectedOptions.includes(option.optionCode);
                const status = getOptionStatus(option);

                return (
                  <Grid item xs={12} sm={6} md={4} key={option.optionCode}>
                    <Card 
                      variant="outlined"
                      sx={{
                        opacity: isDisabled ? 0.5 : 1,
                        borderColor: isSelected ? 'primary.main' : undefined,
                        borderWidth: isSelected ? 2 : 1,
                      }}
                    >
                      <CardContent>
                        <FormControlLabel
                          control={
                            <Checkbox
                              checked={isSelected}
                              onChange={() => handleOptionToggle(option.optionCode)}
                              disabled={isDisabled}
                            />
                          }
                          label={
                            <Box>
                              <Typography variant="subtitle2">
                                {option.optionName}
                              </Typography>
                              <Typography variant="caption" color="text.secondary">
                                {option.optionCode}
                              </Typography>
                              {option.impactsSchedule && (
                                <Chip 
                                  label={`+${option.leadTimeDays}d`}
                                  size="small"
                                  color="warning"
                                  sx={{ ml: 1 }}
                                />
                              )}
                              {option.requiresEngineering && (
                                <Chip 
                                  label="Engineering"
                                  size="small"
                                  color="info"
                                  sx={{ ml: 1 }}
                                />
                              )}
                            </Box>
                          }
                        />
                        {option.description && (
                          <Typography 
                            variant="body2" 
                            color="text.secondary"
                            sx={{ mt: 1, ml: 4 }}
                          >
                            {option.description}
                          </Typography>
                        )}
                        {status && (
                          <Alert severity="warning" sx={{ mt: 1, py: 0 }}>
                            <Typography variant="caption">{status}</Typography>
                          </Alert>
                        )}
                      </CardContent>
                    </Card>
                  </Grid>
                );
              })}
            </Grid>
          </AccordionDetails>
        </Accordion>
      ))}

      {/* Recommendations Dialog */}
      <Dialog 
        open={showRecommendations} 
        onClose={() => setShowRecommendations(false)}
        maxWidth="md"
        fullWidth
      >
        <Box sx={{ p: 3 }}>
          <Typography variant="h6" sx={{ mb: 2 }}>
            Recommended Options
          </Typography>
          <Grid container spacing={2}>
            {validation?.recommendations.map((rec: any) => (
              <Grid item xs={12} sm={6} key={rec.optionCode}>
                <Card variant="outlined">
                  <CardContent>
                    <Typography variant="subtitle2">{rec.optionName}</Typography>
                    <Typography variant="caption" color="text.secondary">
                      {rec.reason}
                    </Typography>
                    <Button
                      size="small"
                      sx={{ mt: 1 }}
                      onClick={() => {
                        handleOptionToggle(rec.optionCode);
                        setShowRecommendations(false);
                      }}
                    >
                      Add to Selection
                    </Button>
                  </CardContent>
                </Card>
              </Grid>
            ))}
          </Grid>
        </Box>
      </Dialog>

      {/* Selection Summary */}
      <Box sx={{ mt: 3, p: 2, bgcolor: 'background.paper', borderRadius: 1 }}>
        <Typography variant="h6" sx={{ mb: 1 }}>
          Selection Summary
        </Typography>
        <Typography variant="body2" color="text.secondary">
          {selectedOptions.length} options selected
        </Typography>
        {validation && validation.warnings.some((w: any) => w.type === 'SCHEDULE_IMPACT') && (
          <Typography variant="body2" color="warning.main">
            ⚠ Estimated schedule impact: +
            {validation.warnings.find((w: any) => w.type === 'SCHEDULE_IMPACT')?.additionalDays} days
          </Typography>
        )}
      </Box>
    </Box>
  );
};

export default PlanOptionSelector;

3. Job Schedule Board Component

// components/schedule/ScheduleBoard.tsx
import React, { useState, useEffect } from 'react';
import {
  Box,
  Card,
  Typography,
  Chip,
  IconButton,
  Menu,
  MenuItem,
  Dialog,
} from '@mui/material';
import MoreVertIcon from '@mui/icons-material/MoreVert';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import { useJobs } from '../../hooks/useJobs';
import { updateJobStatus } from '../../services/jobService';

const statusColumns = [
  { id: 'plan_start', label: 'Plan Start', color: '#9c27b0' },
  { id: 'pdss_initiated', label: 'PDSS Initiated', color: '#3f51b5' },
  { id: 'plan_review', label: 'Plan Review', color: '#2196f3' },
  { id: 'approved', label: 'Approved', color: '#4caf50' },
  { id: 'in_production', label: 'In Production', color: '#ff9800' },
  { id: 'quality_check', label: 'Quality Check', color: '#ff5722' },
  { id: 'completed', label: 'Completed', color: '#8bc34a' },
];

const ScheduleBoard: React.FC = () => {
  const { jobs, loading, updateJob } = useJobs();
  const [selectedJob, setSelectedJob] = useState<any>(null);
  const [showJobDetails, setShowJobDetails] = useState(false);

  const handleDragEnd = async (result: any) => {
    if (!result.destination) return;

    const jobId = result.draggableId;
    const newStatus = result.destination.droppableId;

    try {
      await updateJobStatus(jobId, newStatus);
      updateJob(jobId, { status: newStatus });
    } catch (error) {
      console.error('Error updating job status:', error);
    }
  };

  const jobsByStatus = statusColumns.reduce((acc, column) => {
    acc[column.id] = jobs.filter(job => job.status === column.id);
    return acc;
  }, {} as Record<string, any[]>);

  return (
    <Box sx={{ p: 3 }}>
      <Typography variant="h3" sx={{ mb: 3 }}>
        Schedule Board
      </Typography>

      <DragDropContext onDragEnd={handleDragEnd}>
        <Box sx={{ display: 'flex', gap: 2, overflowX: 'auto', pb: 2 }}>
          {statusColumns.map(column => (
            <Droppable droppableId={column.id} key={column.id}>
              {(provided, snapshot) => (
                <Box
                  ref={provided.innerRef}
                  {...provided.droppableProps}
                  sx={{
                    minWidth: 280,
                    bgcolor: snapshot.isDraggingOver ? 'action.hover' : 'background.default',
                    borderRadius: 1,
                    p: 2,
                  }}
                >
                  <Box 
                    sx={{ 
                      display: 'flex', 
                      alignItems: 'center', 
                      mb: 2,
                      pb: 1,
                      borderBottom: `3px solid ${column.color}`,
                    }}
                  >
                    <Typography variant="h6" sx={{ flex: 1 }}>
                      {column.label}
                    </Typography>
                    <Chip 
                      label={jobsByStatus[column.id]?.length || 0}
                      size="small"
                      sx={{ bgcolor: column.color, color: 'white' }}
                    />
                  </Box>

                  <Box sx={{ minHeight: 400 }}>
                    {jobsByStatus[column.id]?.map((job, index) => (
                      <Draggable 
                        key={job.id} 
                        draggableId={job.id} 
                        index={index}
                      >
                        {(provided, snapshot) => (
                          <Card
                            ref={provided.innerRef}
                            {...provided.draggableProps}
                            {...provided.dragHandleProps}
                            sx={{
                              mb: 2,
                              cursor: 'grab',
                              opacity: snapshot.isDragging ? 0.8 : 1,
                              transform: snapshot.isDragging 
                                ? 'rotate(2deg)' 
                                : 'none',
                            }}
                            onClick={() => {
                              setSelectedJob(job);
                              setShowJobDetails(true);
                            }}
                          >
                            <Box sx={{ p: 2 }}>
                              <Box sx={{ display: 'flex', alignItems: 'start', mb: 1 }}>
                                <Typography variant="subtitle2" sx={{ flex: 1 }}>
                                  {job.jobNumber}
                                </Typography>
                                <Chip
                                  label={job.priority}
                                  size="small"
                                  color={
                                    job.priority === 'urgent' ? 'error' :
                                    job.priority === 'high' ? 'warning' :
                                    'default'
                                  }
                                />
                              </Box>

                              <Typography variant="body2" color="text.secondary">
                                {job.subdivision.subdivisionName}
                              </Typography>
                              
                              <Typography variant="body2" sx={{ mt: 1 }}>
                                Lot {job.lotNumber}
                              </Typography>

                              <Typography variant="caption" color="text.secondary">
                                {job.plan.planName} - {job.elevation}
                              </Typography>

                              {job.flags && job.flags.length > 0 && (
                                <Box sx={{ mt: 1 }}>
                                  {job.flags.map((flag: string) => (
                                    <Chip
                                      key={flag}
                                      label={flag.replace('_', ' ')}
                                      size="small"
                                      color="warning"
                                      sx={{ mr: 0.5, mt: 0.5 }}
                                    />
                                  ))}
                                </Box>
                              )}
                            </Box>
                          </Card>
                        )}
                      </Draggable>
                    ))}
                    {provided.placeholder}
                  </Box>
                </Box>
              )}
            </Droppable>
          ))}
        </Box>
      </DragDropContext>

      {/* Job Details Dialog */}
      <JobDetailsDialog
        job={selectedJob}
        open={showJobDetails}
        onClose={() => setShowJobDetails(false)}
      />
    </Box>
  );
};

export default ScheduleBoard;

Custom Hooks

useRealTimeUpdates Hook

// hooks/useRealTimeUpdates.ts
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { io, Socket } from 'socket.io-client';
import { updateJob, addNotification } from '../features/jobs/jobsSlice';

let socket: Socket | null = null;

export const useRealTimeUpdates = () => {
  const dispatch = useDispatch();

  useEffect(() => {
    // Initialize socket connection
    if (!socket) {
      socket = io(process.env.REACT_APP_WS_URL || 'http://localhost:3001', {
        auth: {
          token: localStorage.getItem('token'),
        },
      });
    }

    // Listen for job updates
    socket.on('job:updated', (data) => {
      dispatch(updateJob(data));
      dispatch(addNotification({
        type: 'info',
        message: `Job ${data.jobNumber} updated`,
      }));
    });

    // Listen for new jobs
    socket.on('job:created', (data) => {
      dispatch(addNotification({
        type: 'success',
        message: `New job ${data.jobNumber} created`,
      }));
    });

    // Listen for PDSS updates
    socket.on('pdss:status_changed', (data) => {
      dispatch(addNotification({
        type: 'info',
        message: `PDSS status updated for job ${data.jobNumber}`,
      }));
    });

    return () => {
      socket?.off('job:updated');
      socket?.off('job:created');
      socket?.off('pdss:status_changed');
    };
  }, [dispatch]);

  return socket;
};

Form Handling Pattern

// components/jobs/CreateJobForm.tsx
import React from 'react';
import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
import {
  Box,
  TextField,
  Button,
  Select,
  MenuItem,
  FormControl,
  InputLabel,
} from '@mui/material';

const schema = yup.object({
  jobNumber: yup.string().required('Job number is required'),
  lotNumber: yup.string().required('Lot number is required'),
  subdivisionId: yup.string().required('Subdivision is required'),
  planId: yup.string().required('Plan is required'),
  elevation: yup.string().required('Elevation is required'),
  clientName: yup.string().required('Client name is required'),
  clientEmail: yup.string().email('Invalid email'),
  priority: yup.string().oneOf(['low', 'medium', 'high', 'urgent']),
}).required();

const CreateJobForm: React.FC = () => {
  const {
    control,
    handleSubmit,
    formState: { errors },
  } = useForm({
    resolver: yupResolver(schema),
    defaultValues: {
      priority: 'medium',
    },
  });

  const onSubmit = async (data: any) => {
    try {
      // API call to create job
      console.log('Creating job:', data);
    } catch (error) {
      console.error('Error creating job:', error);
    }
  };

  return (
    <Box component="form" onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="jobNumber"
        control={control}
        render={({ field }) => (
          <TextField
            {...field}
            label="Job Number"
            error={!!errors.jobNumber}
            helperText={errors.jobNumber?.message}
            fullWidth
            sx={{ mb: 2 }}
          />
        )}
      />

      {/* Additional form fields... */}

      <Button type="submit" variant="contained" fullWidth>
        Create Job
      </Button>
    </Box>
  );
};

Responsive Design Patterns

Mobile-First Grid Layout

<Grid container spacing={{ xs: 2, md: 3 }}>
  <Grid item xs={12} sm={6} md={4} lg={3}>
    {/* Component */}
  </Grid>
</Grid>

Conditional Rendering for Mobile

import { useMediaQuery, useTheme } from '@mui/material';

const MyComponent = () => {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));

  return (
    <Box>
      {isMobile ? (
        <MobileView />
      ) : (
        <DesktopView />
      )}
    </Box>
  );
};

Performance Optimization

Memoization

import React, { useMemo } from 'react';

const ExpensiveComponent = ({ jobs }) => {
  const sortedJobs = useMemo(() => {
    return jobs.sort((a, b) => 
      new Date(b.createdAt) - new Date(a.createdAt)
    );
  }, [jobs]);

  return <>{/* Render sorted jobs */}</>;
};

Virtual Scrolling for Large Lists

import { FixedSizeList } from 'react-window';

const VirtualJobList = ({ jobs }) => {
  const Row = ({ index, style }) => (
    <div style={style}>
      <JobCard job={jobs[index]} />
    </div>
  );

  return (
    <FixedSizeList
      height={600}
      itemCount={jobs.length}
      itemSize={120}
      width="100%"
    >
      {Row}
    </FixedSizeList>
  );
};

Testing Standards

// components/__tests__/PlanOptionSelector.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import PlanOptionSelector from '../PlanOptionSelector';

describe('PlanOptionSelector', () => {
  it('renders all option categories', () => {
    render(<PlanOptionSelector planId="123" elevation="A" />);
    
    expect(screen.getByText('Exterior')).toBeInTheDocument();
    expect(screen.getByText('Interior')).toBeInTheDocument();
  });

  it('disables conflicting options', () => {
    render(<PlanOptionSelector planId="123" elevation="A" />);
    
    const hardwoodCheckbox = screen.getByLabelText('Hardwood Floors');
    fireEvent.click(hardwoodCheckbox);

    const carpetCheckbox = screen.getByLabelText('Carpet');
    expect(carpetCheckbox).toBeDisabled();
  });
});