feat(contracts): Add contracts permission to subscription tiers

- Add contracts_enabled field to SubscriptionPlan model
- Add contracts toggle to plan create/edit modal in platform settings
- Hide contracts menu item for tenants without contracts permission
- Protect /contracts routes with canUse('contracts') check
- Add HasContractsPermission to contracts API ViewSets
- Add contracts to PlanPermissions interface and feature definitions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-05 23:28:51 -05:00
parent 35f4301fe1
commit 023ea7f020
12 changed files with 105 additions and 13 deletions

View File

@@ -9,6 +9,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useCurrentUser, useMasquerade, useLogout } from './hooks/useAuth';
import { useCurrentBusiness } from './hooks/useBusiness';
import { useUpdateBusiness } from './hooks/useBusiness';
import { usePlanFeatures } from './hooks/usePlanFeatures';
import { setCookie } from './utils/cookies';
// Import Login Page
@@ -192,6 +193,7 @@ const AppContent: React.FC = () => {
const updateBusinessMutation = useUpdateBusiness();
const masqueradeMutation = useMasquerade();
const logoutMutation = useLogout();
const { canUse } = usePlanFeatures();
// Apply dark mode class and persist to localStorage
React.useEffect(() => {
@@ -810,7 +812,7 @@ const AppContent: React.FC = () => {
<Route
path="/contracts"
element={
hasAccess(['owner', 'manager']) ? (
hasAccess(['owner', 'manager']) && canUse('contracts') ? (
<Contracts />
) : (
<Navigate to="/" />
@@ -820,7 +822,7 @@ const AppContent: React.FC = () => {
<Route
path="/contracts/templates"
element={
hasAccess(['owner', 'manager']) ? (
hasAccess(['owner', 'manager']) && canUse('contracts') ? (
<ContractTemplates />
) : (
<Navigate to="/" />