Compare commits

...

2 Commits

Author SHA1 Message Date
e729d425fd Merge pull request 'feat: Reorder Log Fuel fields by usage and add decimal keypad (#246)' (#247) from issue-246-reorder-log-fuel-fields into main
All checks were successful
Deploy to Staging / Build Images (push) Successful in 1m2s
Deploy to Staging / Deploy to Staging (push) Successful in 42s
Deploy to Staging / Verify Staging (push) Successful in 4s
Deploy to Staging / Notify Staging Ready (push) Successful in 3s
Deploy to Staging / Notify Staging Failure (push) Has been skipped
Mirror Base Images / Mirror Base Images (push) Successful in 28s
Reviewed-on: #247
2026-06-20 03:44:26 +00:00
Eric Gullickson
2221819b4a feat: reorder Log Fuel fields by usage and add decimal keypad (refs #246)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 4m10s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 44s
Deploy to Staging / Verify Staging (pull_request) Successful in 4s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 4s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
Reorder the Add Fuel Log form so the most-used inputs come first and
calculated/auto-filled fields are de-emphasized:
Vehicle, Mileage, Cost Per Gallon, Fuel Amount, Fuel Type/Grade,
Location, MPG (read-only), Notes, Date & Time.

Mileage is the existing Trip Distance / Odometer Reading field,
repositioned only; toggle and logic unchanged. Fuel Type stays before
Fuel Grade to preserve the type-filters-grade dependency.

Add inputMode=decimal to the numeric fields (Mileage via DistanceInput,
Fuel Amount, Cost Per Gallon) so mobile shows the decimal keypad. MPG
and Date & Time become full-width since they are no longer paired.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 22:18:46 -05:00
2 changed files with 86 additions and 76 deletions

View File

@@ -24,7 +24,7 @@ export const DistanceInput: React.FC<Props> = ({ type, value, onChange, unitSyst
fullWidth
error={!!error}
disabled={disabled}
inputProps={{ step: type === 'trip' ? 0.1 : 1, min: 0 }}
inputProps={{ step: type === 'trip' ? 0.1 : 1, min: 0, inputMode: 'decimal' }}
InputProps={{ endAdornment: <InputAdornment position="end">{units}</InputAdornment> }}
/>
{error && <FormHelperText error>{error}</FormHelperText>}

View File

@@ -247,60 +247,7 @@ const FuelLogFormComponent: React.FC<{ onSuccess?: () => void; initial?: Partial
)} />
</Grid>
{/* Row 2: Date/Time | MPG/L/100km */}
<Grid item xs={12} sm={6}>
<Controller name="dateTime" control={control} render={({ field }) => (
<DateTimePicker
label="Date & Time"
value={field.value ? dayjs(field.value) : null}
onChange={(newValue) => field.onChange(newValue?.toISOString() || '')}
format="MM/DD/YYYY hh:mm a"
slotProps={{
textField: {
fullWidth: true,
error: !!errors.dateTime,
helperText: errors.dateTime?.message,
sx: {
'& .MuiOutlinedInput-root': {
minHeight: '56px',
}
}
}
}}
/>
)} />
</Grid>
<Grid item xs={12} sm={6}>
<TextField
label={`${userSettings?.unitSystem === 'metric' ? 'L/100km' : 'MPG'}`}
value={calculatedEfficiency > 0 ? calculatedEfficiency.toFixed(3) : ''}
fullWidth
InputProps={{
readOnly: true,
sx: (theme) => ({
backgroundColor: 'grey.50',
...theme.applyStyles('dark', {
backgroundColor: '#4C4E4D',
}),
'& .MuiOutlinedInput-input': {
cursor: 'default',
color: 'inherit',
...theme.applyStyles('dark', {
color: '#F2F3F6',
}),
},
}),
}}
helperText="Calculated from distance ÷ fuel amount"
sx={{
'& .MuiOutlinedInput-root': {
minHeight: '56px',
}
}}
/>
</Grid>
{/* Row 3: Odometer | Distance Input Method */}
{/* Row 2: Mileage (Trip Distance / Odometer) | Input Method Toggle */}
<Grid item xs={12} sm={6}>
<Controller name={useOdometer ? 'odometerReading' : 'tripDistance'} control={control} render={({ field }) => (
<DistanceInput type={useOdometer ? 'odometer' : 'trip'} value={field.value as any} onChange={field.onChange as any} unitSystem={userSettings?.unitSystem} error={useOdometer ? (errors.odometerReading?.message as any) : (errors.tripDistance?.message as any)} />
@@ -342,11 +289,21 @@ const FuelLogFormComponent: React.FC<{ onSuccess?: () => void; initial?: Partial
</ToggleButton>
</ToggleButtonGroup>
</Grid>
<Grid item xs={12}>
<Controller name="fuelType" control={control} render={({ field: fuelTypeField }) => (
<Controller name="fuelGrade" control={control} render={({ field: fuelGradeField }) => (
<FuelTypeSelector fuelType={fuelTypeField.value} fuelGrade={fuelGradeField.value as any} onFuelTypeChange={fuelTypeField.onChange} onFuelGradeChange={fuelGradeField.onChange as any} error={(errors.fuelType?.message as any) || (errors.fuelGrade?.message as any)} />
)} />
{/* Row 3: Cost Per Gallon | Fuel Amount */}
<Grid item xs={12} sm={6}>
<Controller name="costPerUnit" control={control} render={({ field }) => (
<TextField
{...field}
value={field.value ?? ''}
onChange={(e) => field.onChange(e.target.value)}
label={`Cost Per ${userSettings?.unitSystem === 'imperial' ? 'Gallon' : 'Liter'}`}
type="number"
inputProps={{ step: 0.001, min: 0.001, inputMode: 'decimal' }}
fullWidth
error={!!errors.costPerUnit}
helperText={errors.costPerUnit?.message}
/>
)} />
</Grid>
<Grid item xs={12} sm={6}>
@@ -357,31 +314,27 @@ const FuelLogFormComponent: React.FC<{ onSuccess?: () => void; initial?: Partial
onChange={(e) => field.onChange(e.target.value)}
label={`Fuel Amount (${userSettings?.unitSystem === 'imperial' ? 'gallons' : 'liters'})`}
type="number"
inputProps={{ step: 0.001, min: 0.001 }}
inputProps={{ step: 0.001, min: 0.001, inputMode: 'decimal' }}
fullWidth
error={!!errors.fuelUnits}
helperText={errors.fuelUnits?.message}
/>
)} />
</Grid>
<Grid item xs={12} sm={6}>
<Controller name="costPerUnit" control={control} render={({ field }) => (
<TextField
{...field}
value={field.value ?? ''}
onChange={(e) => field.onChange(e.target.value)}
label={`Cost Per ${userSettings?.unitSystem === 'imperial' ? 'Gallon' : 'Liter'}`}
type="number"
inputProps={{ step: 0.001, min: 0.001 }}
fullWidth
error={!!errors.costPerUnit}
helperText={errors.costPerUnit?.message}
/>
)} />
</Grid>
<Grid item xs={12}>
<CostCalculator fuelUnits={fuelUnits} costPerUnit={costPerUnit} calculatedCost={calculatedCost} />
</Grid>
{/* Row 4: Fuel Type / Fuel Grade (grade options filtered by type) */}
<Grid item xs={12}>
<Controller name="fuelType" control={control} render={({ field: fuelTypeField }) => (
<Controller name="fuelGrade" control={control} render={({ field: fuelGradeField }) => (
<FuelTypeSelector fuelType={fuelTypeField.value} fuelGrade={fuelGradeField.value as any} onFuelTypeChange={fuelTypeField.onChange} onFuelGradeChange={fuelGradeField.onChange as any} error={(errors.fuelType?.message as any) || (errors.fuelGrade?.message as any)} />
)} />
)} />
</Grid>
{/* Row 5: Location */}
<Grid item xs={12}>
<Controller name="locationData" control={control} render={({ field }) => (
<StationPicker
@@ -392,11 +345,68 @@ const FuelLogFormComponent: React.FC<{ onSuccess?: () => void; initial?: Partial
/>
)} />
</Grid>
{/* Row 6: MPG/L/100km (calculated, read-only) */}
<Grid item xs={12}>
<TextField
label={`${userSettings?.unitSystem === 'metric' ? 'L/100km' : 'MPG'}`}
value={calculatedEfficiency > 0 ? calculatedEfficiency.toFixed(3) : ''}
fullWidth
InputProps={{
readOnly: true,
sx: (theme) => ({
backgroundColor: 'grey.50',
...theme.applyStyles('dark', {
backgroundColor: '#4C4E4D',
}),
'& .MuiOutlinedInput-input': {
cursor: 'default',
color: 'inherit',
...theme.applyStyles('dark', {
color: '#F2F3F6',
}),
},
}),
}}
helperText="Calculated from distance ÷ fuel amount"
sx={{
'& .MuiOutlinedInput-root': {
minHeight: '56px',
}
}}
/>
</Grid>
{/* Row 7: Notes */}
<Grid item xs={12}>
<Controller name="notes" control={control} render={({ field }) => (
<TextField {...field} label="Notes (optional)" multiline rows={3} fullWidth error={!!errors.notes} helperText={errors.notes?.message} />
)} />
</Grid>
{/* Row 8: Date & Time (defaults to now, least-edited field) */}
<Grid item xs={12}>
<Controller name="dateTime" control={control} render={({ field }) => (
<DateTimePicker
label="Date & Time"
value={field.value ? dayjs(field.value) : null}
onChange={(newValue) => field.onChange(newValue?.toISOString() || '')}
format="MM/DD/YYYY hh:mm a"
slotProps={{
textField: {
fullWidth: true,
error: !!errors.dateTime,
helperText: errors.dateTime?.message,
sx: {
'& .MuiOutlinedInput-root': {
minHeight: '56px',
}
}
}
}}
/>
)} />
</Grid>
<Grid item xs={12}>
<Box display="flex" gap={2} justifyContent="flex-end">
<Button type="submit" variant="contained" disabled={!isValid || isLoading} startIcon={isLoading ? <CircularProgress size={18} /> : undefined}>Add Fuel Log</Button>