diff --git a/frontend/src/features/fuel-logs/components/FuelLogForm.tsx b/frontend/src/features/fuel-logs/components/FuelLogForm.tsx index 051c87f..2b5cd34 100644 --- a/frontend/src/features/fuel-logs/components/FuelLogForm.tsx +++ b/frontend/src/features/fuel-logs/components/FuelLogForm.tsx @@ -19,6 +19,8 @@ import { useFuelLogs } from '../hooks/useFuelLogs'; import { useUserSettings } from '../hooks/useUserSettings'; import { useReceiptOcr } from '../hooks/useReceiptOcr'; import { useGeolocation } from '../../stations/hooks/useGeolocation'; +import { useTierAccess } from '../../../core/hooks/useTierAccess'; +import { UpgradeRequiredDialog } from '../../../shared-minimal/components/UpgradeRequiredDialog'; import { CameraCapture } from '../../../shared/components/CameraCapture'; import { CreateFuelLogRequest, FuelType } from '../types/fuel-logs.types'; @@ -48,6 +50,11 @@ const FuelLogFormComponent: React.FC<{ onSuccess?: () => void; initial?: Partial // Get user location for nearby station search const { coordinates: userLocation } = useGeolocation(); + // Tier access check for receipt scan feature + const { hasAccess } = useTierAccess(); + const hasReceiptScanAccess = hasAccess('fuelLog.receiptScan'); + const [showUpgradeDialog, setShowUpgradeDialog] = useState(false); + // Receipt OCR integration const { isCapturing, @@ -217,9 +224,16 @@ const FuelLogFormComponent: React.FC<{ onSuccess?: () => void; initial?: Partial }} > { + if (!hasReceiptScanAccess) { + setShowUpgradeDialog(true); + return; + } + startCapture(); + }} disabled={isProcessing || isLoading} variant="button" + locked={!hasReceiptScanAccess} /> @@ -436,6 +450,13 @@ const FuelLogFormComponent: React.FC<{ onSuccess?: () => void; initial?: Partial /> )} + {/* Upgrade Required Dialog for Receipt Scan */} + setShowUpgradeDialog(false)} + /> + {/* OCR Error Display */} {ocrError && ( diff --git a/frontend/src/features/fuel-logs/components/ReceiptCameraButton.tsx b/frontend/src/features/fuel-logs/components/ReceiptCameraButton.tsx index 4dad8ed..3e7839f 100644 --- a/frontend/src/features/fuel-logs/components/ReceiptCameraButton.tsx +++ b/frontend/src/features/fuel-logs/components/ReceiptCameraButton.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { Button, IconButton, Tooltip, useTheme, useMediaQuery } from '@mui/material'; import CameraAltIcon from '@mui/icons-material/CameraAlt'; import ReceiptIcon from '@mui/icons-material/Receipt'; +import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; export interface ReceiptCameraButtonProps { /** Called when user clicks to start capture */ @@ -17,6 +18,8 @@ export interface ReceiptCameraButtonProps { variant?: 'icon' | 'button' | 'auto'; /** Size of the button */ size?: 'small' | 'medium' | 'large'; + /** Whether the feature is locked behind a tier gate */ + locked?: boolean; } export const ReceiptCameraButton: React.FC = ({ @@ -24,6 +27,7 @@ export const ReceiptCameraButton: React.FC = ({ disabled = false, variant = 'auto', size = 'medium', + locked = false, }) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); @@ -31,28 +35,30 @@ export const ReceiptCameraButton: React.FC = ({ // Determine display variant const displayVariant = variant === 'auto' ? (isMobile ? 'icon' : 'button') : variant; + const tooltipTitle = locked ? 'Upgrade to Pro to scan receipts' : 'Scan Receipt'; + if (displayVariant === 'icon') { return ( - + - + {locked ? : } @@ -60,23 +66,27 @@ export const ReceiptCameraButton: React.FC = ({ } return ( - + + + + + ); };