feat: add Subscription section to Settings page (refs #55)
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 2m51s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 39s
Deploy to Staging / Verify Staging (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 2m51s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 39s
Deploy to Staging / Verify Staging (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
Added a Subscription section to the desktop Settings page that displays: - Current subscription tier (Free/Pro/Enterprise) - Status indicator for non-active subscriptions - Manage button linking to the subscription management page - Descriptive text based on current tier 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import { useAdminAccess } from '../core/auth/useAdminAccess';
|
|||||||
import { useProfile, useUpdateProfile } from '../features/settings/hooks/useProfile';
|
import { useProfile, useUpdateProfile } from '../features/settings/hooks/useProfile';
|
||||||
import { useExportUserData } from '../features/settings/hooks/useExportUserData';
|
import { useExportUserData } from '../features/settings/hooks/useExportUserData';
|
||||||
import { useVehicles } from '../features/vehicles/hooks/useVehicles';
|
import { useVehicles } from '../features/vehicles/hooks/useVehicles';
|
||||||
|
import { useSubscription } from '../features/subscription/hooks/useSubscription';
|
||||||
import { useTheme } from '../shared-minimal/theme/ThemeContext';
|
import { useTheme } from '../shared-minimal/theme/ThemeContext';
|
||||||
import { DeleteAccountDialog } from '../features/settings/components/DeleteAccountDialog';
|
import { DeleteAccountDialog } from '../features/settings/components/DeleteAccountDialog';
|
||||||
import { PendingDeletionBanner } from '../features/settings/components/PendingDeletionBanner';
|
import { PendingDeletionBanner } from '../features/settings/components/PendingDeletionBanner';
|
||||||
@@ -32,7 +33,8 @@ import {
|
|||||||
MenuItem,
|
MenuItem,
|
||||||
FormControl,
|
FormControl,
|
||||||
TextField,
|
TextField,
|
||||||
CircularProgress
|
CircularProgress,
|
||||||
|
Chip
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
||||||
import NotificationsIcon from '@mui/icons-material/Notifications';
|
import NotificationsIcon from '@mui/icons-material/Notifications';
|
||||||
@@ -41,6 +43,7 @@ import SecurityIcon from '@mui/icons-material/Security';
|
|||||||
import StorageIcon from '@mui/icons-material/Storage';
|
import StorageIcon from '@mui/icons-material/Storage';
|
||||||
import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings';
|
import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings';
|
||||||
import DirectionsCarIcon from '@mui/icons-material/DirectionsCar';
|
import DirectionsCarIcon from '@mui/icons-material/DirectionsCar';
|
||||||
|
import CreditCardIcon from '@mui/icons-material/CreditCard';
|
||||||
import EditIcon from '@mui/icons-material/Edit';
|
import EditIcon from '@mui/icons-material/Edit';
|
||||||
import SaveIcon from '@mui/icons-material/Save';
|
import SaveIcon from '@mui/icons-material/Save';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
@@ -62,6 +65,11 @@ export const SettingsPage: React.FC = () => {
|
|||||||
|
|
||||||
// Vehicles state (for My Vehicles section)
|
// Vehicles state (for My Vehicles section)
|
||||||
const { data: vehicles, isLoading: vehiclesLoading } = useVehicles();
|
const { data: vehicles, isLoading: vehiclesLoading } = useVehicles();
|
||||||
|
|
||||||
|
// Subscription state
|
||||||
|
const { data: subscriptionData, isLoading: subscriptionLoading } = useSubscription();
|
||||||
|
const subscription = subscriptionData?.data;
|
||||||
|
|
||||||
const [isEditingProfile, setIsEditingProfile] = useState(false);
|
const [isEditingProfile, setIsEditingProfile] = useState(false);
|
||||||
const [editedDisplayName, setEditedDisplayName] = useState('');
|
const [editedDisplayName, setEditedDisplayName] = useState('');
|
||||||
const [editedNotificationEmail, setEditedNotificationEmail] = useState('');
|
const [editedNotificationEmail, setEditedNotificationEmail] = useState('');
|
||||||
@@ -378,6 +386,65 @@ export const SettingsPage: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* Subscription Section */}
|
||||||
|
<Card>
|
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
|
<CreditCardIcon color="primary" />
|
||||||
|
<Typography variant="h6" sx={{ fontWeight: 600 }}>
|
||||||
|
Subscription
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<MuiButton
|
||||||
|
variant="contained"
|
||||||
|
size="small"
|
||||||
|
onClick={() => navigate('/garage/settings/subscription')}
|
||||||
|
sx={{
|
||||||
|
backgroundColor: 'primary.main',
|
||||||
|
color: 'primary.contrastText',
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'primary.dark'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Manage
|
||||||
|
</MuiButton>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{subscriptionLoading ? (
|
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'center', py: 3 }}>
|
||||||
|
<CircularProgress size={24} />
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||||
|
<Typography variant="body1" sx={{ fontWeight: 500 }}>
|
||||||
|
Current Plan:
|
||||||
|
</Typography>
|
||||||
|
<Chip
|
||||||
|
label={(subscription?.tier || 'free').toUpperCase()}
|
||||||
|
color="primary"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
{subscription?.status && subscription.status !== 'active' && (
|
||||||
|
<Chip
|
||||||
|
label={subscription.status.replace('_', ' ')}
|
||||||
|
color={subscription.status === 'past_due' ? 'warning' : 'error'}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{subscription?.tier === 'free'
|
||||||
|
? 'Upgrade to Pro or Enterprise for more features and vehicle slots.'
|
||||||
|
: subscription?.tier === 'pro'
|
||||||
|
? 'Pro plan with up to 5 vehicles and full features.'
|
||||||
|
: 'Enterprise plan with unlimited vehicles and all features.'}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
|
||||||
{/* Notifications Section */}
|
{/* Notifications Section */}
|
||||||
<Card>
|
<Card>
|
||||||
<Typography variant="h6" sx={{ fontWeight: 600, mb: 3 }}>
|
<Typography variant="h6" sx={{ fontWeight: 600, mb: 3 }}>
|
||||||
|
|||||||
Reference in New Issue
Block a user