mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 09:36:08 +00:00
feat(billing): integrate Stripe for subscription management and billing access
- Added billing-related fields to the User model in the database. - Implemented functions for managing billing access, including trial periods and subscription statuses. - Created new billing utility functions for Stripe integration. - Updated onboarding page to include billing overview and workspace creation eligibility. - Enhanced route access checks to require billing access for certain actions. - Implemented cleanup scripts for expired billing workspaces and associated media. - Updated header component to conditionally show app navigation based on billing access. - Added new migrations for billing-related database changes.
This commit is contained in:
+68
-59
@@ -30,7 +30,13 @@ interface WorkspaceData {
|
||||
ownerId: string;
|
||||
}
|
||||
|
||||
export default function WorkspaceSettingsPageClient({ workspaceId }: { workspaceId: string }) {
|
||||
export default function WorkspaceSettingsPageClient({
|
||||
workspaceId,
|
||||
canDelete,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
canDelete: boolean;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
|
||||
const [workspace, setWorkspace] = useState<WorkspaceData | null>(null);
|
||||
@@ -202,65 +208,68 @@ export default function WorkspaceSettingsPageClient({ workspaceId }: { workspace
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Separator className="my-8" />
|
||||
{canDelete ? (
|
||||
<>
|
||||
<Separator className="my-8" />
|
||||
|
||||
{/* Danger Zone */}
|
||||
<Card className="border-destructive/50">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-destructive">Danger Zone</CardTitle>
|
||||
<CardDescription>
|
||||
Irreversible actions. Proceed with caution.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive">
|
||||
<Trash2 className="h-4 w-4 mr-2" />
|
||||
Delete Workspace
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Delete "{workspace.name}"?</AlertDialogTitle>
|
||||
<AlertDialogDescription asChild>
|
||||
<div className="space-y-4">
|
||||
<p>
|
||||
This will permanently delete this workspace and everything inside it
|
||||
(projects, videos, comments, images, and voice notes). This action cannot be undone.
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="delete-workspace-confirm">
|
||||
Type <strong className="text-foreground">{workspace.name}</strong> to confirm
|
||||
</Label>
|
||||
<Input
|
||||
id="delete-workspace-confirm"
|
||||
value={deleteConfirmation}
|
||||
onChange={(e) => setDeleteConfirmation(e.target.value)}
|
||||
placeholder="Workspace name"
|
||||
className="h-11"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel onClick={() => setDeleteConfirmation('')}>
|
||||
Cancel
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={handleDelete}
|
||||
disabled={deleteConfirmation !== workspace.name || isDeleting}
|
||||
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
||||
>
|
||||
{isDeleting && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
|
||||
Delete Workspace
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="border-destructive/50">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-destructive">Danger Zone</CardTitle>
|
||||
<CardDescription>
|
||||
Irreversible actions. Proceed with caution.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button variant="destructive">
|
||||
<Trash2 className="h-4 w-4 mr-2" />
|
||||
Delete Workspace
|
||||
</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Delete "{workspace.name}"?</AlertDialogTitle>
|
||||
<AlertDialogDescription asChild>
|
||||
<div className="space-y-4">
|
||||
<p>
|
||||
This will permanently delete this workspace and everything inside it
|
||||
(projects, videos, comments, images, and voice notes). This action cannot be undone.
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="delete-workspace-confirm">
|
||||
Type <strong className="text-foreground">{workspace.name}</strong> to confirm
|
||||
</Label>
|
||||
<Input
|
||||
id="delete-workspace-confirm"
|
||||
value={deleteConfirmation}
|
||||
onChange={(e) => setDeleteConfirmation(e.target.value)}
|
||||
placeholder="Workspace name"
|
||||
className="h-11"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel onClick={() => setDeleteConfirmation('')}>
|
||||
Cancel
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={handleDelete}
|
||||
disabled={deleteConfirmation !== workspace.name || isDeleting}
|
||||
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
||||
>
|
||||
{isDeleting && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
|
||||
Delete Workspace
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user