Almost ready

This commit is contained in:
Eric Gullickson
2025-11-08 15:34:29 -06:00
parent bb4a356b9e
commit 408a0736c0
7 changed files with 66 additions and 60 deletions

View File

@@ -25,12 +25,12 @@ Maintain professional documentation standards without emoji usage.
File: `frontend/package.json`
- Add `"{package}": "{version}"` to dependencies
- No npm install needed - handled by container rebuild
- Testing: `make rebuild` then verify container starts
- Testing: Instruct user to rebuild the containers and report back build errors
### 2. Container-Validated Development Workflow (Production-only)
```bash
# After each change:
make rebuild # Rebuilds containers with new dependencies
Instruct user to rebuild the containers and report back build errors
make logs # Monitor for build/runtime errors
```

View File

@@ -125,18 +125,32 @@ export class StationsService {
async getUserSavedStations(userId: string) {
const savedStations = await this.repository.getUserSavedStations(userId);
// Enrich with cached station data
const enriched = await Promise.all(
savedStations.map(async (saved: SavedStation) => {
const station = await this.repository.getCachedStation(saved.stationId);
// Flatten station data into top level to match frontend SavedStation type
// Frontend expects SavedStation to extend Station
return {
...saved,
// Merge cached station data at top level (with fallbacks if cache miss)
name: station?.name || saved.nickname || 'Saved Station',
address: station?.address || '',
latitude: station?.latitude || 0,
longitude: station?.longitude || 0,
rating: station?.rating,
photoUrl: station?.photoUrl,
priceRegular: station?.priceRegular,
pricePremium: station?.pricePremium,
priceDiesel: station?.priceDiesel,
// Keep nested station for compatibility
station
};
})
);
return enriched;
}

View File

@@ -11,7 +11,7 @@ Project documentation hub for the 5-container single-tenant architecture with in
- Testing (containers only): `docs/TESTING.md`
- Database Migration: `docs/DATABASE-MIGRATION.md`
- Admin feature: `docs/ADMIN.md` - Role management, APIs, catalog CRUD, station oversight
- Development commands: `Makefile`, `docker-compose.yml`
- Development Environment: `docker-compose.yml`
- Application features (start at each README):
- `backend/src/features/admin/README.md` - Admin role management and oversight
- `backend/src/features/platform/README.md` - Vehicle data and VIN decoding

View File

@@ -84,14 +84,14 @@ export const FuelLogsPage: React.FC = () => {
<FuelLogForm />
</Grid>
<Grid item xs={12} md={6}>
<Typography variant="h6" gutterBottom>Recent Fuel Logs</Typography>
<Typography variant="h6" gutterBottom>Summary</Typography>
<FuelStatsCard logs={fuelLogs} />
<Typography variant="h6" sx={{ mt: 3 }} gutterBottom>Recent Fuel Logs</Typography>
<FuelLogsList
logs={fuelLogs}
onEdit={handleEdit}
onDelete={handleDelete}
/>
<Typography variant="h6" sx={{ mt: 3 }} gutterBottom>Summary</Typography>
<FuelStatsCard logs={fuelLogs} />
</Grid>
</Grid>

View File

@@ -1,10 +1,10 @@
/**
* @ai-summary Reusable checkbox group for maintenance subtype selection
* @ai-context Responsive grid layout with proper mobile touch targets
* @ai-summary Multi-select dropdown for maintenance subtype selection
* @ai-context Material-UI Autocomplete with proper mobile touch targets
*/
import React from 'react';
import { FormGroup, FormControlLabel, Checkbox, Box } from '@mui/material';
import { Autocomplete, TextField, Chip } from '@mui/material';
import { MaintenanceCategory, getSubtypesForCategory } from '../types/maintenance.types';
interface SubtypeCheckboxGroupProps {
@@ -20,52 +20,44 @@ export const SubtypeCheckboxGroup: React.FC<SubtypeCheckboxGroupProps> = ({
}) => {
const availableSubtypes = getSubtypesForCategory(category);
const handleToggle = (subtype: string) => {
const newSelected = selected.includes(subtype)
? selected.filter((s) => s !== subtype)
: [...selected, subtype];
onChange(newSelected);
};
return (
<Box
sx={{
display: 'grid',
gridTemplateColumns: {
xs: '1fr',
sm: 'repeat(2, 1fr)',
md: 'repeat(3, 1fr)',
},
gap: 1,
}}
>
<FormGroup>
{availableSubtypes.map((subtype) => (
<FormControlLabel
key={subtype}
control={
<Checkbox
checked={selected.includes(subtype)}
onChange={() => handleToggle(subtype)}
sx={{
minWidth: 44,
minHeight: 44,
'& .MuiSvgIcon-root': {
fontSize: 24,
},
}}
/>
}
label={subtype}
<Autocomplete
multiple
options={Array.from(availableSubtypes)}
value={selected}
onChange={(_, newValue) => onChange(newValue)}
disableCloseOnSelect
renderInput={(params) => (
<TextField
{...params}
label="Select Subtypes"
placeholder={selected.length === 0 ? 'Choose one or more...' : ''}
sx={{
'& .MuiOutlinedInput-root': {
minHeight: 56,
},
}}
/>
)}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<Chip
label={option}
{...getTagProps({ index })}
key={option}
sx={{
minHeight: 44,
'& .MuiFormControlLabel-label': {
fontSize: { xs: 14, sm: 16 },
},
height: 32,
fontSize: { xs: 13, sm: 14 },
}}
/>
))}
</FormGroup>
</Box>
))
}
sx={{
'& .MuiAutocomplete-option': {
minHeight: 44,
fontSize: { xs: 14, sm: 16 },
},
}}
/>
);
};

View File

@@ -86,14 +86,14 @@ export const MaintenancePage: React.FC = () => {
return (
<FormSuspense>
<Grid container spacing={2}>
{/* Left Column: Form */}
<Grid item xs={12} md={6}>
<Grid container spacing={3}>
{/* Top: Form */}
<Grid item xs={12}>
<MaintenanceRecordForm />
</Grid>
{/* Right Column: Records List */}
<Grid item xs={12} md={6}>
{/* Bottom: Records List */}
<Grid item xs={12}>
<Typography variant="h6" gutterBottom>
Recent Maintenance Records
</Typography>

View File

@@ -46,6 +46,7 @@ export const StationMap: React.FC<StationMapProps> = ({
const infoWindows = useRef<google.maps.InfoWindow[]>([]);
const currentLocationMarker = useRef<google.maps.marker.AdvancedMarkerElement | null>(null);
const isInitializing = useRef<boolean>(false);
const mapIdRef = useRef<string | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
@@ -368,4 +369,3 @@ export const StationMap: React.FC<StationMapProps> = ({
};
export default StationMap;
const mapIdRef = useRef<string | null>(null);