task_receipts/client
2025-06-17 20:36:41 -05:00
..
public update everything 2025-06-14 15:57:24 -05:00
src Fix screensaver animation blinking issue - Remove frequent screen clearing that caused black frames every few seconds - Keep only the 3-minute clear cycle for burn-in protection - Ensure smooth animation loop by scheduling next frame before any clearing - Eliminate brief black flashes that occurred at animation cycle boundaries - Maintain continuous visual flow without interruption 2025-06-17 20:36:41 -05:00
.gitignore update everything 2025-06-14 15:57:24 -05:00
eslint.config.js update everything 2025-06-14 15:57:24 -05:00
index.html add print buttons to mobile 2025-06-14 23:09:12 -05:00
package-lock.json update everything 2025-06-14 15:57:24 -05:00
package.json refactor: use Zustand for task state, optimize GraphQL requests, and fix recursive setState bug 2025-06-17 18:24:34 -05:00
README.md refactor: use Zustand for task state, optimize GraphQL requests, and fix recursive setState bug 2025-06-17 18:24:34 -05:00
tsconfig.app.json update everything 2025-06-14 15:57:24 -05:00
tsconfig.json update everything 2025-06-14 15:57:24 -05:00
tsconfig.node.json update everything 2025-06-14 15:57:24 -05:00
vite.config.ts update everything 2025-06-14 15:57:24 -05:00

React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

export default tseslint.config({
  extends: [
    // Remove ...tseslint.configs.recommended and replace with this
    ...tseslint.configs.recommendedTypeChecked,
    // Alternatively, use this for stricter rules
    ...tseslint.configs.strictTypeChecked,
    // Optionally, add this for stylistic rules
    ...tseslint.configs.stylisticTypeChecked,
  ],
  languageOptions: {
    // other options...
    parserOptions: {
      project: ['./tsconfig.node.json', './tsconfig.app.json'],
      tsconfigRootDir: import.meta.dirname,
    },
  },
})

You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:

// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default tseslint.config({
  plugins: {
    // Add the react-x and react-dom plugins
    'react-x': reactX,
    'react-dom': reactDom,
  },
  rules: {
    // other rules...
    // Enable its recommended typescript rules
    ...reactX.configs['recommended-typescript'].rules,
    ...reactDom.configs.recommended.rules,
  },
})

Task Receipts Client

A React application for managing task receipts with GraphQL API integration and Zustand state management.

Architecture

State Management with Zustand

The application uses Zustand for state management to optimize GraphQL API requests and improve performance:

Key Features:

  • Centralized State: All task data is stored in a single Zustand store
  • Optimized Queries: GraphQL queries are only made when data is not already available in the store
  • Efficient Updates: Mutations update the store directly, reducing the need for refetching
  • Selective Rendering: Components only re-render when their specific data changes

Store Structure:

interface TaskState {
  // Data
  groups: GroupWithTasks[];
  recentTasks: TaskWithSteps[];
  frequentTasks: TaskWithSteps[];
  currentStep: StepWithNotes | null;

  // Loading states
  isLoadingGroups: boolean;
  isLoadingRecentTasks: boolean;
  isLoadingFrequentTasks: boolean;
  isLoadingStep: boolean;

  // Selection state
  selectedGroup: GroupWithTasks | undefined;
  selectedTask: TaskWithSteps | undefined;
  selectedStep: StepWithNotes | undefined;

  // Actions and helper methods...
}

Hooks:

  1. useTaskDataOptimized: Main hook that manages GraphQL queries and store updates
  2. useTaskSelector: Collection of selector hooks for efficient data access
  3. useTaskStore: Direct access to the Zustand store

Performance Optimizations:

  • Skip Queries: Queries are skipped if data already exists in the store
  • Cache-First Policy: Apollo Client uses cache-first for queries
  • Selective Updates: Only relevant parts of the store are updated
  • Efficient Selectors: Components subscribe only to the data they need

GraphQL Integration

The application uses Apollo Client for GraphQL operations with optimized caching policies:

  • Cache-First: Queries prioritize cached data
  • Cache-and-Network: Watch queries update from cache first, then network
  • Optimistic Updates: Mutations update the store immediately

Component Structure

  • App.tsx: Main application component using the optimized hook
  • Layouts: Desktop and mobile layouts for different screen sizes
  • Components: Reusable UI components
  • Hooks: Custom hooks for data management and device detection

Development

Prerequisites

  • Node.js 18+
  • npm or yarn

Installation

npm install

Development Server

npm run dev

Build

npm run build

State Management Flow

  1. Initial Load:

    • useTaskDataOptimized checks if data exists in store
    • If not, makes GraphQL queries to fetch data
    • Updates store with fetched data
  2. User Interactions:

    • Selection changes update store directly
    • Mutations update store optimistically
    • Components re-render only when their data changes
  3. Data Persistence:

    • Store maintains data across component unmounts
    • Queries are skipped if data is already available
    • Cache policies ensure efficient data retrieval

Benefits

  • Reduced API Calls: Data is fetched once and reused
  • Better Performance: Components only re-render when necessary
  • Improved UX: Faster navigation and interactions
  • Maintainable Code: Centralized state management
  • Type Safety: Full TypeScript support with proper typing