Add sub-categories to affirmation categories

Add self-referential parent/child relation on AffirmationCategory for
   one-level hierarchy. Update AffirmationForm with two-level category and
   sub-category dropdowns, server actions with find-or-create hierarchy
   logic, AffirmationList with Parent
This commit is contained in:
NeilClack
2026-02-23 10:53:15 -06:00
parent a230a1e36d
commit 3c201f9b66
14 changed files with 573 additions and 64 deletions
+11
View File
@@ -11,6 +11,17 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run migrations
run: |
set -a
source /mnt/volume_nyc3_01/Portal/.env
set +a
export DO_CA_CERTIFICATE=/etc/ssl/certs/do-ca-certificate.crt
npx prisma migrate deploy
- name: Build image
run: podman build -t portal:latest .
@@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE "AffirmationCategory" ADD COLUMN "parentId" INTEGER;
-- AddForeignKey
ALTER TABLE "AffirmationCategory" ADD CONSTRAINT "AffirmationCategory_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "AffirmationCategory"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+3
View File
@@ -130,6 +130,9 @@ model SolfeggioFrequency {
model AffirmationCategory {
id Int @id @default(autoincrement())
name String @unique
parentId Int?
parent AffirmationCategory? @relation("CategoryHierarchy", fields: [parentId], references: [id])
children AffirmationCategory[] @relation("CategoryHierarchy")
affirmations Affirmation[]
}
+1 -1
View File
@@ -110,7 +110,7 @@
class="flex items-center gap-1 hover:text-gray-900"
onclick={() => toggleSort(field)}
>
{fieldNameToLabel(field.includes('.') ? (field.split('.').pop() ?? field) : field)}
{fieldNameToLabel(field.includes('.') ? field.split('.')[0] : field)}
<span class="text-xs text-gray-400">{getSortIndicator(field)}</span>
</button>
</th>
@@ -4,6 +4,8 @@
type Category = {
id: string;
name: string;
parentId?: number | null;
children?: Category[];
};
type Frequency = {
@@ -18,6 +20,7 @@
price?: number;
categoryId?: string;
solfeggioFrequencyId?: string;
category?: { parentId?: number | null; parent?: { name: string } };
};
type FormData = {
@@ -27,6 +30,7 @@
price?: number;
categoryId?: string;
categoryName?: string;
subCategoryName?: string;
solfeggioFrequencyId?: string;
};
@@ -48,11 +52,74 @@
submitLabel = 'Save Affirmation'
}: Props = $props();
const currentCategory = $derived(
categories.find((c : Category) => c.id === (form?.categoryId ?? affirmation.categoryId))
);
const topLevelCategories = $derived(categories.filter((c) => !c.parentId));
let categoryInput = $derived(form?.categoryName ?? currentCategory?.name ?? '');
// Determine initial parent category name from form data or existing affirmation
function getInitialCategoryName(): string {
if (form?.categoryName) return form.categoryName;
if (affirmation.category?.parent) return affirmation.category.parent.name;
if (affirmation.categoryId) {
const cat = categories.find((c) => c.id === affirmation.categoryId);
if (cat?.parentId) {
const parent = categories.find((c) => String(c.id) === String(cat.parentId));
return parent?.name ?? '';
}
return cat?.name ?? '';
}
return '';
}
function getInitialSubCategoryName(): string {
if (form?.subCategoryName) return form.subCategoryName;
if (affirmation.categoryId) {
const cat = categories.find((c) => c.id === affirmation.categoryId);
if (cat?.parentId) return cat.name;
}
return '';
}
let categoryInput = $state(getInitialCategoryName());
let showNewCategory = $state(false);
let newCategoryName = $state('');
let subCategoryInput = $state(getInitialSubCategoryName());
let showNewSubCategory = $state(false);
let newSubCategoryName = $state('');
const selectedParent = $derived(topLevelCategories.find((c) => c.name === categoryInput));
const subCategories = $derived(selectedParent?.children ?? []);
function handleCategoryChange(e: Event) {
const value = (e.target as HTMLSelectElement).value;
if (value === '__new__') {
showNewCategory = true;
categoryInput = '';
} else {
showNewCategory = false;
newCategoryName = '';
categoryInput = value;
}
subCategoryInput = '';
showNewSubCategory = false;
newSubCategoryName = '';
}
function handleSubCategoryChange(e: Event) {
const value = (e.target as HTMLSelectElement).value;
if (value === '__new__') {
showNewSubCategory = true;
subCategoryInput = '';
} else {
showNewSubCategory = false;
newSubCategoryName = '';
subCategoryInput = value;
}
}
const effectiveCategoryName = $derived(showNewCategory ? newCategoryName : categoryInput);
const effectiveSubCategoryName = $derived(
showNewSubCategory ? newSubCategoryName : subCategoryInput
);
</script>
<form method="POST" {action} class="space-y-5">
@@ -60,6 +127,9 @@
<input type="hidden" name="id" value={form?.id ?? affirmation.id} />
{/if}
<input type="hidden" name="categoryName" value={effectiveCategoryName} />
<input type="hidden" name="subCategoryName" value={effectiveSubCategoryName} />
<div>
<label for="name" class="mb-1 block text-sm font-medium text-gray-700">Name</label>
<input
@@ -102,24 +172,66 @@
</div>
<div>
<label for="categoryName" class="mb-1 block text-sm font-medium text-gray-700">Category</label>
<label for="categorySelect" class="mb-1 block text-sm font-medium text-gray-700">
Category
</label>
<select
id="categorySelect"
onchange={handleCategoryChange}
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 outline-none transition-shadow focus:border-blue-500 focus:ring-2 focus:ring-blue-500"
>
<option value="" disabled selected={!categoryInput && !showNewCategory}>
Select a category
</option>
{#each topLevelCategories as category}
<option value={category.name} selected={category.name === categoryInput}>
{category.name}
</option>
{/each}
<option value="__new__" selected={showNewCategory}>New...</option>
</select>
{#if showNewCategory}
<input
type="text"
id="categoryName"
name="categoryName"
bind:value={categoryInput}
list="categories"
placeholder="New category name"
bind:value={newCategoryName}
required
class="w-full rounded-lg border border-gray-300 px-3 py-2 outline-none transition-shadow focus:border-blue-500 focus:ring-2 focus:ring-blue-500"
class="mt-2 w-full rounded-lg border border-gray-300 px-3 py-2 outline-none transition-shadow focus:border-blue-500 focus:ring-2 focus:ring-blue-500"
/>
<datalist id="categories">
{#each categories as category}
<option value={category.name}>{category.name}</option>
{/each}
</datalist>
<p class="mt-1 text-sm text-gray-500">Select existing or type to create new</p>
{/if}
</div>
{#if categoryInput || showNewCategory}
<div>
<label for="subCategorySelect" class="mb-1 block text-sm font-medium text-gray-700">
Sub-category
</label>
<select
id="subCategorySelect"
onchange={handleSubCategoryChange}
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 outline-none transition-shadow focus:border-blue-500 focus:ring-2 focus:ring-blue-500"
>
<option value="" selected={!subCategoryInput && !showNewSubCategory}>None</option>
{#each subCategories as sub}
<option value={sub.name} selected={sub.name === subCategoryInput}>
{sub.name}
</option>
{/each}
<option value="__new__" selected={showNewSubCategory}>New...</option>
</select>
{#if showNewSubCategory}
<input
type="text"
placeholder="New sub-category name"
bind:value={newSubCategoryName}
class="mt-2 w-full rounded-lg border border-gray-300 px-3 py-2 outline-none transition-shadow focus:border-blue-500 focus:ring-2 focus:ring-blue-500"
/>
{/if}
</div>
{/if}
<div>
<label for="price" class="mb-1 block text-sm font-medium text-gray-700">Price</label>
<div class="relative">
@@ -10,9 +10,16 @@
};
category?: {
name: string;
parent?: { name: string } | null;
};
};
function categoryDisplayName(category?: Affirmation['category']): string {
if (!category) return '';
if (category.parent) return `${category.parent.name} > ${category.name}`;
return category.name;
}
type SortKey = 'name' | 'category' | 'frequency' | 'price';
type SortDirection = 'asc' | 'desc';
@@ -28,7 +35,7 @@
let sortKey = $state<SortKey>('name');
let sortDirection = $state<SortDirection>('asc');
const categories = $derived([...new Set(affirmations.map((a) => a.category?.name).filter(Boolean))].sort());
const categories = $derived([...new Set(affirmations.map((a) => categoryDisplayName(a.category)).filter(Boolean))].sort());
const frequencies = $derived([...new Set(affirmations.map((a) => a.solfeggioFrequency?.name).filter(Boolean))].sort());
const filteredAndSorted = $derived(() => {
@@ -41,14 +48,14 @@
(a) =>
a.name.toLowerCase().includes(searchLower) ||
a.content.toLowerCase().includes(searchLower) ||
a.category?.name.toLowerCase().includes(searchLower) ||
categoryDisplayName(a.category).toLowerCase().includes(searchLower) ||
a.solfeggioFrequency?.name.toLowerCase().includes(searchLower)
);
}
// Category filter
if (categoryFilter) {
result = result.filter((a) => a.category?.name === categoryFilter);
result = result.filter((a) => categoryDisplayName(a.category) === categoryFilter);
}
// Frequency filter
@@ -67,8 +74,8 @@
bVal = b.name.toLowerCase();
break;
case 'category':
aVal = a.category?.name?.toLowerCase() ?? '';
bVal = b.category?.name?.toLowerCase() ?? '';
aVal = categoryDisplayName(a.category).toLowerCase();
bVal = categoryDisplayName(b.category).toLowerCase();
break;
case 'frequency':
aVal = a.solfeggioFrequency?.value ?? 0;
@@ -206,7 +213,7 @@
{#each filteredAndSorted() as affirmation}
<tr class="border-b border-gray-100 hover:bg-gray-50">
<td class="px-4 py-3 font-medium text-gray-900">{affirmation.name}</td>
<td class="px-4 py-3 text-gray-600">{affirmation.category?.name ?? '—'}</td>
<td class="px-4 py-3 text-gray-600">{categoryDisplayName(affirmation.category) || '—'}</td>
<td class="px-4 py-3 text-gray-600">{affirmation.solfeggioFrequency?.name ?? '—'}</td>
<td class="px-4 py-3 text-right text-gray-600">${affirmation.price.toFixed(2)}</td>
<td class="px-4 py-3 text-right">
File diff suppressed because one or more lines are too long
@@ -1381,7 +1381,8 @@ export type SolfeggioFrequencyScalarFieldEnum = (typeof SolfeggioFrequencyScalar
export const AffirmationCategoryScalarFieldEnum = {
id: 'id',
name: 'name'
name: 'name',
parentId: 'parentId'
} as const
export type AffirmationCategoryScalarFieldEnum = (typeof AffirmationCategoryScalarFieldEnum)[keyof typeof AffirmationCategoryScalarFieldEnum]
@@ -194,7 +194,8 @@ export type SolfeggioFrequencyScalarFieldEnum = (typeof SolfeggioFrequencyScalar
export const AffirmationCategoryScalarFieldEnum = {
id: 'id',
name: 'name'
name: 'name',
parentId: 'parentId'
} as const
export type AffirmationCategoryScalarFieldEnum = (typeof AffirmationCategoryScalarFieldEnum)[keyof typeof AffirmationCategoryScalarFieldEnum]
@@ -28,50 +28,60 @@ export type AggregateAffirmationCategory = {
export type AffirmationCategoryAvgAggregateOutputType = {
id: number | null
parentId: number | null
}
export type AffirmationCategorySumAggregateOutputType = {
id: number | null
parentId: number | null
}
export type AffirmationCategoryMinAggregateOutputType = {
id: number | null
name: string | null
parentId: number | null
}
export type AffirmationCategoryMaxAggregateOutputType = {
id: number | null
name: string | null
parentId: number | null
}
export type AffirmationCategoryCountAggregateOutputType = {
id: number
name: number
parentId: number
_all: number
}
export type AffirmationCategoryAvgAggregateInputType = {
id?: true
parentId?: true
}
export type AffirmationCategorySumAggregateInputType = {
id?: true
parentId?: true
}
export type AffirmationCategoryMinAggregateInputType = {
id?: true
name?: true
parentId?: true
}
export type AffirmationCategoryMaxAggregateInputType = {
id?: true
name?: true
parentId?: true
}
export type AffirmationCategoryCountAggregateInputType = {
id?: true
name?: true
parentId?: true
_all?: true
}
@@ -164,6 +174,7 @@ export type AffirmationCategoryGroupByArgs<ExtArgs extends runtime.Types.Extensi
export type AffirmationCategoryGroupByOutputType = {
id: number
name: string
parentId: number | null
_count: AffirmationCategoryCountAggregateOutputType | null
_avg: AffirmationCategoryAvgAggregateOutputType | null
_sum: AffirmationCategorySumAggregateOutputType | null
@@ -192,12 +203,18 @@ export type AffirmationCategoryWhereInput = {
NOT?: Prisma.AffirmationCategoryWhereInput | Prisma.AffirmationCategoryWhereInput[]
id?: Prisma.IntFilter<"AffirmationCategory"> | number
name?: Prisma.StringFilter<"AffirmationCategory"> | string
parentId?: Prisma.IntNullableFilter<"AffirmationCategory"> | number | null
parent?: Prisma.XOR<Prisma.AffirmationCategoryNullableScalarRelationFilter, Prisma.AffirmationCategoryWhereInput> | null
children?: Prisma.AffirmationCategoryListRelationFilter
affirmations?: Prisma.AffirmationListRelationFilter
}
export type AffirmationCategoryOrderByWithRelationInput = {
id?: Prisma.SortOrder
name?: Prisma.SortOrder
parentId?: Prisma.SortOrderInput | Prisma.SortOrder
parent?: Prisma.AffirmationCategoryOrderByWithRelationInput
children?: Prisma.AffirmationCategoryOrderByRelationAggregateInput
affirmations?: Prisma.AffirmationOrderByRelationAggregateInput
}
@@ -207,12 +224,16 @@ export type AffirmationCategoryWhereUniqueInput = Prisma.AtLeast<{
AND?: Prisma.AffirmationCategoryWhereInput | Prisma.AffirmationCategoryWhereInput[]
OR?: Prisma.AffirmationCategoryWhereInput[]
NOT?: Prisma.AffirmationCategoryWhereInput | Prisma.AffirmationCategoryWhereInput[]
parentId?: Prisma.IntNullableFilter<"AffirmationCategory"> | number | null
parent?: Prisma.XOR<Prisma.AffirmationCategoryNullableScalarRelationFilter, Prisma.AffirmationCategoryWhereInput> | null
children?: Prisma.AffirmationCategoryListRelationFilter
affirmations?: Prisma.AffirmationListRelationFilter
}, "id" | "name">
export type AffirmationCategoryOrderByWithAggregationInput = {
id?: Prisma.SortOrder
name?: Prisma.SortOrder
parentId?: Prisma.SortOrderInput | Prisma.SortOrder
_count?: Prisma.AffirmationCategoryCountOrderByAggregateInput
_avg?: Prisma.AffirmationCategoryAvgOrderByAggregateInput
_max?: Prisma.AffirmationCategoryMaxOrderByAggregateInput
@@ -226,33 +247,43 @@ export type AffirmationCategoryScalarWhereWithAggregatesInput = {
NOT?: Prisma.AffirmationCategoryScalarWhereWithAggregatesInput | Prisma.AffirmationCategoryScalarWhereWithAggregatesInput[]
id?: Prisma.IntWithAggregatesFilter<"AffirmationCategory"> | number
name?: Prisma.StringWithAggregatesFilter<"AffirmationCategory"> | string
parentId?: Prisma.IntNullableWithAggregatesFilter<"AffirmationCategory"> | number | null
}
export type AffirmationCategoryCreateInput = {
name: string
parent?: Prisma.AffirmationCategoryCreateNestedOneWithoutChildrenInput
children?: Prisma.AffirmationCategoryCreateNestedManyWithoutParentInput
affirmations?: Prisma.AffirmationCreateNestedManyWithoutCategoryInput
}
export type AffirmationCategoryUncheckedCreateInput = {
id?: number
name: string
parentId?: number | null
children?: Prisma.AffirmationCategoryUncheckedCreateNestedManyWithoutParentInput
affirmations?: Prisma.AffirmationUncheckedCreateNestedManyWithoutCategoryInput
}
export type AffirmationCategoryUpdateInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string
parent?: Prisma.AffirmationCategoryUpdateOneWithoutChildrenNestedInput
children?: Prisma.AffirmationCategoryUpdateManyWithoutParentNestedInput
affirmations?: Prisma.AffirmationUpdateManyWithoutCategoryNestedInput
}
export type AffirmationCategoryUncheckedUpdateInput = {
id?: Prisma.IntFieldUpdateOperationsInput | number
name?: Prisma.StringFieldUpdateOperationsInput | string
parentId?: Prisma.NullableIntFieldUpdateOperationsInput | number | null
children?: Prisma.AffirmationCategoryUncheckedUpdateManyWithoutParentNestedInput
affirmations?: Prisma.AffirmationUncheckedUpdateManyWithoutCategoryNestedInput
}
export type AffirmationCategoryCreateManyInput = {
id?: number
name: string
parentId?: number | null
}
export type AffirmationCategoryUpdateManyMutationInput = {
@@ -262,6 +293,7 @@ export type AffirmationCategoryUpdateManyMutationInput = {
export type AffirmationCategoryUncheckedUpdateManyInput = {
id?: Prisma.IntFieldUpdateOperationsInput | number
name?: Prisma.StringFieldUpdateOperationsInput | string
parentId?: Prisma.NullableIntFieldUpdateOperationsInput | number | null
}
export type AffirmationCategoryScalarRelationFilter = {
@@ -269,27 +301,47 @@ export type AffirmationCategoryScalarRelationFilter = {
isNot?: Prisma.AffirmationCategoryWhereInput
}
export type AffirmationCategoryNullableScalarRelationFilter = {
is?: Prisma.AffirmationCategoryWhereInput | null
isNot?: Prisma.AffirmationCategoryWhereInput | null
}
export type AffirmationCategoryListRelationFilter = {
every?: Prisma.AffirmationCategoryWhereInput
some?: Prisma.AffirmationCategoryWhereInput
none?: Prisma.AffirmationCategoryWhereInput
}
export type AffirmationCategoryOrderByRelationAggregateInput = {
_count?: Prisma.SortOrder
}
export type AffirmationCategoryCountOrderByAggregateInput = {
id?: Prisma.SortOrder
name?: Prisma.SortOrder
parentId?: Prisma.SortOrder
}
export type AffirmationCategoryAvgOrderByAggregateInput = {
id?: Prisma.SortOrder
parentId?: Prisma.SortOrder
}
export type AffirmationCategoryMaxOrderByAggregateInput = {
id?: Prisma.SortOrder
name?: Prisma.SortOrder
parentId?: Prisma.SortOrder
}
export type AffirmationCategoryMinOrderByAggregateInput = {
id?: Prisma.SortOrder
name?: Prisma.SortOrder
parentId?: Prisma.SortOrder
}
export type AffirmationCategorySumOrderByAggregateInput = {
id?: Prisma.SortOrder
parentId?: Prisma.SortOrder
}
export type AffirmationCategoryCreateNestedOneWithoutAffirmationsInput = {
@@ -306,13 +358,75 @@ export type AffirmationCategoryUpdateOneRequiredWithoutAffirmationsNestedInput =
update?: Prisma.XOR<Prisma.XOR<Prisma.AffirmationCategoryUpdateToOneWithWhereWithoutAffirmationsInput, Prisma.AffirmationCategoryUpdateWithoutAffirmationsInput>, Prisma.AffirmationCategoryUncheckedUpdateWithoutAffirmationsInput>
}
export type AffirmationCategoryCreateNestedOneWithoutChildrenInput = {
create?: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutChildrenInput, Prisma.AffirmationCategoryUncheckedCreateWithoutChildrenInput>
connectOrCreate?: Prisma.AffirmationCategoryCreateOrConnectWithoutChildrenInput
connect?: Prisma.AffirmationCategoryWhereUniqueInput
}
export type AffirmationCategoryCreateNestedManyWithoutParentInput = {
create?: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutParentInput, Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput> | Prisma.AffirmationCategoryCreateWithoutParentInput[] | Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput[]
connectOrCreate?: Prisma.AffirmationCategoryCreateOrConnectWithoutParentInput | Prisma.AffirmationCategoryCreateOrConnectWithoutParentInput[]
createMany?: Prisma.AffirmationCategoryCreateManyParentInputEnvelope
connect?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
}
export type AffirmationCategoryUncheckedCreateNestedManyWithoutParentInput = {
create?: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutParentInput, Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput> | Prisma.AffirmationCategoryCreateWithoutParentInput[] | Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput[]
connectOrCreate?: Prisma.AffirmationCategoryCreateOrConnectWithoutParentInput | Prisma.AffirmationCategoryCreateOrConnectWithoutParentInput[]
createMany?: Prisma.AffirmationCategoryCreateManyParentInputEnvelope
connect?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
}
export type AffirmationCategoryUpdateOneWithoutChildrenNestedInput = {
create?: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutChildrenInput, Prisma.AffirmationCategoryUncheckedCreateWithoutChildrenInput>
connectOrCreate?: Prisma.AffirmationCategoryCreateOrConnectWithoutChildrenInput
upsert?: Prisma.AffirmationCategoryUpsertWithoutChildrenInput
disconnect?: Prisma.AffirmationCategoryWhereInput | boolean
delete?: Prisma.AffirmationCategoryWhereInput | boolean
connect?: Prisma.AffirmationCategoryWhereUniqueInput
update?: Prisma.XOR<Prisma.XOR<Prisma.AffirmationCategoryUpdateToOneWithWhereWithoutChildrenInput, Prisma.AffirmationCategoryUpdateWithoutChildrenInput>, Prisma.AffirmationCategoryUncheckedUpdateWithoutChildrenInput>
}
export type AffirmationCategoryUpdateManyWithoutParentNestedInput = {
create?: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutParentInput, Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput> | Prisma.AffirmationCategoryCreateWithoutParentInput[] | Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput[]
connectOrCreate?: Prisma.AffirmationCategoryCreateOrConnectWithoutParentInput | Prisma.AffirmationCategoryCreateOrConnectWithoutParentInput[]
upsert?: Prisma.AffirmationCategoryUpsertWithWhereUniqueWithoutParentInput | Prisma.AffirmationCategoryUpsertWithWhereUniqueWithoutParentInput[]
createMany?: Prisma.AffirmationCategoryCreateManyParentInputEnvelope
set?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
disconnect?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
delete?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
connect?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
update?: Prisma.AffirmationCategoryUpdateWithWhereUniqueWithoutParentInput | Prisma.AffirmationCategoryUpdateWithWhereUniqueWithoutParentInput[]
updateMany?: Prisma.AffirmationCategoryUpdateManyWithWhereWithoutParentInput | Prisma.AffirmationCategoryUpdateManyWithWhereWithoutParentInput[]
deleteMany?: Prisma.AffirmationCategoryScalarWhereInput | Prisma.AffirmationCategoryScalarWhereInput[]
}
export type AffirmationCategoryUncheckedUpdateManyWithoutParentNestedInput = {
create?: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutParentInput, Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput> | Prisma.AffirmationCategoryCreateWithoutParentInput[] | Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput[]
connectOrCreate?: Prisma.AffirmationCategoryCreateOrConnectWithoutParentInput | Prisma.AffirmationCategoryCreateOrConnectWithoutParentInput[]
upsert?: Prisma.AffirmationCategoryUpsertWithWhereUniqueWithoutParentInput | Prisma.AffirmationCategoryUpsertWithWhereUniqueWithoutParentInput[]
createMany?: Prisma.AffirmationCategoryCreateManyParentInputEnvelope
set?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
disconnect?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
delete?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
connect?: Prisma.AffirmationCategoryWhereUniqueInput | Prisma.AffirmationCategoryWhereUniqueInput[]
update?: Prisma.AffirmationCategoryUpdateWithWhereUniqueWithoutParentInput | Prisma.AffirmationCategoryUpdateWithWhereUniqueWithoutParentInput[]
updateMany?: Prisma.AffirmationCategoryUpdateManyWithWhereWithoutParentInput | Prisma.AffirmationCategoryUpdateManyWithWhereWithoutParentInput[]
deleteMany?: Prisma.AffirmationCategoryScalarWhereInput | Prisma.AffirmationCategoryScalarWhereInput[]
}
export type AffirmationCategoryCreateWithoutAffirmationsInput = {
name: string
parent?: Prisma.AffirmationCategoryCreateNestedOneWithoutChildrenInput
children?: Prisma.AffirmationCategoryCreateNestedManyWithoutParentInput
}
export type AffirmationCategoryUncheckedCreateWithoutAffirmationsInput = {
id?: number
name: string
parentId?: number | null
children?: Prisma.AffirmationCategoryUncheckedCreateNestedManyWithoutParentInput
}
export type AffirmationCategoryCreateOrConnectWithoutAffirmationsInput = {
@@ -333,11 +447,128 @@ export type AffirmationCategoryUpdateToOneWithWhereWithoutAffirmationsInput = {
export type AffirmationCategoryUpdateWithoutAffirmationsInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string
parent?: Prisma.AffirmationCategoryUpdateOneWithoutChildrenNestedInput
children?: Prisma.AffirmationCategoryUpdateManyWithoutParentNestedInput
}
export type AffirmationCategoryUncheckedUpdateWithoutAffirmationsInput = {
id?: Prisma.IntFieldUpdateOperationsInput | number
name?: Prisma.StringFieldUpdateOperationsInput | string
parentId?: Prisma.NullableIntFieldUpdateOperationsInput | number | null
children?: Prisma.AffirmationCategoryUncheckedUpdateManyWithoutParentNestedInput
}
export type AffirmationCategoryCreateWithoutChildrenInput = {
name: string
parent?: Prisma.AffirmationCategoryCreateNestedOneWithoutChildrenInput
affirmations?: Prisma.AffirmationCreateNestedManyWithoutCategoryInput
}
export type AffirmationCategoryUncheckedCreateWithoutChildrenInput = {
id?: number
name: string
parentId?: number | null
affirmations?: Prisma.AffirmationUncheckedCreateNestedManyWithoutCategoryInput
}
export type AffirmationCategoryCreateOrConnectWithoutChildrenInput = {
where: Prisma.AffirmationCategoryWhereUniqueInput
create: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutChildrenInput, Prisma.AffirmationCategoryUncheckedCreateWithoutChildrenInput>
}
export type AffirmationCategoryCreateWithoutParentInput = {
name: string
children?: Prisma.AffirmationCategoryCreateNestedManyWithoutParentInput
affirmations?: Prisma.AffirmationCreateNestedManyWithoutCategoryInput
}
export type AffirmationCategoryUncheckedCreateWithoutParentInput = {
id?: number
name: string
children?: Prisma.AffirmationCategoryUncheckedCreateNestedManyWithoutParentInput
affirmations?: Prisma.AffirmationUncheckedCreateNestedManyWithoutCategoryInput
}
export type AffirmationCategoryCreateOrConnectWithoutParentInput = {
where: Prisma.AffirmationCategoryWhereUniqueInput
create: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutParentInput, Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput>
}
export type AffirmationCategoryCreateManyParentInputEnvelope = {
data: Prisma.AffirmationCategoryCreateManyParentInput | Prisma.AffirmationCategoryCreateManyParentInput[]
skipDuplicates?: boolean
}
export type AffirmationCategoryUpsertWithoutChildrenInput = {
update: Prisma.XOR<Prisma.AffirmationCategoryUpdateWithoutChildrenInput, Prisma.AffirmationCategoryUncheckedUpdateWithoutChildrenInput>
create: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutChildrenInput, Prisma.AffirmationCategoryUncheckedCreateWithoutChildrenInput>
where?: Prisma.AffirmationCategoryWhereInput
}
export type AffirmationCategoryUpdateToOneWithWhereWithoutChildrenInput = {
where?: Prisma.AffirmationCategoryWhereInput
data: Prisma.XOR<Prisma.AffirmationCategoryUpdateWithoutChildrenInput, Prisma.AffirmationCategoryUncheckedUpdateWithoutChildrenInput>
}
export type AffirmationCategoryUpdateWithoutChildrenInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string
parent?: Prisma.AffirmationCategoryUpdateOneWithoutChildrenNestedInput
affirmations?: Prisma.AffirmationUpdateManyWithoutCategoryNestedInput
}
export type AffirmationCategoryUncheckedUpdateWithoutChildrenInput = {
id?: Prisma.IntFieldUpdateOperationsInput | number
name?: Prisma.StringFieldUpdateOperationsInput | string
parentId?: Prisma.NullableIntFieldUpdateOperationsInput | number | null
affirmations?: Prisma.AffirmationUncheckedUpdateManyWithoutCategoryNestedInput
}
export type AffirmationCategoryUpsertWithWhereUniqueWithoutParentInput = {
where: Prisma.AffirmationCategoryWhereUniqueInput
update: Prisma.XOR<Prisma.AffirmationCategoryUpdateWithoutParentInput, Prisma.AffirmationCategoryUncheckedUpdateWithoutParentInput>
create: Prisma.XOR<Prisma.AffirmationCategoryCreateWithoutParentInput, Prisma.AffirmationCategoryUncheckedCreateWithoutParentInput>
}
export type AffirmationCategoryUpdateWithWhereUniqueWithoutParentInput = {
where: Prisma.AffirmationCategoryWhereUniqueInput
data: Prisma.XOR<Prisma.AffirmationCategoryUpdateWithoutParentInput, Prisma.AffirmationCategoryUncheckedUpdateWithoutParentInput>
}
export type AffirmationCategoryUpdateManyWithWhereWithoutParentInput = {
where: Prisma.AffirmationCategoryScalarWhereInput
data: Prisma.XOR<Prisma.AffirmationCategoryUpdateManyMutationInput, Prisma.AffirmationCategoryUncheckedUpdateManyWithoutParentInput>
}
export type AffirmationCategoryScalarWhereInput = {
AND?: Prisma.AffirmationCategoryScalarWhereInput | Prisma.AffirmationCategoryScalarWhereInput[]
OR?: Prisma.AffirmationCategoryScalarWhereInput[]
NOT?: Prisma.AffirmationCategoryScalarWhereInput | Prisma.AffirmationCategoryScalarWhereInput[]
id?: Prisma.IntFilter<"AffirmationCategory"> | number
name?: Prisma.StringFilter<"AffirmationCategory"> | string
parentId?: Prisma.IntNullableFilter<"AffirmationCategory"> | number | null
}
export type AffirmationCategoryCreateManyParentInput = {
id?: number
name: string
}
export type AffirmationCategoryUpdateWithoutParentInput = {
name?: Prisma.StringFieldUpdateOperationsInput | string
children?: Prisma.AffirmationCategoryUpdateManyWithoutParentNestedInput
affirmations?: Prisma.AffirmationUpdateManyWithoutCategoryNestedInput
}
export type AffirmationCategoryUncheckedUpdateWithoutParentInput = {
id?: Prisma.IntFieldUpdateOperationsInput | number
name?: Prisma.StringFieldUpdateOperationsInput | string
children?: Prisma.AffirmationCategoryUncheckedUpdateManyWithoutParentNestedInput
affirmations?: Prisma.AffirmationUncheckedUpdateManyWithoutCategoryNestedInput
}
export type AffirmationCategoryUncheckedUpdateManyWithoutParentInput = {
id?: Prisma.IntFieldUpdateOperationsInput | number
name?: Prisma.StringFieldUpdateOperationsInput | string
}
@@ -346,10 +577,12 @@ export type AffirmationCategoryUncheckedUpdateWithoutAffirmationsInput = {
*/
export type AffirmationCategoryCountOutputType = {
children: number
affirmations: number
}
export type AffirmationCategoryCountOutputTypeSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
children?: boolean | AffirmationCategoryCountOutputTypeCountChildrenArgs
affirmations?: boolean | AffirmationCategoryCountOutputTypeCountAffirmationsArgs
}
@@ -363,6 +596,13 @@ export type AffirmationCategoryCountOutputTypeDefaultArgs<ExtArgs extends runtim
select?: Prisma.AffirmationCategoryCountOutputTypeSelect<ExtArgs> | null
}
/**
* AffirmationCategoryCountOutputType without action
*/
export type AffirmationCategoryCountOutputTypeCountChildrenArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
where?: Prisma.AffirmationCategoryWhereInput
}
/**
* AffirmationCategoryCountOutputType without action
*/
@@ -374,6 +614,9 @@ export type AffirmationCategoryCountOutputTypeCountAffirmationsArgs<ExtArgs exte
export type AffirmationCategorySelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean
name?: boolean
parentId?: boolean
parent?: boolean | Prisma.AffirmationCategory$parentArgs<ExtArgs>
children?: boolean | Prisma.AffirmationCategory$childrenArgs<ExtArgs>
affirmations?: boolean | Prisma.AffirmationCategory$affirmationsArgs<ExtArgs>
_count?: boolean | Prisma.AffirmationCategoryCountOutputTypeDefaultArgs<ExtArgs>
}, ExtArgs["result"]["affirmationCategory"]>
@@ -381,34 +624,48 @@ export type AffirmationCategorySelect<ExtArgs extends runtime.Types.Extensions.I
export type AffirmationCategorySelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean
name?: boolean
parentId?: boolean
parent?: boolean | Prisma.AffirmationCategory$parentArgs<ExtArgs>
}, ExtArgs["result"]["affirmationCategory"]>
export type AffirmationCategorySelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
id?: boolean
name?: boolean
parentId?: boolean
parent?: boolean | Prisma.AffirmationCategory$parentArgs<ExtArgs>
}, ExtArgs["result"]["affirmationCategory"]>
export type AffirmationCategorySelectScalar = {
id?: boolean
name?: boolean
parentId?: boolean
}
export type AffirmationCategoryOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "name", ExtArgs["result"]["affirmationCategory"]>
export type AffirmationCategoryOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "name" | "parentId", ExtArgs["result"]["affirmationCategory"]>
export type AffirmationCategoryInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
parent?: boolean | Prisma.AffirmationCategory$parentArgs<ExtArgs>
children?: boolean | Prisma.AffirmationCategory$childrenArgs<ExtArgs>
affirmations?: boolean | Prisma.AffirmationCategory$affirmationsArgs<ExtArgs>
_count?: boolean | Prisma.AffirmationCategoryCountOutputTypeDefaultArgs<ExtArgs>
}
export type AffirmationCategoryIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {}
export type AffirmationCategoryIncludeUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {}
export type AffirmationCategoryIncludeCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
parent?: boolean | Prisma.AffirmationCategory$parentArgs<ExtArgs>
}
export type AffirmationCategoryIncludeUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
parent?: boolean | Prisma.AffirmationCategory$parentArgs<ExtArgs>
}
export type $AffirmationCategoryPayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
name: "AffirmationCategory"
objects: {
parent: Prisma.$AffirmationCategoryPayload<ExtArgs> | null
children: Prisma.$AffirmationCategoryPayload<ExtArgs>[]
affirmations: Prisma.$AffirmationPayload<ExtArgs>[]
}
scalars: runtime.Types.Extensions.GetPayloadResult<{
id: number
name: string
parentId: number | null
}, ExtArgs["result"]["affirmationCategory"]>
composites: {}
}
@@ -803,6 +1060,8 @@ readonly fields: AffirmationCategoryFieldRefs;
*/
export interface Prisma__AffirmationCategoryClient<T, Null = never, ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> extends Prisma.PrismaPromise<T> {
readonly [Symbol.toStringTag]: "PrismaPromise"
parent<T extends Prisma.AffirmationCategory$parentArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.AffirmationCategory$parentArgs<ExtArgs>>): Prisma.Prisma__AffirmationCategoryClient<runtime.Types.Result.GetResult<Prisma.$AffirmationCategoryPayload<ExtArgs>, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions>
children<T extends Prisma.AffirmationCategory$childrenArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.AffirmationCategory$childrenArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$AffirmationCategoryPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
affirmations<T extends Prisma.AffirmationCategory$affirmationsArgs<ExtArgs> = {}>(args?: Prisma.Subset<T, Prisma.AffirmationCategory$affirmationsArgs<ExtArgs>>): Prisma.PrismaPromise<runtime.Types.Result.GetResult<Prisma.$AffirmationPayload<ExtArgs>, T, "findMany", GlobalOmitOptions> | Null>
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
@@ -835,6 +1094,7 @@ export interface Prisma__AffirmationCategoryClient<T, Null = never, ExtArgs exte
export interface AffirmationCategoryFieldRefs {
readonly id: Prisma.FieldRef<"AffirmationCategory", 'Int'>
readonly name: Prisma.FieldRef<"AffirmationCategory", 'String'>
readonly parentId: Prisma.FieldRef<"AffirmationCategory", 'Int'>
}
@@ -1084,6 +1344,10 @@ export type AffirmationCategoryCreateManyAndReturnArgs<ExtArgs extends runtime.T
*/
data: Prisma.AffirmationCategoryCreateManyInput | Prisma.AffirmationCategoryCreateManyInput[]
skipDuplicates?: boolean
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.AffirmationCategoryIncludeCreateManyAndReturn<ExtArgs> | null
}
/**
@@ -1154,6 +1418,10 @@ export type AffirmationCategoryUpdateManyAndReturnArgs<ExtArgs extends runtime.T
* Limit how many AffirmationCategories to update.
*/
limit?: number
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.AffirmationCategoryIncludeUpdateManyAndReturn<ExtArgs> | null
}
/**
@@ -1222,6 +1490,49 @@ export type AffirmationCategoryDeleteManyArgs<ExtArgs extends runtime.Types.Exte
limit?: number
}
/**
* AffirmationCategory.parent
*/
export type AffirmationCategory$parentArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the AffirmationCategory
*/
select?: Prisma.AffirmationCategorySelect<ExtArgs> | null
/**
* Omit specific fields from the AffirmationCategory
*/
omit?: Prisma.AffirmationCategoryOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.AffirmationCategoryInclude<ExtArgs> | null
where?: Prisma.AffirmationCategoryWhereInput
}
/**
* AffirmationCategory.children
*/
export type AffirmationCategory$childrenArgs<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
/**
* Select specific fields to fetch from the AffirmationCategory
*/
select?: Prisma.AffirmationCategorySelect<ExtArgs> | null
/**
* Omit specific fields from the AffirmationCategory
*/
omit?: Prisma.AffirmationCategoryOmit<ExtArgs> | null
/**
* Choose, which related nodes to fetch as well
*/
include?: Prisma.AffirmationCategoryInclude<ExtArgs> | null
where?: Prisma.AffirmationCategoryWhereInput
orderBy?: Prisma.AffirmationCategoryOrderByWithRelationInput | Prisma.AffirmationCategoryOrderByWithRelationInput[]
cursor?: Prisma.AffirmationCategoryWhereUniqueInput
take?: number
skip?: number
distinct?: Prisma.AffirmationCategoryScalarFieldEnum | Prisma.AffirmationCategoryScalarFieldEnum[]
}
/**
* AffirmationCategory.affirmations
*/
+16 -5
View File
@@ -96,7 +96,7 @@ const models: AdminModelConfig[] = [
displayName: 'Affirmations',
displayNameSingular: 'Affirmation',
idType: 'String',
include: { solfeggioFrequency: true, category: true },
include: { solfeggioFrequency: true, category: { include: { parent: true } } },
listFields: ['name', 'category.name', 'solfeggioFrequency.name', 'price'],
searchFields: ['name', 'content'],
formFields: ['name', 'content', 'solfeggioFrequencyId', 'categoryId', 'price'],
@@ -152,13 +152,17 @@ const models: AdminModelConfig[] = [
displayName: 'Affirmation Categories',
displayNameSingular: 'Affirmation Category',
idType: 'Int',
include: { affirmations: true },
listFields: ['name'],
include: { affirmations: true, children: true, parent: true },
listFields: ['name', 'parent.name'],
searchFields: ['name'],
formFields: ['name'],
formFields: ['name', 'parentId'],
readonlyFields: ['id'],
fieldTypes: {
name: 'String'
name: 'String',
parentId: 'Int'
},
relationOptions: {
parentId: { model: 'AffirmationCategory', labelField: 'name', valueField: 'id' }
},
relatedRecords: [
{
@@ -167,6 +171,13 @@ const models: AdminModelConfig[] = [
type: 'has-many',
displayFields: ['name', 'price'],
editSlug: 'affirmations'
},
{
relationKey: 'children',
label: 'Sub-categories',
type: 'has-many',
displayFields: ['name'],
editSlug: 'affirmation-categories'
}
]
},
+1 -1
View File
@@ -25,7 +25,7 @@ export type AdminModelConfig = {
displayName: string;
displayNameSingular: string;
idType: 'String' | 'Int';
include?: Record<string, boolean>;
include?: Record<string, boolean | { include: Record<string, boolean> }>;
listFields: string[];
searchFields: string[];
formFields: string[];
@@ -10,20 +10,49 @@ export const load: PageServerLoad = async ({ locals }) => {
const affirmations = await prisma.affirmation.findMany({
include: {
solfeggioFrequency: true,
category: true
category: { include: { parent: true } }
}
});
const affirmationCategories = await prisma.affirmationCategory.findMany();
const affirmationCategories = await prisma.affirmationCategory.findMany({
include: { children: true }
});
const solfeggioFrequencies = await prisma.solfeggioFrequency.findMany();
return { user, affirmationCategories, affirmations, solfeggioFrequencies };
};
async function resolveCategory(categoryName: string, subCategoryName: string | null) {
let parent = await prisma.affirmationCategory.findFirst({
where: { name: categoryName, parentId: null }
});
if (!parent) {
parent = await prisma.affirmationCategory.create({
data: { name: categoryName }
});
}
if (!subCategoryName) return parent;
let child = await prisma.affirmationCategory.findFirst({
where: { name: subCategoryName, parentId: parent.id }
});
if (!child) {
child = await prisma.affirmationCategory.create({
data: { name: subCategoryName, parentId: parent.id }
});
}
return child;
}
export const actions: Actions = {
create: async ({ request }: RequestEvent) => {
const form = await request.formData();
const frequencyId = Number(form.get('solfeggioFrequencyId')?.toString()) || 0;
const price = Number(form.get('price')) || 0.0;
const categoryName = form.get('categoryName') as string;
const subCategoryName = (form.get('subCategoryName') as string) || null;
if (frequencyId === 0) {
return fail(400, {
@@ -39,15 +68,7 @@ export const actions: Actions = {
});
}
let category = await prisma.affirmationCategory.findFirst({ where: { name: categoryName } });
if (!category) {
category = await prisma.affirmationCategory.create({
data: {
name: categoryName
}
});
}
const category = await resolveCategory(categoryName, subCategoryName);
try {
const newAffirmation = await prisma.affirmation.create({
@@ -5,35 +5,59 @@ import { error, fail, type Actions, type RequestEvent, type ServerLoadEvent } fr
export const load: PageServerLoad = async ({ params }: ServerLoadEvent) => {
const affirmation = await prisma.affirmation.findUnique({
where: { id: params.id },
include: { solfeggioFrequency: true, category: true }
include: { solfeggioFrequency: true, category: { include: { parent: true } } }
});
const solfeggioFrequencies = await prisma.solfeggioFrequency.findMany();
const affirmationCategories = await prisma.affirmationCategory.findMany();
const affirmationCategories = await prisma.affirmationCategory.findMany({
include: { children: true }
});
if (!affirmation) {
throw error(404, 'not found');
}
console.log(affirmation);
return { affirmation, solfeggioFrequencies, affirmationCategories };
};
async function resolveCategory(categoryName: string, subCategoryName: string | null) {
let parent = await prisma.affirmationCategory.findFirst({
where: { name: categoryName, parentId: null }
});
if (!parent) {
parent = await prisma.affirmationCategory.create({
data: { name: categoryName }
});
}
if (!subCategoryName) return parent;
let child = await prisma.affirmationCategory.findFirst({
where: { name: subCategoryName, parentId: parent.id }
});
if (!child) {
child = await prisma.affirmationCategory.create({
data: { name: subCategoryName, parentId: parent.id }
});
}
return child;
}
export const actions: Actions = {
update: async ({ request }: RequestEvent) => {
const form = await request.formData();
const frequencyId = Number(form.get('solfeggioFrequencyId')?.toString()) || 0;
const price = Number(form.get('price')) || 0.0;
const categoryName = form.get('categoryName') as string;
const subCategoryName = (form.get('subCategoryName') as string) || null;
let category = await prisma.affirmationCategory.findFirst({ where: { name: categoryName } });
if (!category) {
category = await prisma.affirmationCategory.create({
data: {
name: categoryName
}
if (!categoryName) {
return fail(400, {
error: 'Category is required!',
...Object.fromEntries(form)
});
}
@@ -44,6 +68,8 @@ export const actions: Actions = {
});
}
const category = await resolveCategory(categoryName, subCategoryName);
try {
const updatedAffirmation = await prisma.affirmation.update({
where: {