admin: category drag-and-drop reorder + modal-based license key management

- Add sortOrder column to ProclamationCategory with migration
- Implement drag-and-drop reorder in AdminTable with persist-to-DB
- Refactor AdminTable to use $derived + dragOverride (no $effect sync)
- Replace window.location.reload with invalidateAll for reorder

- Convert license key create to modal with subscription level dropdown
- Add LicenseKeyForm.svelte following the CategoryForm pattern
- Add replace action (delete + generate new key with same level)
- Remove deactivateOld checkbox; each key has its own level
- Use use:enhance with update() to refresh list after create/replace
This commit is contained in:
NeilClack
2026-07-08 12:59:55 -05:00
parent 93d941569e
commit 6266be0edf
31 changed files with 21102 additions and 23217 deletions
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "ProclamationCategory" ADD COLUMN "sortOrder" INTEGER NOT NULL DEFAULT 0;
+1
View File
@@ -149,6 +149,7 @@ model SolfeggioFrequency {
model ProclamationCategory { model ProclamationCategory {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
name String name String
sortOrder Int @default(0)
parentId Int? parentId Int?
parent ProclamationCategory? @relation("CategoryHierarchy", fields: [parentId], references: [id]) parent ProclamationCategory? @relation("CategoryHierarchy", fields: [parentId], references: [id])
children ProclamationCategory[] @relation("CategoryHierarchy") children ProclamationCategory[] @relation("CategoryHierarchy")
+78 -4
View File
@@ -8,16 +8,20 @@
searchFields = [], searchFields = [],
fieldTypes = {} as Record<string, PrismaScalarType>, fieldTypes = {} as Record<string, PrismaScalarType>,
singular = 'record', singular = 'record',
draggable = false,
onRowClick, onRowClick,
onNew onNew,
onReorder
}: { }: {
records: Record<string, unknown>[]; records: Record<string, unknown>[];
listFields: string[]; listFields: string[];
searchFields?: string[]; searchFields?: string[];
fieldTypes?: Record<string, PrismaScalarType>; fieldTypes?: Record<string, PrismaScalarType>;
singular?: string; singular?: string;
draggable?: boolean;
onRowClick?: (record: Record<string, unknown>) => void; onRowClick?: (record: Record<string, unknown>) => void;
onNew?: () => void; onNew?: () => void;
onReorder?: (ids: (string | number)[]) => void;
} = $props(); } = $props();
let search = $state(''); let search = $state('');
@@ -48,6 +52,15 @@
: filtered : filtered
); );
let isDragging = $state(false);
let dragOverride = $state<Record<string, unknown>[] | null>(null);
let rows = $derived(dragOverride ?? sorted);
let dragIndex = $state<number | null>(null);
let hoverIndex = $state<number | null>(null);
function toggleSort(field: string) { function toggleSort(field: string) {
if (sortCol === field) { if (sortCol === field) {
sortAsc = !sortAsc; sortAsc = !sortAsc;
@@ -57,6 +70,45 @@
} }
} }
function handleDragStart(e: DragEvent, i: number) {
dragOverride = sorted;
isDragging = true;
dragIndex = i;
hoverIndex = i;
e.dataTransfer!.effectAllowed = 'move';
e.dataTransfer!.setData('text/plain', '');
}
function handleDragOver(e: DragEvent, i: number) {
if (dragIndex === null) return;
e.preventDefault();
if (i === hoverIndex) return;
e.dataTransfer!.dropEffect = 'move';
const reordered = rows.slice();
const [moved] = reordered.splice(dragIndex, 1);
reordered.splice(i, 0, moved);
dragOverride = reordered;
dragIndex = i;
hoverIndex = i;
}
async function handleDrop() {
if (dragIndex === null) return;
const ids = rows.map((r) => r.id as string | number);
await onReorder?.(ids);
isDragging = false;
dragIndex = null;
hoverIndex = null;
}
function handleDragEnd() {
dragOverride = null;
isDragging = false;
dragIndex = null;
hoverIndex = null;
}
function formatCellValue(v: unknown, field: string): string { function formatCellValue(v: unknown, field: string): string {
if (v == null) return ''; if (v == null) return '';
const ft = fieldTypes[field]; const ft = fieldTypes[field];
@@ -100,6 +152,9 @@
<table class="w-full"> <table class="w-full">
<thead> <thead>
<tr class="border-b border-gray-200 bg-gray-50 dark:border-gray-700 dark:bg-gray-800"> <tr class="border-b border-gray-200 bg-gray-50 dark:border-gray-700 dark:bg-gray-800">
{#if draggable}
<th scope="col" class="w-10 px-2 py-2"></th>
{/if}
{#each listFields as field (field)} {#each listFields as field (field)}
<th <th
scope="col" scope="col"
@@ -115,11 +170,30 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each sorted as record, i ((record['id'] as string) ?? (record['key'] as string) ?? i)} {#each rows as record, i ((record['id'] as string) ?? (record['key'] as string) ?? i)}
<tr <tr
{draggable}
ondragstart={(e) => handleDragStart(e, i)}
ondragover={(e) => handleDragOver(e, i)}
ondrop={handleDrop}
ondragend={handleDragEnd}
onclick={() => onRowClick?.(record)} onclick={() => onRowClick?.(record)}
class="cursor-pointer border-b border-gray-200 hover:bg-gray-100 dark:border-gray-700 dark:text-gray-100 dark:hover:bg-gray-800" class="border-b border-gray-200 hover:bg-gray-100 dark:border-gray-700 dark:text-gray-100 dark:hover:bg-gray-800 {draggable &&
isDragging &&
dragIndex === i
? 'opacity-40'
: ''} {draggable && isDragging && hoverIndex === i
? 'border-t-2 border-t-blue-500'
: ''}"
> >
{#if draggable}
<td
class="w-10 cursor-grab px-2 py-2 text-center"
onclick={(e) => e.stopPropagation()}
>
<span class="text-gray-400 select-none">⠿</span>
</td>
{/if}
{#each listFields as field (field)} {#each listFields as field (field)}
<td class="px-4 py-2 text-sm"> <td class="px-4 py-2 text-sm">
{formatCellValue(resolveFieldValue(record, field), field)} {formatCellValue(resolveFieldValue(record, field), field)}
@@ -129,7 +203,7 @@
{:else} {:else}
<tr> <tr>
<td <td
colspan={listFields.length} colspan={listFields.length + (draggable ? 1 : 0)}
class="px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400" class="px-4 py-8 text-center text-sm text-gray-500 dark:text-gray-400"
> >
No {singular}s found. No {singular}s found.
+38 -32
View File
@@ -1,83 +1,89 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This file should be your main import to use Prisma-related types and utilities in a browser. * This file should be your main import to use Prisma-related types and utilities in a browser.
* Use it to get access to models, enums, and input types. * Use it to get access to models, enums, and input types.
* *
* This file does not contain a `PrismaClient` class, nor several other helpers that are intended as server-side only. * This file does not contain a `PrismaClient` class, nor several other helpers that are intended as server-side only.
* See `client.ts` for the standard, server-side entry point. * See `client.ts` for the standard, server-side entry point.
* *
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
import * as Prisma from './internal/prismaNamespaceBrowser.ts'; import * as Prisma from './internal/prismaNamespaceBrowser.ts'
export { Prisma }; export { Prisma }
export * as $Enums from './enums.ts'; export * as $Enums from './enums.ts'
export * from './enums.ts'; export * from './enums.ts';
/** /**
* Model User * Model User
* *
*/ */
export type User = Prisma.UserModel; export type User = Prisma.UserModel
/** /**
* Model Profile * Model Profile
* *
*/ */
export type Profile = Prisma.ProfileModel; export type Profile = Prisma.ProfileModel
/** /**
* Model Address * Model Address
* *
*/ */
export type Address = Prisma.AddressModel; export type Address = Prisma.AddressModel
/** /**
* Model Session * Model Session
* *
*/ */
export type Session = Prisma.SessionModel; export type Session = Prisma.SessionModel
/** /**
* Model Account * Model Account
* *
*/ */
export type Account = Prisma.AccountModel; export type Account = Prisma.AccountModel
/** /**
* Model UserRole * Model UserRole
* *
*/ */
export type UserRole = Prisma.UserRoleModel; export type UserRole = Prisma.UserRoleModel
/** /**
* Model Verification * Model Verification
* *
*/ */
export type Verification = Prisma.VerificationModel; export type Verification = Prisma.VerificationModel
/** /**
* Model Proclamation * Model Proclamation
* *
*/ */
export type Proclamation = Prisma.ProclamationModel; export type Proclamation = Prisma.ProclamationModel
/** /**
* Model UserProclamations * Model UserProclamations
* *
*/ */
export type UserProclamations = Prisma.UserProclamationsModel; export type UserProclamations = Prisma.UserProclamationsModel
/** /**
* Model SolfeggioFrequency * Model SolfeggioFrequency
* *
*/ */
export type SolfeggioFrequency = Prisma.SolfeggioFrequencyModel; export type SolfeggioFrequency = Prisma.SolfeggioFrequencyModel
/** /**
* Model ProclamationCategory * Model ProclamationCategory
* *
*/ */
export type ProclamationCategory = Prisma.ProclamationCategoryModel; export type ProclamationCategory = Prisma.ProclamationCategoryModel
/**
* Model ProclamationCategorySubscriptionLevel
*
*/
export type ProclamationCategorySubscriptionLevel = Prisma.ProclamationCategorySubscriptionLevelModel
/** /**
* Model LicenseKey * Model LicenseKey
* *
*/ */
export type LicenseKey = Prisma.LicenseKeyModel; export type LicenseKey = Prisma.LicenseKeyModel
/** /**
* Model SubscriptionLevel * Model SubscriptionLevel
* *
*/ */
export type SubscriptionLevel = Prisma.SubscriptionLevelModel; export type SubscriptionLevel = Prisma.SubscriptionLevelModel
+48 -46
View File
@@ -1,7 +1,8 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types. * This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types.
* If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead. * If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead.
@@ -9,21 +10,21 @@
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
import * as process from 'node:process'; import * as process from 'node:process'
import * as path from 'node:path'; import * as path from 'node:path'
import { fileURLToPath } from 'node:url'; import { fileURLToPath } from 'node:url'
globalThis['__dirname'] = path.dirname(fileURLToPath(import.meta.url)); globalThis['__dirname'] = path.dirname(fileURLToPath(import.meta.url))
import * as runtime from '@prisma/client/runtime/client'; import * as runtime from "@prisma/client/runtime/client"
import * as $Enums from './enums.ts'; import * as $Enums from "./enums.ts"
import * as $Class from './internal/class.ts'; import * as $Class from "./internal/class.ts"
import * as Prisma from './internal/prismaNamespace.ts'; import * as Prisma from "./internal/prismaNamespace.ts"
export * as $Enums from './enums.ts'; export * as $Enums from './enums.ts'
export * from './enums.ts'; export * from "./enums.ts"
/** /**
* ## Prisma Client * ## Prisma Client
* *
* Type-safe database client for TypeScript * Type-safe database client for TypeScript
* @example * @example
* ``` * ```
@@ -33,79 +34,80 @@ export * from './enums.ts';
* // Fetch zero or more Users * // Fetch zero or more Users
* const users = await prisma.user.findMany() * const users = await prisma.user.findMany()
* ``` * ```
* *
* Read more in our [docs](https://pris.ly/d/client). * Read more in our [docs](https://pris.ly/d/client).
*/ */
export const PrismaClient = $Class.getPrismaClientClass(); export const PrismaClient = $Class.getPrismaClientClass()
export type PrismaClient< export type PrismaClient<LogOpts extends Prisma.LogLevel = never, OmitOpts extends Prisma.PrismaClientOptions["omit"] = Prisma.PrismaClientOptions["omit"], ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = $Class.PrismaClient<LogOpts, OmitOpts, ExtArgs>
LogOpts extends Prisma.LogLevel = never, export { Prisma }
OmitOpts extends Prisma.PrismaClientOptions['omit'] = Prisma.PrismaClientOptions['omit'],
ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs
> = $Class.PrismaClient<LogOpts, OmitOpts, ExtArgs>;
export { Prisma };
/** /**
* Model User * Model User
* *
*/ */
export type User = Prisma.UserModel; export type User = Prisma.UserModel
/** /**
* Model Profile * Model Profile
* *
*/ */
export type Profile = Prisma.ProfileModel; export type Profile = Prisma.ProfileModel
/** /**
* Model Address * Model Address
* *
*/ */
export type Address = Prisma.AddressModel; export type Address = Prisma.AddressModel
/** /**
* Model Session * Model Session
* *
*/ */
export type Session = Prisma.SessionModel; export type Session = Prisma.SessionModel
/** /**
* Model Account * Model Account
* *
*/ */
export type Account = Prisma.AccountModel; export type Account = Prisma.AccountModel
/** /**
* Model UserRole * Model UserRole
* *
*/ */
export type UserRole = Prisma.UserRoleModel; export type UserRole = Prisma.UserRoleModel
/** /**
* Model Verification * Model Verification
* *
*/ */
export type Verification = Prisma.VerificationModel; export type Verification = Prisma.VerificationModel
/** /**
* Model Proclamation * Model Proclamation
* *
*/ */
export type Proclamation = Prisma.ProclamationModel; export type Proclamation = Prisma.ProclamationModel
/** /**
* Model UserProclamations * Model UserProclamations
* *
*/ */
export type UserProclamations = Prisma.UserProclamationsModel; export type UserProclamations = Prisma.UserProclamationsModel
/** /**
* Model SolfeggioFrequency * Model SolfeggioFrequency
* *
*/ */
export type SolfeggioFrequency = Prisma.SolfeggioFrequencyModel; export type SolfeggioFrequency = Prisma.SolfeggioFrequencyModel
/** /**
* Model ProclamationCategory * Model ProclamationCategory
* *
*/ */
export type ProclamationCategory = Prisma.ProclamationCategoryModel; export type ProclamationCategory = Prisma.ProclamationCategoryModel
/**
* Model ProclamationCategorySubscriptionLevel
*
*/
export type ProclamationCategorySubscriptionLevel = Prisma.ProclamationCategorySubscriptionLevelModel
/** /**
* Model LicenseKey * Model LicenseKey
* *
*/ */
export type LicenseKey = Prisma.LicenseKeyModel; export type LicenseKey = Prisma.LicenseKeyModel
/** /**
* Model SubscriptionLevel * Model SubscriptionLevel
* *
*/ */
export type SubscriptionLevel = Prisma.SubscriptionLevelModel; export type SubscriptionLevel = Prisma.SubscriptionLevelModel
+335 -331
View File
@@ -1,402 +1,406 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This file exports various common sort, input & filter types that are not directly linked to a particular model. * This file exports various common sort, input & filter types that are not directly linked to a particular model.
* *
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
import type * as runtime from '@prisma/client/runtime/client'; import type * as runtime from "@prisma/client/runtime/client"
import * as $Enums from './enums.ts'; import * as $Enums from "./enums.ts"
import type * as Prisma from './internal/prismaNamespace.ts'; import type * as Prisma from "./internal/prismaNamespace.ts"
export type StringFilter<$PrismaModel = never> = { export type StringFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>; equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>; in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>; notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>; lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>; lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>; gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>; gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>; contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
mode?: Prisma.QueryMode; mode?: Prisma.QueryMode
not?: Prisma.NestedStringFilter<$PrismaModel> | string; not?: Prisma.NestedStringFilter<$PrismaModel> | string
}; }
export type BoolFilter<$PrismaModel = never> = { export type BoolFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>; equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>
not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean; not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean
}; }
export type StringNullableFilter<$PrismaModel = never> = { export type StringNullableFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null; equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null; in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null; notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>; lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>; lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>; gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>; gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>; contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
mode?: Prisma.QueryMode; mode?: Prisma.QueryMode
not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null; not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null
}; }
export type DateTimeFilter<$PrismaModel = never> = { export type DateTimeFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>; in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>; notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string; not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string
}; }
export type IntNullableFilter<$PrismaModel = never> = { export type IntNullableFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null; equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null; in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null; notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>; lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>; lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>; gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>; gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null; not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null
}; }
export type SortOrderInput = { export type SortOrderInput = {
sort: Prisma.SortOrder; sort: Prisma.SortOrder
nulls?: Prisma.NullsOrder; nulls?: Prisma.NullsOrder
}; }
export type StringWithAggregatesFilter<$PrismaModel = never> = { export type StringWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>; equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>; in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>; notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>; lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>; lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>; gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>; gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>; contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
mode?: Prisma.QueryMode; mode?: Prisma.QueryMode
not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string; not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string
_count?: Prisma.NestedIntFilter<$PrismaModel>; _count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedStringFilter<$PrismaModel>; _min?: Prisma.NestedStringFilter<$PrismaModel>
_max?: Prisma.NestedStringFilter<$PrismaModel>; _max?: Prisma.NestedStringFilter<$PrismaModel>
}; }
export type BoolWithAggregatesFilter<$PrismaModel = never> = { export type BoolWithAggregatesFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>; equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>
not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean; not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean
_count?: Prisma.NestedIntFilter<$PrismaModel>; _count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedBoolFilter<$PrismaModel>; _min?: Prisma.NestedBoolFilter<$PrismaModel>
_max?: Prisma.NestedBoolFilter<$PrismaModel>; _max?: Prisma.NestedBoolFilter<$PrismaModel>
}; }
export type StringNullableWithAggregatesFilter<$PrismaModel = never> = { export type StringNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null; equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null; in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null; notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>; lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>; lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>; gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>; gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>; contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
mode?: Prisma.QueryMode; mode?: Prisma.QueryMode
not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null; not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>; _count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedStringNullableFilter<$PrismaModel>; _min?: Prisma.NestedStringNullableFilter<$PrismaModel>
_max?: Prisma.NestedStringNullableFilter<$PrismaModel>; _max?: Prisma.NestedStringNullableFilter<$PrismaModel>
}; }
export type DateTimeWithAggregatesFilter<$PrismaModel = never> = { export type DateTimeWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>; in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>; notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string; not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string
_count?: Prisma.NestedIntFilter<$PrismaModel>; _count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedDateTimeFilter<$PrismaModel>; _min?: Prisma.NestedDateTimeFilter<$PrismaModel>
_max?: Prisma.NestedDateTimeFilter<$PrismaModel>; _max?: Prisma.NestedDateTimeFilter<$PrismaModel>
}; }
export type IntNullableWithAggregatesFilter<$PrismaModel = never> = { export type IntNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null; equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null; in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null; notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>; lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>; lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>; gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>; gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null; not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>; _count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_avg?: Prisma.NestedFloatNullableFilter<$PrismaModel>; _avg?: Prisma.NestedFloatNullableFilter<$PrismaModel>
_sum?: Prisma.NestedIntNullableFilter<$PrismaModel>; _sum?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedIntNullableFilter<$PrismaModel>; _min?: Prisma.NestedIntNullableFilter<$PrismaModel>
_max?: Prisma.NestedIntNullableFilter<$PrismaModel>; _max?: Prisma.NestedIntNullableFilter<$PrismaModel>
}; }
export type DateTimeNullableFilter<$PrismaModel = never> = { export type DateTimeNullableFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null; equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null; in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null; notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null; not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null
}; }
export type DateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { export type DateTimeNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null; equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null; in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null; notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
not?: Prisma.NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null; not?: Prisma.NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>; _count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>; _min?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>
_max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>; _max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>
}; }
export type IntFilter<$PrismaModel = never> = { export type IntFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>; equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>; in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>; notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>; lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>; lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>; gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>; gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntFilter<$PrismaModel> | number; not?: Prisma.NestedIntFilter<$PrismaModel> | number
}; }
export type IntWithAggregatesFilter<$PrismaModel = never> = { export type IntWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>; equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>; in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>; notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>; lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>; lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>; gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>; gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number; not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number
_count?: Prisma.NestedIntFilter<$PrismaModel>; _count?: Prisma.NestedIntFilter<$PrismaModel>
_avg?: Prisma.NestedFloatFilter<$PrismaModel>; _avg?: Prisma.NestedFloatFilter<$PrismaModel>
_sum?: Prisma.NestedIntFilter<$PrismaModel>; _sum?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedIntFilter<$PrismaModel>; _min?: Prisma.NestedIntFilter<$PrismaModel>
_max?: Prisma.NestedIntFilter<$PrismaModel>; _max?: Prisma.NestedIntFilter<$PrismaModel>
}; }
export type NestedStringFilter<$PrismaModel = never> = { export type NestedStringFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>; equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>; in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>; notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>; lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>; lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>; gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>; gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>; contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
not?: Prisma.NestedStringFilter<$PrismaModel> | string; not?: Prisma.NestedStringFilter<$PrismaModel> | string
}; }
export type NestedBoolFilter<$PrismaModel = never> = { export type NestedBoolFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>; equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>
not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean; not?: Prisma.NestedBoolFilter<$PrismaModel> | boolean
}; }
export type NestedStringNullableFilter<$PrismaModel = never> = { export type NestedStringNullableFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null; equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null; in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null; notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>; lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>; lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>; gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>; gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>; contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null; not?: Prisma.NestedStringNullableFilter<$PrismaModel> | string | null
}; }
export type NestedDateTimeFilter<$PrismaModel = never> = { export type NestedDateTimeFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>; in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>; notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string; not?: Prisma.NestedDateTimeFilter<$PrismaModel> | Date | string
}; }
export type NestedIntNullableFilter<$PrismaModel = never> = { export type NestedIntNullableFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null; equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null; in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null; notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>; lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>; lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>; gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>; gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null; not?: Prisma.NestedIntNullableFilter<$PrismaModel> | number | null
}; }
export type NestedStringWithAggregatesFilter<$PrismaModel = never> = { export type NestedStringWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel>; equals?: string | Prisma.StringFieldRefInput<$PrismaModel>
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>; in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>; notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel>
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>; lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>; lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>; gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>; gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>; contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string; not?: Prisma.NestedStringWithAggregatesFilter<$PrismaModel> | string
_count?: Prisma.NestedIntFilter<$PrismaModel>; _count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedStringFilter<$PrismaModel>; _min?: Prisma.NestedStringFilter<$PrismaModel>
_max?: Prisma.NestedStringFilter<$PrismaModel>; _max?: Prisma.NestedStringFilter<$PrismaModel>
}; }
export type NestedIntFilter<$PrismaModel = never> = { export type NestedIntFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>; equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>; in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>; notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>; lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>; lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>; gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>; gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntFilter<$PrismaModel> | number; not?: Prisma.NestedIntFilter<$PrismaModel> | number
}; }
export type NestedBoolWithAggregatesFilter<$PrismaModel = never> = { export type NestedBoolWithAggregatesFilter<$PrismaModel = never> = {
equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>; equals?: boolean | Prisma.BooleanFieldRefInput<$PrismaModel>
not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean; not?: Prisma.NestedBoolWithAggregatesFilter<$PrismaModel> | boolean
_count?: Prisma.NestedIntFilter<$PrismaModel>; _count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedBoolFilter<$PrismaModel>; _min?: Prisma.NestedBoolFilter<$PrismaModel>
_max?: Prisma.NestedBoolFilter<$PrismaModel>; _max?: Prisma.NestedBoolFilter<$PrismaModel>
}; }
export type NestedStringNullableWithAggregatesFilter<$PrismaModel = never> = { export type NestedStringNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null; equals?: string | Prisma.StringFieldRefInput<$PrismaModel> | null
in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null; in?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null; notIn?: string[] | Prisma.ListStringFieldRefInput<$PrismaModel> | null
lt?: string | Prisma.StringFieldRefInput<$PrismaModel>; lt?: string | Prisma.StringFieldRefInput<$PrismaModel>
lte?: string | Prisma.StringFieldRefInput<$PrismaModel>; lte?: string | Prisma.StringFieldRefInput<$PrismaModel>
gt?: string | Prisma.StringFieldRefInput<$PrismaModel>; gt?: string | Prisma.StringFieldRefInput<$PrismaModel>
gte?: string | Prisma.StringFieldRefInput<$PrismaModel>; gte?: string | Prisma.StringFieldRefInput<$PrismaModel>
contains?: string | Prisma.StringFieldRefInput<$PrismaModel>; contains?: string | Prisma.StringFieldRefInput<$PrismaModel>
startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; startsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>; endsWith?: string | Prisma.StringFieldRefInput<$PrismaModel>
not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null; not?: Prisma.NestedStringNullableWithAggregatesFilter<$PrismaModel> | string | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>; _count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedStringNullableFilter<$PrismaModel>; _min?: Prisma.NestedStringNullableFilter<$PrismaModel>
_max?: Prisma.NestedStringNullableFilter<$PrismaModel>; _max?: Prisma.NestedStringNullableFilter<$PrismaModel>
}; }
export type NestedDateTimeWithAggregatesFilter<$PrismaModel = never> = { export type NestedDateTimeWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>; in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>; notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel>
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string; not?: Prisma.NestedDateTimeWithAggregatesFilter<$PrismaModel> | Date | string
_count?: Prisma.NestedIntFilter<$PrismaModel>; _count?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedDateTimeFilter<$PrismaModel>; _min?: Prisma.NestedDateTimeFilter<$PrismaModel>
_max?: Prisma.NestedDateTimeFilter<$PrismaModel>; _max?: Prisma.NestedDateTimeFilter<$PrismaModel>
}; }
export type NestedIntNullableWithAggregatesFilter<$PrismaModel = never> = { export type NestedIntNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null; equals?: number | Prisma.IntFieldRefInput<$PrismaModel> | null
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null; in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null; notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel> | null
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>; lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>; lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>; gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>; gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null; not?: Prisma.NestedIntNullableWithAggregatesFilter<$PrismaModel> | number | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>; _count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_avg?: Prisma.NestedFloatNullableFilter<$PrismaModel>; _avg?: Prisma.NestedFloatNullableFilter<$PrismaModel>
_sum?: Prisma.NestedIntNullableFilter<$PrismaModel>; _sum?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedIntNullableFilter<$PrismaModel>; _min?: Prisma.NestedIntNullableFilter<$PrismaModel>
_max?: Prisma.NestedIntNullableFilter<$PrismaModel>; _max?: Prisma.NestedIntNullableFilter<$PrismaModel>
}; }
export type NestedFloatNullableFilter<$PrismaModel = never> = { export type NestedFloatNullableFilter<$PrismaModel = never> = {
equals?: number | Prisma.FloatFieldRefInput<$PrismaModel> | null; equals?: number | Prisma.FloatFieldRefInput<$PrismaModel> | null
in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> | null; in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> | null
notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> | null; notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel> | null
lt?: number | Prisma.FloatFieldRefInput<$PrismaModel>; lt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
lte?: number | Prisma.FloatFieldRefInput<$PrismaModel>; lte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
gt?: number | Prisma.FloatFieldRefInput<$PrismaModel>; gt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
gte?: number | Prisma.FloatFieldRefInput<$PrismaModel>; gte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
not?: Prisma.NestedFloatNullableFilter<$PrismaModel> | number | null; not?: Prisma.NestedFloatNullableFilter<$PrismaModel> | number | null
}; }
export type NestedDateTimeNullableFilter<$PrismaModel = never> = { export type NestedDateTimeNullableFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null; equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null; in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null; notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null; not?: Prisma.NestedDateTimeNullableFilter<$PrismaModel> | Date | string | null
}; }
export type NestedDateTimeNullableWithAggregatesFilter<$PrismaModel = never> = { export type NestedDateTimeNullableWithAggregatesFilter<$PrismaModel = never> = {
equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null; equals?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel> | null
in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null; in?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null
notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null; notIn?: Date[] | string[] | Prisma.ListDateTimeFieldRefInput<$PrismaModel> | null
lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; lte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gt?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>; gte?: Date | string | Prisma.DateTimeFieldRefInput<$PrismaModel>
not?: Prisma.NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null; not?: Prisma.NestedDateTimeNullableWithAggregatesFilter<$PrismaModel> | Date | string | null
_count?: Prisma.NestedIntNullableFilter<$PrismaModel>; _count?: Prisma.NestedIntNullableFilter<$PrismaModel>
_min?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>; _min?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>
_max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>; _max?: Prisma.NestedDateTimeNullableFilter<$PrismaModel>
}; }
export type NestedIntWithAggregatesFilter<$PrismaModel = never> = { export type NestedIntWithAggregatesFilter<$PrismaModel = never> = {
equals?: number | Prisma.IntFieldRefInput<$PrismaModel>; equals?: number | Prisma.IntFieldRefInput<$PrismaModel>
in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>; in?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>; notIn?: number[] | Prisma.ListIntFieldRefInput<$PrismaModel>
lt?: number | Prisma.IntFieldRefInput<$PrismaModel>; lt?: number | Prisma.IntFieldRefInput<$PrismaModel>
lte?: number | Prisma.IntFieldRefInput<$PrismaModel>; lte?: number | Prisma.IntFieldRefInput<$PrismaModel>
gt?: number | Prisma.IntFieldRefInput<$PrismaModel>; gt?: number | Prisma.IntFieldRefInput<$PrismaModel>
gte?: number | Prisma.IntFieldRefInput<$PrismaModel>; gte?: number | Prisma.IntFieldRefInput<$PrismaModel>
not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number; not?: Prisma.NestedIntWithAggregatesFilter<$PrismaModel> | number
_count?: Prisma.NestedIntFilter<$PrismaModel>; _count?: Prisma.NestedIntFilter<$PrismaModel>
_avg?: Prisma.NestedFloatFilter<$PrismaModel>; _avg?: Prisma.NestedFloatFilter<$PrismaModel>
_sum?: Prisma.NestedIntFilter<$PrismaModel>; _sum?: Prisma.NestedIntFilter<$PrismaModel>
_min?: Prisma.NestedIntFilter<$PrismaModel>; _min?: Prisma.NestedIntFilter<$PrismaModel>
_max?: Prisma.NestedIntFilter<$PrismaModel>; _max?: Prisma.NestedIntFilter<$PrismaModel>
}; }
export type NestedFloatFilter<$PrismaModel = never> = { export type NestedFloatFilter<$PrismaModel = never> = {
equals?: number | Prisma.FloatFieldRefInput<$PrismaModel>; equals?: number | Prisma.FloatFieldRefInput<$PrismaModel>
in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel>; in?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel>
notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel>; notIn?: number[] | Prisma.ListFloatFieldRefInput<$PrismaModel>
lt?: number | Prisma.FloatFieldRefInput<$PrismaModel>; lt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
lte?: number | Prisma.FloatFieldRefInput<$PrismaModel>; lte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
gt?: number | Prisma.FloatFieldRefInput<$PrismaModel>; gt?: number | Prisma.FloatFieldRefInput<$PrismaModel>
gte?: number | Prisma.FloatFieldRefInput<$PrismaModel>; gte?: number | Prisma.FloatFieldRefInput<$PrismaModel>
not?: Prisma.NestedFloatFilter<$PrismaModel> | number; not?: Prisma.NestedFloatFilter<$PrismaModel> | number
}; }
+9 -6
View File
@@ -1,12 +1,15 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This file exports all enum related types from the schema. * This file exports all enum related types from the schema.
* *
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
// This file is empty because there are no enums in the schema. // This file is empty because there are no enums in the schema.
export {}; export {}
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,8 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* WARNING: This is an internal file that is subject to change! * WARNING: This is an internal file that is subject to change!
* *
@@ -14,243 +15,259 @@
* model files in the `model` directory! * model files in the `model` directory!
*/ */
import * as runtime from '@prisma/client/runtime/index-browser'; import * as runtime from "@prisma/client/runtime/index-browser"
export type * from '../models.ts'; export type * from '../models.ts'
export type * from './prismaNamespace.ts'; export type * from './prismaNamespace.ts'
export const Decimal = runtime.Decimal
export const Decimal = runtime.Decimal;
export const NullTypes = { export const NullTypes = {
DbNull: runtime.NullTypes.DbNull as new (secret: never) => typeof runtime.DbNull, DbNull: runtime.NullTypes.DbNull as (new (secret: never) => typeof runtime.DbNull),
JsonNull: runtime.NullTypes.JsonNull as new (secret: never) => typeof runtime.JsonNull, JsonNull: runtime.NullTypes.JsonNull as (new (secret: never) => typeof runtime.JsonNull),
AnyNull: runtime.NullTypes.AnyNull as new (secret: never) => typeof runtime.AnyNull AnyNull: runtime.NullTypes.AnyNull as (new (secret: never) => typeof runtime.AnyNull),
}; }
/** /**
* Helper for filtering JSON entries that have `null` on the database (empty on the db) * Helper for filtering JSON entries that have `null` on the database (empty on the db)
* *
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/ */
export const DbNull = runtime.DbNull; export const DbNull = runtime.DbNull
/** /**
* Helper for filtering JSON entries that have JSON `null` values (not empty on the db) * Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
* *
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/ */
export const JsonNull = runtime.JsonNull; export const JsonNull = runtime.JsonNull
/** /**
* Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull` * Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
* *
* @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
*/ */
export const AnyNull = runtime.AnyNull; export const AnyNull = runtime.AnyNull
export const ModelName = { export const ModelName = {
User: 'User', User: 'User',
Profile: 'Profile', Profile: 'Profile',
Address: 'Address', Address: 'Address',
Session: 'Session', Session: 'Session',
Account: 'Account', Account: 'Account',
UserRole: 'UserRole', UserRole: 'UserRole',
Verification: 'Verification', Verification: 'Verification',
Proclamation: 'Proclamation', Proclamation: 'Proclamation',
UserProclamations: 'UserProclamations', UserProclamations: 'UserProclamations',
SolfeggioFrequency: 'SolfeggioFrequency', SolfeggioFrequency: 'SolfeggioFrequency',
ProclamationCategory: 'ProclamationCategory', ProclamationCategory: 'ProclamationCategory',
LicenseKey: 'LicenseKey', ProclamationCategorySubscriptionLevel: 'ProclamationCategorySubscriptionLevel',
SubscriptionLevel: 'SubscriptionLevel' LicenseKey: 'LicenseKey',
} as const; SubscriptionLevel: 'SubscriptionLevel'
} as const
export type ModelName = (typeof ModelName)[keyof typeof ModelName]; export type ModelName = (typeof ModelName)[keyof typeof ModelName]
/* /*
* Enums * Enums
*/ */
export const TransactionIsolationLevel = runtime.makeStrictEnum({ export const TransactionIsolationLevel = runtime.makeStrictEnum({
ReadUncommitted: 'ReadUncommitted', ReadUncommitted: 'ReadUncommitted',
ReadCommitted: 'ReadCommitted', ReadCommitted: 'ReadCommitted',
RepeatableRead: 'RepeatableRead', RepeatableRead: 'RepeatableRead',
Serializable: 'Serializable' Serializable: 'Serializable'
} as const); } as const)
export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof typeof TransactionIsolationLevel]
export type TransactionIsolationLevel =
(typeof TransactionIsolationLevel)[keyof typeof TransactionIsolationLevel];
export const UserScalarFieldEnum = { export const UserScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
email: 'email', email: 'email',
emailVerified: 'emailVerified', emailVerified: 'emailVerified',
image: 'image', image: 'image',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt', updatedAt: 'updatedAt',
roleId: 'roleId' roleId: 'roleId'
} as const; } as const
export type UserScalarFieldEnum = (typeof UserScalarFieldEnum)[keyof typeof UserScalarFieldEnum]
export type UserScalarFieldEnum = (typeof UserScalarFieldEnum)[keyof typeof UserScalarFieldEnum];
export const ProfileScalarFieldEnum = { export const ProfileScalarFieldEnum = {
id: 'id', id: 'id',
userId: 'userId', userId: 'userId',
firstName: 'firstName', firstName: 'firstName',
lastName: 'lastName', lastName: 'lastName',
phoneNumber: 'phoneNumber', phoneNumber: 'phoneNumber',
ghlContactId: 'ghlContactId' ghlContactId: 'ghlContactId'
} as const; } as const
export type ProfileScalarFieldEnum = (typeof ProfileScalarFieldEnum)[keyof typeof ProfileScalarFieldEnum]
export type ProfileScalarFieldEnum =
(typeof ProfileScalarFieldEnum)[keyof typeof ProfileScalarFieldEnum];
export const AddressScalarFieldEnum = { export const AddressScalarFieldEnum = {
id: 'id', id: 'id',
profileId: 'profileId', profileId: 'profileId',
street: 'street', street: 'street',
city: 'city', city: 'city',
state: 'state', state: 'state',
postalCode: 'postalCode', postalCode: 'postalCode',
country: 'country', country: 'country',
type: 'type', type: 'type',
isDefaultMailing: 'isDefaultMailing', isDefaultMailing: 'isDefaultMailing',
isDefaultBilling: 'isDefaultBilling', isDefaultBilling: 'isDefaultBilling',
isDefaultShipping: 'isDefaultShipping' isDefaultShipping: 'isDefaultShipping'
} as const; } as const
export type AddressScalarFieldEnum = (typeof AddressScalarFieldEnum)[keyof typeof AddressScalarFieldEnum]
export type AddressScalarFieldEnum =
(typeof AddressScalarFieldEnum)[keyof typeof AddressScalarFieldEnum];
export const SessionScalarFieldEnum = { export const SessionScalarFieldEnum = {
id: 'id', id: 'id',
expiresAt: 'expiresAt', expiresAt: 'expiresAt',
token: 'token', token: 'token',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt', updatedAt: 'updatedAt',
ipAddress: 'ipAddress', ipAddress: 'ipAddress',
userAgent: 'userAgent', userAgent: 'userAgent',
userId: 'userId' userId: 'userId'
} as const; } as const
export type SessionScalarFieldEnum = (typeof SessionScalarFieldEnum)[keyof typeof SessionScalarFieldEnum]
export type SessionScalarFieldEnum =
(typeof SessionScalarFieldEnum)[keyof typeof SessionScalarFieldEnum];
export const AccountScalarFieldEnum = { export const AccountScalarFieldEnum = {
id: 'id', id: 'id',
accountId: 'accountId', accountId: 'accountId',
providerId: 'providerId', providerId: 'providerId',
userId: 'userId', userId: 'userId',
accessToken: 'accessToken', accessToken: 'accessToken',
refreshToken: 'refreshToken', refreshToken: 'refreshToken',
idToken: 'idToken', idToken: 'idToken',
accessTokenExpiresAt: 'accessTokenExpiresAt', accessTokenExpiresAt: 'accessTokenExpiresAt',
refreshTokenExpiresAt: 'refreshTokenExpiresAt', refreshTokenExpiresAt: 'refreshTokenExpiresAt',
scope: 'scope', scope: 'scope',
password: 'password', password: 'password',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const; } as const
export type AccountScalarFieldEnum = (typeof AccountScalarFieldEnum)[keyof typeof AccountScalarFieldEnum]
export type AccountScalarFieldEnum =
(typeof AccountScalarFieldEnum)[keyof typeof AccountScalarFieldEnum];
export const UserRoleScalarFieldEnum = { export const UserRoleScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name' name: 'name'
} as const; } as const
export type UserRoleScalarFieldEnum = (typeof UserRoleScalarFieldEnum)[keyof typeof UserRoleScalarFieldEnum]
export type UserRoleScalarFieldEnum =
(typeof UserRoleScalarFieldEnum)[keyof typeof UserRoleScalarFieldEnum];
export const VerificationScalarFieldEnum = { export const VerificationScalarFieldEnum = {
id: 'id', id: 'id',
identifier: 'identifier', identifier: 'identifier',
value: 'value', value: 'value',
expiresAt: 'expiresAt', expiresAt: 'expiresAt',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const; } as const
export type VerificationScalarFieldEnum = (typeof VerificationScalarFieldEnum)[keyof typeof VerificationScalarFieldEnum]
export type VerificationScalarFieldEnum =
(typeof VerificationScalarFieldEnum)[keyof typeof VerificationScalarFieldEnum];
export const ProclamationScalarFieldEnum = { export const ProclamationScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
content: 'content', content: 'content',
solfeggioFrequencyId: 'solfeggioFrequencyId', solfeggioFrequencyId: 'solfeggioFrequencyId',
categoryId: 'categoryId', categoryId: 'categoryId',
subscriptionLevelId: 'subscriptionLevelId' subscriptionLevelId: 'subscriptionLevelId'
} as const; } as const
export type ProclamationScalarFieldEnum = (typeof ProclamationScalarFieldEnum)[keyof typeof ProclamationScalarFieldEnum]
export type ProclamationScalarFieldEnum =
(typeof ProclamationScalarFieldEnum)[keyof typeof ProclamationScalarFieldEnum];
export const UserProclamationsScalarFieldEnum = { export const UserProclamationsScalarFieldEnum = {
userId: 'userId', userId: 'userId',
proclamationId: 'proclamationId', proclamationId: 'proclamationId',
createdAt: 'createdAt', createdAt: 'createdAt',
updatedAt: 'updatedAt' updatedAt: 'updatedAt'
} as const; } as const
export type UserProclamationsScalarFieldEnum = (typeof UserProclamationsScalarFieldEnum)[keyof typeof UserProclamationsScalarFieldEnum]
export type UserProclamationsScalarFieldEnum =
(typeof UserProclamationsScalarFieldEnum)[keyof typeof UserProclamationsScalarFieldEnum];
export const SolfeggioFrequencyScalarFieldEnum = { export const SolfeggioFrequencyScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
value: 'value' value: 'value'
} as const; } as const
export type SolfeggioFrequencyScalarFieldEnum = (typeof SolfeggioFrequencyScalarFieldEnum)[keyof typeof SolfeggioFrequencyScalarFieldEnum]
export type SolfeggioFrequencyScalarFieldEnum =
(typeof SolfeggioFrequencyScalarFieldEnum)[keyof typeof SolfeggioFrequencyScalarFieldEnum];
export const ProclamationCategoryScalarFieldEnum = { export const ProclamationCategoryScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
parentId: 'parentId' sortOrder: 'sortOrder',
} as const; parentId: 'parentId'
} as const
export type ProclamationCategoryScalarFieldEnum = (typeof ProclamationCategoryScalarFieldEnum)[keyof typeof ProclamationCategoryScalarFieldEnum]
export const ProclamationCategorySubscriptionLevelScalarFieldEnum = {
categoryId: 'categoryId',
subscriptionLevelId: 'subscriptionLevelId'
} as const
export type ProclamationCategorySubscriptionLevelScalarFieldEnum = (typeof ProclamationCategorySubscriptionLevelScalarFieldEnum)[keyof typeof ProclamationCategorySubscriptionLevelScalarFieldEnum]
export type ProclamationCategoryScalarFieldEnum =
(typeof ProclamationCategoryScalarFieldEnum)[keyof typeof ProclamationCategoryScalarFieldEnum];
export const LicenseKeyScalarFieldEnum = { export const LicenseKeyScalarFieldEnum = {
id: 'id', id: 'id',
key: 'key', key: 'key',
active: 'active', active: 'active',
level: 'level', level: 'level',
userId: 'userId' userId: 'userId'
} as const; } as const
export type LicenseKeyScalarFieldEnum = (typeof LicenseKeyScalarFieldEnum)[keyof typeof LicenseKeyScalarFieldEnum]
export type LicenseKeyScalarFieldEnum =
(typeof LicenseKeyScalarFieldEnum)[keyof typeof LicenseKeyScalarFieldEnum];
export const SubscriptionLevelScalarFieldEnum = { export const SubscriptionLevelScalarFieldEnum = {
id: 'id', id: 'id',
name: 'name', name: 'name',
description: 'description' description: 'description'
} as const; } as const
export type SubscriptionLevelScalarFieldEnum = (typeof SubscriptionLevelScalarFieldEnum)[keyof typeof SubscriptionLevelScalarFieldEnum]
export type SubscriptionLevelScalarFieldEnum =
(typeof SubscriptionLevelScalarFieldEnum)[keyof typeof SubscriptionLevelScalarFieldEnum];
export const SortOrder = { export const SortOrder = {
asc: 'asc', asc: 'asc',
desc: 'desc' desc: 'desc'
} as const; } as const
export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder]
export type SortOrder = (typeof SortOrder)[keyof typeof SortOrder];
export const QueryMode = { export const QueryMode = {
default: 'default', default: 'default',
insensitive: 'insensitive' insensitive: 'insensitive'
} as const; } as const
export type QueryMode = (typeof QueryMode)[keyof typeof QueryMode]
export type QueryMode = (typeof QueryMode)[keyof typeof QueryMode];
export const NullsOrder = { export const NullsOrder = {
first: 'first', first: 'first',
last: 'last' last: 'last'
} as const; } as const
export type NullsOrder = (typeof NullsOrder)[keyof typeof NullsOrder]
export type NullsOrder = (typeof NullsOrder)[keyof typeof NullsOrder];
+17 -15
View File
@@ -1,23 +1,25 @@
/* !!! This is code generated by Prisma. Do not edit directly. !!! */ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
/* eslint-disable */ /* eslint-disable */
// biome-ignore-all lint: generated file // biome-ignore-all lint: generated file
// @ts-nocheck // @ts-nocheck
/* /*
* This is a barrel export file for all models and their related types. * This is a barrel export file for all models and their related types.
* *
* 🟢 You can import this file directly. * 🟢 You can import this file directly.
*/ */
export type * from './models/User.ts'; export type * from './models/User.ts'
export type * from './models/Profile.ts'; export type * from './models/Profile.ts'
export type * from './models/Address.ts'; export type * from './models/Address.ts'
export type * from './models/Session.ts'; export type * from './models/Session.ts'
export type * from './models/Account.ts'; export type * from './models/Account.ts'
export type * from './models/UserRole.ts'; export type * from './models/UserRole.ts'
export type * from './models/Verification.ts'; export type * from './models/Verification.ts'
export type * from './models/Proclamation.ts'; export type * from './models/Proclamation.ts'
export type * from './models/UserProclamations.ts'; export type * from './models/UserProclamations.ts'
export type * from './models/SolfeggioFrequency.ts'; export type * from './models/SolfeggioFrequency.ts'
export type * from './models/ProclamationCategory.ts'; export type * from './models/ProclamationCategory.ts'
export type * from './models/LicenseKey.ts'; export type * from './models/ProclamationCategorySubscriptionLevel.ts'
export type * from './models/SubscriptionLevel.ts'; export type * from './models/LicenseKey.ts'
export type * from './commonInputTypes.ts'; export type * from './models/SubscriptionLevel.ts'
export type * from './commonInputTypes.ts'
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -209,7 +209,8 @@ const models: AdminModelConfig[] = [
readonlyFields: ['id'], readonlyFields: ['id'],
fieldTypes: { fieldTypes: {
name: 'String', name: 'String',
parentId: 'Int' parentId: 'Int',
sortOrder: 'Int'
}, },
relationOptions: { relationOptions: {
parentId: { model: 'ProclamationCategory', labelField: 'name', valueField: 'id' } parentId: { model: 'ProclamationCategory', labelField: 'name', valueField: 'id' }
@@ -8,7 +8,20 @@ import { error } from '@sveltejs/kit';
const config = getModelConfig('license-keys')!; const config = getModelConfig('license-keys')!;
export const load: PageServerLoad = async ({ locals }) => { export const load: PageServerLoad = async ({ locals }) => {
return loadRecords(locals, config); const records = await loadRecords(locals, config);
const subscriptionLevels = await prisma.subscriptionLevel.findMany({
select: { id: true, name: true },
orderBy: { name: 'asc' }
});
return {
...records,
subscriptionLevels: subscriptionLevels.map((s: { id: number; name: string }) => ({
label: s.name,
value: s.name
}))
};
}; };
export const actions = { export const actions = {
@@ -17,45 +30,39 @@ export const actions = {
const formData = await request.formData(); const formData = await request.formData();
const email = formData.get('email')?.toString(); const email = formData.get('email')?.toString();
const deactivateOld = formData.get('deactivateOld') === 'on'; const level = formData.get('level')?.toString();
if (!email) { if (!email) {
return { success: false, error: 'Email is required' }; return { success: false, error: 'Email is required' };
} }
if (!level) {
return { success: false, error: 'Subscription level is required' };
}
const user = await prisma.user.findUnique({ where: { email } }); const user = await prisma.user.findUnique({ where: { email } });
if (!user) { if (!user) {
return { success: false, error: 'No user found with that email' }; return { success: false, error: 'No user found with that email' };
} }
// Deactivate old keys if requested
if (deactivateOld) {
await prisma.licenseKey.updateMany({
where: { userId: user.id, active: true },
data: { active: false }
});
}
// Generate 16-char hex UUID grouped as 4-4-4-4
const hex = crypto.randomUUID().replace(/-/g, '').slice(0, 16).toUpperCase(); const hex = crypto.randomUUID().replace(/-/g, '').slice(0, 16).toUpperCase();
const key = `${hex.slice(0, 4)}-${hex.slice(4, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}`; const key = `${hex.slice(0, 4)}-${hex.slice(4, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}`;
const licenseKey = await prisma.licenseKey.create({ await prisma.licenseKey.create({
data: { data: {
key, key,
active: true, active: true,
level: 'standard', level,
userId: user.id userId: user.id
} }
}); });
// Send email with license key
try { try {
const profile = await prisma.profile.findUnique({ where: { userId: user.id } });
await sendMail({ await sendMail({
to: email, to: email,
subject: 'Your License Key', subject: 'Your License Key',
data: { data: {
firstName: user.name ?? 'Valued Customer', firstName: profile?.firstName ?? user.name ?? 'Valued Customer',
licenseKey: key licenseKey: key
} }
}); });
@@ -63,6 +70,32 @@ export const actions = {
console.error('Failed to send license key email:', e); console.error('Failed to send license key email:', e);
} }
return { success: true, error: undefined };
},
replace: async ({ request, locals }) => {
if (!locals.user) throw error(401, 'Unauthorized');
const formData = await request.formData();
const keyId = formData.get('id')?.toString();
if (!keyId) return { success: false, error: 'Missing key id' };
const existing = await prisma.licenseKey.findUnique({ where: { id: keyId } });
if (!existing) return { success: false, error: 'License key not found' };
await prisma.licenseKey.delete({ where: { id: keyId } });
const hex = crypto.randomUUID().replace(/-/g, '').slice(0, 16).toUpperCase();
const key = `${hex.slice(0, 4)}-${hex.slice(4, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}`;
await prisma.licenseKey.create({
data: {
key,
active: true,
level: existing.level,
userId: existing.userId
}
});
return { success: true, error: undefined }; return { success: true, error: undefined };
} }
}; };
@@ -1,36 +1,52 @@
<script lang="ts"> <script lang="ts">
import type { PageProps } from './$types'; import type { PageProps } from './$types';
import type { ActionResult } from '$lib/svelte-admin/types'; import { enhance } from '$app/forms';
import AdminTable from '$lib/components/admin/AdminTable.svelte'; import AdminTable from '$lib/components/admin/AdminTable.svelte';
import AdminModal from '$lib/components/admin/AdminModal.svelte';
import Toast from '$lib/components/admin/Toast.svelte'; import Toast from '$lib/components/admin/Toast.svelte';
import { getModelConfig } from '$lib/svelte-admin/registry'; import { getModelConfig } from '$lib/svelte-admin/registry';
import { enhance } from '$app/forms'; import LicenseKeyForm from './LicenseKeyForm.svelte';
let { data, form }: PageProps = $props(); let { data }: PageProps = $props();
const config = getModelConfig('license-keys')!; const config = getModelConfig('license-keys')!;
let showCreateForm = $state(false); let createOpen = $state(false);
let replaceOpen = $state(false);
let replaceRecord = $state<Record<string, unknown> | null>(null);
let toastMessage = $state(''); let toastMessage = $state('');
let toastType = $state<'success' | 'error'>('success'); let toastType = $state<'success' | 'error'>('success');
let createError = $state('');
$effect(() => { function openCreate() {
if (form && 'success' in (form as ActionResult)) { createOpen = true;
const result = form as ActionResult; }
if (result.success) {
toastMessage = 'License key created and emailed'; function openReplace(record: Record<string, unknown>) {
replaceRecord = record;
replaceOpen = true;
}
function closeCreate() {
createOpen = false;
}
function closeReplace() {
replaceOpen = false;
replaceRecord = null;
}
function replaceEnhance() {
return async ({ result, update }: any) => {
if (result.type === 'success' && result.status === 200) {
closeReplace();
toastMessage = 'License key replaced';
toastType = 'success'; toastType = 'success';
showCreateForm = false;
} else { } else {
createError = result.error ?? 'Failed to create license key'; toastMessage = 'Failed to replace license key';
toastType = 'error';
} }
} await update();
}); };
function toggleForm() {
showCreateForm = !showCreateForm;
createError = '';
} }
</script> </script>
@@ -39,70 +55,76 @@
<h1 class="text-xl font-bold text-gray-900 dark:text-gray-100">{config.displayName}</h1> <h1 class="text-xl font-bold text-gray-900 dark:text-gray-100">{config.displayName}</h1>
<button <button
type="button" type="button"
onclick={toggleForm} onclick={openCreate}
class="border border-gray-300 px-3 py-1.5 text-sm font-medium dark:border-gray-600 dark:text-gray-300" class="border border-gray-300 px-3 py-1.5 text-sm font-medium dark:border-gray-600 dark:text-gray-300"
> >
{showCreateForm ? 'Cancel' : 'Create Key +'} New License Key +
</button> </button>
</div> </div>
{#if showCreateForm}
<form
method="POST"
action="?/createKey"
use:enhance
class="mb-6 border border-gray-200 p-4 dark:border-gray-700"
>
<h2 class="mb-3 text-sm font-semibold text-gray-700 dark:text-gray-300">
Create New License Key
</h2>
{#if createError}
<div class="mb-3 border border-red-300 bg-red-50 px-3 py-2 text-sm text-red-700">
{createError}
</div>
{/if}
<div class="flex flex-col gap-3">
<div>
<label
for="email"
class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300"
>
User Email
</label>
<input
type="email"
id="email"
name="email"
required
class="w-full border border-gray-300 px-3 py-1.5 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100"
placeholder="user@example.com"
/>
</div>
<label class="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300">
<input type="checkbox" name="deactivateOld" class="h-4 w-4" />
Deactivate existing active keys for this user
</label>
<div class="flex justify-end">
<button
type="submit"
class="border border-gray-300 bg-gray-100 px-4 py-1.5 text-sm font-medium hover:bg-gray-200 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700"
>
Create & Email Key
</button>
</div>
</div>
</form>
{/if}
<AdminTable <AdminTable
records={data.records} records={data.records}
listFields={config.listFields} listFields={config.listFields}
searchFields={config.searchFields} searchFields={config.searchFields}
fieldTypes={config.fieldTypes} fieldTypes={config.fieldTypes}
singular={config.displayNameSingular} singular={config.displayNameSingular}
onRowClick={openReplace}
/> />
</div> </div>
<AdminModal title="Create License Key" open={createOpen} onClose={closeCreate}>
<LicenseKeyForm subscriptionLevels={data.subscriptionLevels} onSuccess={closeCreate} />
</AdminModal>
<AdminModal title="Replace License Key" open={replaceOpen} onClose={closeReplace}>
{#if replaceRecord}
<div class="flex flex-col gap-4">
<p class="text-sm text-gray-700 dark:text-gray-300">
Generate a new key to replace <strong>{String(replaceRecord.key)}</strong>?
</p>
<div
class="rounded border border-gray-200 bg-gray-50 p-3 text-sm dark:border-gray-700 dark:bg-gray-800"
>
<div class="mb-1 text-gray-500 dark:text-gray-400">
User: <span class="font-medium text-gray-700 dark:text-gray-300"
>{String(replaceRecord['user.name'] ?? '')}</span
>
</div>
<div class="text-gray-500 dark:text-gray-400">
Level: <span class="font-medium text-gray-700 dark:text-gray-300"
>{String(replaceRecord.level ?? '')}</span
>
</div>
</div>
<p class="text-xs text-gray-500 dark:text-gray-400">
The existing key will be deleted and a new one with the same subscription level will be
created and emailed.
</p>
<form
method="POST"
action="?/replace"
use:enhance={replaceEnhance}
class="flex justify-end gap-2 pt-2"
>
<input type="hidden" name="id" value={String(replaceRecord.id)} />
<button
type="button"
onclick={closeReplace}
class="border border-gray-300 px-3 py-1.5 text-sm dark:border-gray-600 dark:text-gray-300"
>
Cancel
</button>
<button
type="submit"
class="border border-amber-300 bg-amber-50 px-4 py-1.5 text-sm font-medium hover:bg-amber-100 dark:border-amber-700 dark:bg-amber-900/30 dark:text-amber-300 dark:hover:bg-amber-900/50"
>
Generate Replacement
</button>
</form>
</div>
{/if}
</AdminModal>
{#if toastMessage} {#if toastMessage}
<Toast message={toastMessage} type={toastType} /> <Toast message={toastMessage} type={toastType} />
{/if} {/if}
@@ -0,0 +1,91 @@
<script lang="ts">
import { enhance } from '$app/forms';
let {
subscriptionLevels = [] as { label: string; value: string }[],
onSuccess
}: {
subscriptionLevels?: { label: string; value: string }[];
onSuccess?: () => void;
} = $props();
let email = $state('');
let level = $state('');
let formError = $state('');
function handleEnhance() {
return async ({ result, update }: any) => {
if (result.type === 'success' && result.status === 200) {
if (result.data?.error) {
formError = result.data.error;
} else {
email = '';
level = '';
formError = '';
await update();
onSuccess?.();
}
} else {
await update();
}
};
}
</script>
<form method="POST" action="?/createKey" use:enhance={handleEnhance}>
{#if formError}
<div class="mb-4 border border-red-300 bg-red-50 px-4 py-2 text-sm text-red-700">
{formError}
</div>
{/if}
<div class="flex flex-col gap-4">
<div>
<label
for="field-email"
class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300"
>
User Email
</label>
<input
type="email"
id="field-email"
name="email"
required
bind:value={email}
class="w-full border border-gray-300 px-3 py-1.5 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100"
placeholder="user@example.com"
/>
</div>
<div>
<label
for="field-level"
class="mb-1 block text-sm font-medium text-gray-700 dark:text-gray-300"
>
Subscription Level
</label>
<select
name="level"
id="field-level"
required
onchange={(e) => (level = (e.target as HTMLSelectElement).value)}
class="w-full border border-gray-300 px-3 py-1.5 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100"
>
<option value="" disabled selected={!level}>-- Select --</option>
{#each subscriptionLevels as opt (opt.value)}
<option value={opt.value} selected={opt.value === level}>{opt.label}</option>
{/each}
</select>
</div>
<div class="flex justify-end gap-2 pt-2">
<button
type="submit"
class="border border-gray-300 bg-gray-100 px-4 py-1.5 text-sm font-medium hover:bg-gray-200 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700"
>
Create & Email Key
</button>
</div>
</div>
</form>
@@ -10,7 +10,7 @@ export const load: PageServerLoad = async ({ locals }) => {
const records = await delegate.findMany({ const records = await delegate.findMany({
where: { parentId: null }, where: { parentId: null },
include: config.include, include: config.include,
orderBy: { id: 'asc' } orderBy: { sortOrder: 'asc' }
}); });
const relationOptionsData: Record<string, { label: string; value: string | number }[]> = {}; const relationOptionsData: Record<string, { label: string; value: string | number }[]> = {};
@@ -44,8 +44,11 @@ export const actions = {
const name = (formData.get('name')?.toString() ?? '').trim(); const name = (formData.get('name')?.toString() ?? '').trim();
const rawId = formData.get('id')?.toString(); const rawId = formData.get('id')?.toString();
const childIds = formData.getAll('childId').map(v => v.toString()); const childIds = formData.getAll('childId').map((v) => v.toString());
const childNames = formData.getAll('childName').map(v => v.toString().trim()).filter(Boolean); const childNames = formData
.getAll('childName')
.map((v) => v.toString().trim())
.filter(Boolean);
if (!name) { if (!name) {
return { success: false, error: 'Name is required', fieldErrors: { name: 'Required' } }; return { success: false, error: 'Name is required', fieldErrors: { name: 'Required' } };
@@ -63,8 +66,14 @@ export const actions = {
}); });
categoryId = id; categoryId = id;
} else { } else {
const maxSort = await delegate.findFirst({
where: { parentId: null },
orderBy: { sortOrder: 'desc' },
select: { sortOrder: true }
});
const sortOrder = (maxSort?.sortOrder ?? -1) + 1;
const created = await delegate.create({ const created = await delegate.create({
data: { name } data: { name, sortOrder }
}); });
categoryId = created.id; categoryId = created.id;
} }
@@ -104,16 +113,10 @@ export const actions = {
return { success: true }; return { success: true };
} catch (e: unknown) { } catch (e: unknown) {
if ( if (e && typeof e === 'object' && 'code' in e && (e as { code: string }).code === 'P2002') {
e &&
typeof e === 'object' &&
'code' in e &&
(e as { code: string }).code === 'P2002'
) {
return { return {
success: false, success: false,
error: error: 'A sub-category with this name already exists under this parent.'
'A sub-category with this name already exists under this parent.'
}; };
} }
throw e; throw e;
@@ -137,6 +140,24 @@ export const actions = {
await delegate.deleteMany({ where: { parentId: id } }); await delegate.deleteMany({ where: { parentId: id } });
await delegate.delete({ where: { id } }); await delegate.delete({ where: { id } });
return { success: true };
},
reorder: async ({ request }) => {
const formData = await request.formData();
const raw = formData.get('ids')?.toString();
if (!raw) return { success: false, error: 'Missing ids' };
const ids = JSON.parse(raw) as number[];
const delegate = getDelegate(config);
for (let i = 0; i < ids.length; i++) {
await delegate.update({
where: { id: ids[i] },
data: { sortOrder: i }
});
}
return { success: true }; return { success: true };
} }
}; };
@@ -5,6 +5,7 @@
import AdminModal from '$lib/components/admin/AdminModal.svelte'; import AdminModal from '$lib/components/admin/AdminModal.svelte';
import Toast from '$lib/components/admin/Toast.svelte'; import Toast from '$lib/components/admin/Toast.svelte';
import { getModelConfig } from '$lib/svelte-admin/registry'; import { getModelConfig } from '$lib/svelte-admin/registry';
import { invalidateAll } from '$app/navigation';
import CategoryForm from './CategoryForm.svelte'; import CategoryForm from './CategoryForm.svelte';
let { data, form }: PageProps = $props(); let { data, form }: PageProps = $props();
@@ -33,6 +34,13 @@
} }
}); });
async function handleReorder(ids: (string | number)[]) {
const formData = new FormData();
formData.set('ids', JSON.stringify(ids));
await fetch('?/reorder', { method: 'POST', body: formData });
await invalidateAll();
}
function openCreate() { function openCreate() {
editingRecord = null; editingRecord = null;
formError = ''; formError = '';
@@ -63,6 +71,8 @@
searchFields={config.searchFields} searchFields={config.searchFields}
fieldTypes={config.fieldTypes} fieldTypes={config.fieldTypes}
singular={config.displayNameSingular} singular={config.displayNameSingular}
draggable={true}
onReorder={handleReorder}
onRowClick={openEdit} onRowClick={openEdit}
onNew={openCreate} onNew={openCreate}
/> />