turash/bugulma/frontend/BACKEND_ALIGNMENT.md
Damir Mukimov 6347f42e20
Consolidate repositories: Remove nested frontend .git and merge into main repository
- Remove nested git repository from bugulma/frontend/.git
- Add all frontend files to main repository tracking
- Convert from separate frontend/backend repos to unified monorepo
- Preserve all frontend code and development history as tracked files
- Eliminate nested repository complexity for simpler development workflow

This creates a proper monorepo structure with frontend and backend
coexisting in the same repository for easier development and deployment.
2025-11-25 06:02:57 +01:00

5.6 KiB

Frontend-Backend Alignment

This document describes the alignment between the frontend and the enhanced Go backend.

Architecture Overview

The frontend now communicates with the backend through:

  1. API Client Layer (lib/api-client.ts): Base HTTP client with authentication
  2. Service Layer (services/*-api.ts): Type-safe API service functions
  3. React Hooks (hooks/api/*.ts): React Query hooks for data fetching and mutations
  4. Backend Schemas (schemas/backend/*.ts): Zod schemas matching backend domain models

API Endpoints

Authentication

  • POST /auth/login - JWT authentication

Organizations

  • GET /api/organizations - List all organizations
  • GET /api/organizations/:id - Get organization by ID
  • POST /api/organizations - Create organization
  • DELETE /api/organizations/:id - Delete organization

Sites

  • POST /api/sites - Create site
  • GET /api/sites/:id - Get site by ID
  • GET /api/sites/business/:businessId - Get sites by business
  • GET /api/sites/nearby?lat=&lng=&radius= - Find sites within radius
  • DELETE /api/sites/:id - Delete site

Resource Flows

  • POST /api/resources - Create resource flow
  • GET /api/resources/:id - Get resource flow by ID
  • GET /api/resources/site/:siteId - Get flows by site
  • GET /api/resources/business/:businessId - Get flows by business
  • DELETE /api/resources/:id - Delete resource flow

Matching Engine

  • GET /api/matching/resource/:resourceId?max_distance_km=50&min_score=0.3&limit=20 - Find matches for a resource

Data Models

Organization

  • Simplified compared to frontend's previous model
  • No embedded needs/offers (these are now separate ResourceFlow entities)
  • Fields: ID, Name, Sector, Description, LogoURL, Website, Address, Verified, CreatedAt, UpdatedAt

Site

  • Represents a physical location
  • Fields: ID, Name, Address, Latitude, Longitude, SiteType, FloorAreaM2, OwnerBusinessID, CreatedAt, UpdatedAt

ResourceFlow

  • Represents input/output resource flows
  • Direction: input or output
  • Types: heat, water, steam, CO2, biowaste, cooling, logistics, materials, service
  • Includes: Quality, Quantity, TimeProfile, EconomicData, Constraints, ServiceDetails
  • Precision levels: rough, estimated, measured
  • Source types: declared, device, calculated

Match

  • Represents a match between two resource flows
  • Status: suggested, negotiating, reserved, contracted, live, failed, cancelled
  • Includes: CompatibilityScore, EconomicValue, DistanceKm, RiskAssessment, EconomicImpact, TransportationEstimate

Usage Examples

Using Organizations API

import { useOrganizations, useCreateOrganization } from '@/hooks/api';

function OrganizationsList() {
  const { data: organizations, isLoading } = useOrganizations();
  const createOrg = useCreateOrganization();

  const handleCreate = async () => {
    await createOrg.mutateAsync({
      name: 'New Organization',
      sector: '35.30',
      description: 'Description',
    });
  };

  // ...
}

Using Resource Flows API

import { useResourceFlowsByBusiness, useCreateResourceFlow } from '@/hooks/api';

function ResourceFlowsList({ businessId }: { businessId: string }) {
  const { data: flows } = useResourceFlowsByBusiness(businessId);
  const createFlow = useCreateResourceFlow();

  const handleCreate = async () => {
    await createFlow.mutateAsync({
      business_id: businessId,
      site_id: 'site-id',
      direction: 'output',
      type: 'heat',
      quantity: {
        amount: 500,
        unit: 'kWh',
        temporal_unit: 'per_hour',
      },
      quality: {
        temperature_celsius: 65.0,
        physical_state: 'liquid',
      },
    });
  };

  // ...
}

Using Matching API

import { useFindMatches } from '@/hooks/api';

function MatchesList({ resourceId }: { resourceId: string }) {
  const { data: matchesData } = useFindMatches(resourceId, {
    max_distance_km: 30,
    min_score: 0.3,
    limit: 10,
  });

  // matchesData.matches contains the array of matches
  // matchesData.count contains the count
}

Authentication

The AuthContext has been updated to:

  • Use the API client's login function
  • Decode JWT tokens to extract user information
  • Store tokens in localStorage
  • Automatically include Bearer tokens in API requests

Migration Notes

Breaking Changes

  1. Organization Model: The frontend's previous organization model included embedded needs and offers. These are now separate ResourceFlow entities that must be created independently.

  2. Field Naming: Backend uses Go's default JSON encoding (capitalized field names) for main structs, but snake_case for nested structs. The schemas reflect this.

  3. Data Structure: Organizations no longer contain resource flows directly. Use useResourceFlowsByBusiness(businessId) to fetch related resource flows.

Next Steps

  1. Update components that display organizations to use the new API hooks
  2. Create components for managing resource flows separately
  3. Implement match visualization and management UI
  4. Add error handling and loading states throughout
  5. Consider adding optimistic updates for better UX

Field Name Convention

Note: The backend Go structs use capitalized field names (Go's default JSON encoding) for main entities, but nested structs use snake_case JSON tags. The frontend schemas match this convention:

  • Main struct fields: ID, Name, Sector, etc. (capitalized)
  • Nested struct fields: temperature_celsius, cost_in, etc. (snake_case)

If the actual API responses differ, adjust the schemas accordingly.