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>
208 lines
4.2 KiB
TypeScript
208 lines
4.2 KiB
TypeScript
import { CollectionConfig } from 'payload';
|
|
|
|
export const Users: CollectionConfig = {
|
|
slug: 'users',
|
|
auth: {
|
|
tokenExpiration: 604800, // 7 days
|
|
cookies: {
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'Lax',
|
|
},
|
|
},
|
|
admin: {
|
|
useAsTitle: 'email',
|
|
defaultColumns: ['email', 'name', 'role', 'createdAt'],
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'name',
|
|
type: 'text',
|
|
required: true,
|
|
localized: false,
|
|
},
|
|
{
|
|
name: 'email',
|
|
type: 'email',
|
|
required: true,
|
|
unique: true,
|
|
index: true,
|
|
},
|
|
{
|
|
name: 'role',
|
|
type: 'select',
|
|
options: [
|
|
{
|
|
label: 'User',
|
|
value: 'user',
|
|
},
|
|
{
|
|
label: 'Admin',
|
|
value: 'admin',
|
|
},
|
|
{
|
|
label: 'Super Admin',
|
|
value: 'super-admin',
|
|
},
|
|
],
|
|
defaultValue: 'user',
|
|
required: true,
|
|
admin: {
|
|
position: 'sidebar',
|
|
},
|
|
},
|
|
{
|
|
name: 'favoriteVersion',
|
|
type: 'select',
|
|
options: [
|
|
{ label: 'Cornilescu', value: 'VDC' },
|
|
{ label: 'NASB', value: 'NASB' },
|
|
{ label: 'RVR', value: 'RVR' },
|
|
{ label: 'NR', value: 'NR' },
|
|
],
|
|
defaultValue: 'VDC',
|
|
admin: {
|
|
position: 'sidebar',
|
|
},
|
|
},
|
|
{
|
|
name: 'stripeCustomerId',
|
|
type: 'text',
|
|
unique: true,
|
|
admin: {
|
|
position: 'sidebar',
|
|
readOnly: true,
|
|
description: 'Automatically set by Stripe integration',
|
|
},
|
|
},
|
|
{
|
|
name: 'subscription',
|
|
type: 'relationship',
|
|
relationTo: 'subscriptions',
|
|
hasMany: false,
|
|
admin: {
|
|
position: 'sidebar',
|
|
},
|
|
},
|
|
{
|
|
name: 'profileSettings',
|
|
type: 'group',
|
|
fields: [
|
|
{
|
|
name: 'fontSize',
|
|
type: 'number',
|
|
defaultValue: 16,
|
|
min: 12,
|
|
max: 24,
|
|
},
|
|
{
|
|
name: 'theme',
|
|
type: 'select',
|
|
options: [
|
|
{ label: 'Light', value: 'light' },
|
|
{ label: 'Dark', value: 'dark' },
|
|
],
|
|
defaultValue: 'light',
|
|
},
|
|
{
|
|
name: 'showVerseNumbers',
|
|
type: 'checkbox',
|
|
defaultValue: true,
|
|
},
|
|
{
|
|
name: 'enableNotifications',
|
|
type: 'checkbox',
|
|
defaultValue: true,
|
|
},
|
|
],
|
|
label: 'Profile Settings',
|
|
},
|
|
{
|
|
name: 'activityLog',
|
|
type: 'array',
|
|
fields: [
|
|
{
|
|
name: 'action',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'timestamp',
|
|
type: 'date',
|
|
required: true,
|
|
admin: {
|
|
readOnly: true,
|
|
},
|
|
},
|
|
],
|
|
admin: {
|
|
readOnly: true,
|
|
description: 'Automatically tracked user activities',
|
|
},
|
|
},
|
|
],
|
|
hooks: {
|
|
beforeChange: [
|
|
async ({ data, operation }) => {
|
|
if (operation === 'create' && !data.email) {
|
|
throw new Error('Email is required');
|
|
}
|
|
return data;
|
|
},
|
|
],
|
|
afterChange: [
|
|
async ({ doc, operation }) => {
|
|
if (operation === 'create') {
|
|
console.log(`New user created: ${doc.email}`);
|
|
}
|
|
return doc;
|
|
},
|
|
],
|
|
},
|
|
access: {
|
|
read: ({ req }) => {
|
|
// Users can read their own data, admins can read all
|
|
if (!req.user) {
|
|
return false;
|
|
}
|
|
|
|
if (req.user.role === 'admin' || req.user.role === 'super-admin') {
|
|
return true;
|
|
}
|
|
|
|
return {
|
|
id: {
|
|
equals: req.user.id,
|
|
},
|
|
};
|
|
},
|
|
create: () => {
|
|
// Public can create accounts (registration)
|
|
return true;
|
|
},
|
|
update: ({ req }) => {
|
|
// Users can update their own data, admins can update all
|
|
if (!req.user) {
|
|
return false;
|
|
}
|
|
|
|
if (req.user.role === 'admin' || req.user.role === 'super-admin') {
|
|
return true;
|
|
}
|
|
|
|
return {
|
|
id: {
|
|
equals: req.user.id,
|
|
},
|
|
};
|
|
},
|
|
delete: ({ req }) => {
|
|
// Only super admins can delete users
|
|
if (!req.user) {
|
|
return false;
|
|
}
|
|
|
|
return req.user.role === 'super-admin';
|
|
},
|
|
},
|
|
};
|