Files
biblical-guide.com/payload/collections/Subscriptions.ts
Andrei 9b5c0ed8bb build: production build with Phase 1 2025 Bible Reader implementation complete
Includes all Phase 1 features:
- Search-first navigation with auto-complete
- Responsive reading interface (desktop/tablet/mobile)
- 4 customization presets + full fine-tuning controls
- Layered details panel with notes, bookmarks, highlights
- Smart offline caching with IndexedDB and auto-sync
- Full accessibility (WCAG 2.1 AA)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 20:38:01 +00:00

156 lines
3.4 KiB
TypeScript

import { CollectionConfig } from 'payload';
export const Subscriptions: CollectionConfig = {
slug: 'subscriptions',
admin: {
useAsTitle: 'id',
defaultColumns: ['customer', 'status', 'currentPeriodEnd', 'active'],
group: 'E-Commerce',
},
fields: [
{
name: 'stripeSubscriptionId',
type: 'text',
unique: true,
required: true,
index: true,
admin: {
readOnly: true,
},
},
{
name: 'customer',
type: 'relationship',
relationTo: 'customers',
required: true,
index: true,
},
{
name: 'user',
type: 'relationship',
relationTo: 'users',
required: true,
unique: true,
index: true,
},
{
name: 'prices',
type: 'relationship',
relationTo: 'prices',
hasMany: true,
required: true,
},
{
name: 'status',
type: 'select',
options: [
{ label: 'Active', value: 'active' },
{ label: 'Past Due', value: 'past_due' },
{ label: 'Canceled', value: 'canceled' },
{ label: 'Incomplete', value: 'incomplete' },
{ label: 'Incomplete Expired', value: 'incomplete_expired' },
{ label: 'Trialing', value: 'trialing' },
{ label: 'Unpaid', value: 'unpaid' },
{ label: 'Paused', value: 'paused' },
],
required: true,
admin: {
readOnly: true,
},
},
{
name: 'currentPeriodStart',
type: 'date',
required: true,
admin: {
readOnly: true,
},
},
{
name: 'currentPeriodEnd',
type: 'date',
required: true,
index: true,
admin: {
readOnly: true,
},
},
{
name: 'canceledAt',
type: 'date',
admin: {
readOnly: true,
},
},
{
name: 'cancelAtPeriodEnd',
type: 'checkbox',
defaultValue: false,
admin: {
readOnly: true,
},
},
{
name: 'metadata',
type: 'group',
fields: [
{
name: 'planName',
type: 'text',
required: true,
},
{
name: 'conversationCount',
type: 'number',
defaultValue: 0,
admin: {
description: 'Monthly conversation count for free tier',
},
},
{
name: 'lastResetDate',
type: 'date',
},
],
},
],
hooks: {
afterChange: [
async ({ doc, operation, req }) => {
if (operation === 'create' || operation === 'update') {
// Update user's subscription reference
if (doc.user) {
await req.payload.update({
collection: 'users',
id: doc.user,
data: {
subscription: doc.id,
},
});
}
}
},
],
},
access: {
read: ({ req }) => {
if (!req.user) {
return false;
}
if (req.user.role === 'admin' || req.user.role === 'super-admin') {
return true;
}
return {
user: {
equals: req.user.id,
},
};
},
create: ({ req }) => req.user?.role === 'admin' || req.user?.role === 'super-admin',
update: ({ req }) => req.user?.role === 'admin' || req.user?.role === 'super-admin',
delete: () => false, // Never delete subscription records
},
};