Skip to content

Commit 078893f

Browse files
committed
Add books feature
1 parent 131cb0f commit 078893f

File tree

11 files changed

+149
-26
lines changed

11 files changed

+149
-26
lines changed

app/api/interests/route.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { prisma } from "@/lib/server/prisma";
2-
import { NextResponse } from "next/server";
1+
import {prisma} from "@/lib/server/prisma";
2+
import {NextResponse} from "next/server";
33

44
export async function GET() {
55
try {
@@ -28,6 +28,17 @@ export async function GET() {
2828
cacheStrategy: cacheStrategy,
2929
});
3030

31+
const books = await prisma.book.findMany({
32+
select: {
33+
id: true,
34+
name: true,
35+
},
36+
orderBy: {
37+
name: 'asc'
38+
},
39+
cacheStrategy: cacheStrategy,
40+
});
41+
3142
const causeAreas = await prisma.causeArea.findMany({
3243
select: {
3344
id: true,
@@ -50,12 +61,12 @@ export async function GET() {
5061
cacheStrategy: cacheStrategy,
5162
});
5263

53-
return NextResponse.json({ interests, coreValues, causeAreas, connections });
64+
return NextResponse.json({interests, coreValues, books, causeAreas, connections});
5465
} catch (error) {
5566
console.error('Error fetching interests:', error);
5667
return NextResponse.json(
57-
{ error: "Failed to fetch interests" },
58-
{ status: 500 }
68+
{error: "Failed to fetch interests"},
69+
{status: 500}
5970
);
6071
}
6172
}

app/api/profiles/route.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export async function GET(request: Request) {
1212
const maxIntroversion = url.searchParams.get("maxIntroversion");
1313
const interests = url.searchParams.get("interests")?.split(",").filter(Boolean) || [];
1414
const coreValues = url.searchParams.get("coreValues")?.split(",").filter(Boolean) || [];
15+
const books = url.searchParams.get("books")?.split(",").filter(Boolean) || [];
1516
const causeAreas = url.searchParams.get("causeAreas")?.split(",").filter(Boolean) || [];
1617
const connections = url.searchParams.get("connections")?.split(",").filter(Boolean) || [];
1718
const searchQueries = url.searchParams.get("searchQuery")?.split(",").map(q => q.trim()).filter(Boolean) || [];
@@ -116,6 +117,22 @@ export async function GET(request: Request) {
116117
];
117118
}
118119

120+
// AND
121+
if (books.length > 0) {
122+
where.profile.AND = [
123+
...where.profile.AND,
124+
...books.map((name) => ({
125+
books: {
126+
some: {
127+
value: {
128+
name: name,
129+
},
130+
},
131+
},
132+
})),
133+
];
134+
}
135+
119136
if (causeAreas.length > 0) {
120137
where.profile.AND = [
121138
...where.profile.AND,
@@ -194,6 +211,17 @@ export async function GET(request: Request) {
194211
},
195212
},
196213
},
214+
{
215+
profile: {
216+
books: {
217+
some: {
218+
value: {
219+
name: {contains: query, mode: "insensitive"},
220+
},
221+
},
222+
},
223+
},
224+
},
197225
{
198226
profile: {
199227
causeAreas: {
@@ -259,6 +287,7 @@ export async function GET(request: Request) {
259287
include: {
260288
intellectualInterests: {include: {interest: true}},
261289
coreValues: {include: {value: true}},
290+
books: {include: {value: true}},
262291
causeAreas: {include: {causeArea: true}},
263292
desiredConnections: {include: {connection: true}},
264293
promptAnswers: true,

app/api/user/update-profile/route.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ export async function POST(req: Request) {
1414
}
1515

1616
const data = await req.json();
17-
const {profile, image, name, interests = [], connections = [], coreValues = [], causeAreas = []} = data;
17+
const {profile, image, name, interests = [], connections = [], coreValues = [], books = [], causeAreas = []} = data;
1818

19+
console.log('books: ', books)
1920
Object.keys(profile).forEach(key => {
2021
if (profile[key] === '' || !profile[key]) {
2122
delete profile[key];
@@ -71,6 +72,8 @@ export async function POST(req: Request) {
7172
profileConnection: prisma.profileConnection,
7273
value: prisma.value,
7374
profileValue: prisma.profileValue,
75+
book: prisma.book,
76+
profileBook: prisma.profileBook,
7477
causeArea: prisma.causeArea,
7578
profileCauseArea: prisma.profileCauseArea,
7679
} as const;
@@ -79,7 +82,7 @@ export async function POST(req: Request) {
7982

8083
async function handleFeatures(features: any, attribute: ModelKey, profileAttribute: string, idName: string) {
8184
// Add new features
82-
if (features.length > 0 && updatedUser.profile) {
85+
if (features !== null && updatedUser.profile) {
8386
// First, find or create all features
8487
console.log('profile', profileAttribute, profileAttribute);
8588
const operations = features.map((feat: { id?: string; name: string }) =>
@@ -95,25 +98,31 @@ export async function POST(req: Request) {
9598
// Get the IDs of all created/updated features
9699
const ids = createdFeatures.map(v => v.id);
97100

98-
// First, remove all existing interests for this profile
99-
await modelMap[profileAttribute].deleteMany({
100-
where: {profileId: updatedUser.profile.id},
101+
const profileId = updatedUser.profile.id;
102+
console.log('profile ID:', profileId);
103+
104+
// First, remove all existing features for this profile
105+
const res = await modelMap[profileAttribute].deleteMany({
106+
where: {profileId: profileId},
101107
});
108+
console.log('deleted profile:', profileAttribute, res);
102109

103-
// Then, create new connections
110+
// Then, create new features
104111
if (ids.length > 0) {
105-
await modelMap[profileAttribute].createMany({
112+
const create_res =await modelMap[profileAttribute].createMany({
106113
data: ids.map(id => ({
107-
profileId: updatedUser.profile!.id,
114+
profileId: profileId,
108115
[idName]: id,
109116
})),
110117
skipDuplicates: true,
111118
});
119+
console.log('created many:', profileAttribute, create_res);
112120
}
113121
}
114122
}
115123

116124
await handleFeatures(interests, 'interest', 'profileInterest', 'interestId')
125+
await handleFeatures(books, 'book', 'profileBook', 'valueId')
117126
await handleFeatures(connections, 'connection', 'profileConnection', 'connectionId')
118127
await handleFeatures(coreValues, 'value', 'profileValue', 'valueId')
119128
await handleFeatures(causeAreas, 'causeArea', 'profileCauseArea', 'causeAreaId')

app/complete-profile/page.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function RegisterComponent() {
5656
const router = useRouter();
5757
const {data: session, update} = useSession();
5858

59-
const featureNames = ['interests', 'coreValues', 'description', 'connections', 'causeAreas'];
59+
const featureNames = ['interests', 'coreValues', 'description', 'connections', 'causeAreas', 'books'];
6060

6161
const [showMoreInfo, _setShowMoreInfo] = useState(() =>
6262
Object.fromEntries(featureNames.map((id) => [id, false]))
@@ -141,6 +141,7 @@ function RegisterComponent() {
141141
setSelFeat('coreValues', 'coreValues', 'value')
142142
setSelFeat('connections', 'desiredConnections', 'connection')
143143
setSelFeat('causeAreas', 'causeAreas', 'causeArea')
144+
setSelFeat('books', 'books', 'value')
144145

145146
setImages([])
146147
setKeys(profile?.images)
@@ -309,10 +310,11 @@ function RegisterComponent() {
309310
...(key && {image: key}),
310311
...(name && {name}),
311312
};
312-
for (const name of ['interests', 'connections', 'coreValues', 'causeAreas']) {
313+
for (const name of ['books', 'interests', 'connections', 'coreValues', 'causeAreas']) {
314+
// if (!selectedFeatures[name].size) continue;
313315
data[name] = Array.from(selectedFeatures[name]).map(id => ({
314316
id: id.startsWith('new-') ? undefined : id,
315-
name: allFeatures[name].find(i => i.id === id)?.name || id.replace('new-', '')
317+
name: allFeatures[name].find(i => i.id === id)?.name
316318
}));
317319
}
318320
console.log('data', data)
@@ -416,6 +418,20 @@ function RegisterComponent() {
416418
</p>
417419
</>
418420
},
421+
{
422+
id: 'books', title: 'Works to discuss', allowAdd: true,
423+
content: <>
424+
<p className="mt-2">
425+
List the works (books, articles, essays, reports, etc.) you would like to bring up.
426+
For each work, include the exact title (as it appears on the cover), the
427+
author’s full name, and, if necessary, the edition or publication year. For example: <i>Peter Singer - Animal
428+
Liberation</i>. If you want to focus on specific
429+
chapters, themes, or questions, note them in your description—it helps keep the discussion targeted. Don’t just write
430+
“something by Orwell” or “that new mystery”; vague entries waste time and make it harder for others to find
431+
the right work. Be explicit so everyone is literally on the same page!
432+
</p>
433+
</>
434+
},
419435
// {
420436
// id: 'causeAreas', title: 'Cause Areas', allowAdd: true,
421437
// content: <>

app/profiles/ProfileFilters.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export const dropdownConfig: { id: DropdownKey, name: string }[] = [
3131
{id: "connections", name: "Connection Type"},
3232
{id: "coreValues", name: "Values"},
3333
{id: "interests", name: "Interests"},
34+
{id: "books", name: "Works"},
3435
// {id: "causeAreas", name: "Cause Areas"},
3536
]
3637

app/profiles/page.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const initialState = {
2020
maxIntroversion: null as number | null,
2121
interests: [] as string[],
2222
coreValues: [] as string[],
23+
books: [] as string[],
2324
causeAreas: [] as string[],
2425
connections: [] as string[],
2526
searchQuery: '',
@@ -33,6 +34,7 @@ type ProfileFilters = {
3334
minIntroversion: number | null;
3435
maxIntroversion: number | null;
3536
interests: string[];
37+
books: string[];
3638
coreValues: string[];
3739
causeAreas: string[];
3840
connections: string[];
@@ -327,6 +329,18 @@ export default function ProfilePage() {
327329
</div>
328330
)}
329331
</div>
332+
<div className="mt-4 space-y-2 flex-grow">
333+
{user.profile.books?.length > 0 && (
334+
<div className="flex flex-wrap gap-1">
335+
{user.profile.books.slice(0, 6).map(({value}) => (
336+
<span key={value?.id}
337+
className="inline-block text-xs px-2 py-1 bg-blue-50 text-blue-700 dark:text-white dark:bg-gray-700 rounded-full">
338+
{value?.name}
339+
</span>
340+
))}
341+
</div>
342+
)}
343+
</div>
330344
</div>
331345
</Link>
332346
))}

lib/client/profile.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,19 +115,21 @@ export function Profile(url: string, header: any = null) {
115115

116116
interface Tags {
117117
profileAttribute: string;
118-
attribute: string;
118+
attribute?: string;
119119
title: string;
120120
}
121121

122122
const tagsConfig: Tags[] = [
123123
{profileAttribute: 'desiredConnections', attribute: 'connection', title: 'Connection Type'},
124-
{profileAttribute: 'coreValues', attribute: 'value', title: 'Values'},
124+
{profileAttribute: 'coreValues', title: 'Values'},
125125
{profileAttribute: 'intellectualInterests', attribute: 'interest', title: 'Interests'},
126+
{profileAttribute: 'books', title: 'Works to Discuss'},
126127
// {profileAttribute: 'causeAreas', attribute: 'causeArea', title: 'Cause Areas'},
127128
]
128129

129-
function getTags({profileAttribute, attribute, title}: Tags) {
130+
function getTags({profileAttribute, attribute = 'value', title}: Tags) {
130131
const values = userData?.profile?.[profileAttribute];
132+
console.log('values', values);
131133
return <div key={profileAttribute + '.div'}>
132134
{values?.length > 0 && (
133135
<div className="mt-3"><

lib/client/schema.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ export interface ProfileData {
1616
contactInfo: string;
1717
intellectualInterests: { interest?: { name?: string, id?: string } }[];
1818
coreValues: { value?: { name?: string, id?: string } }[];
19+
books: { value?: { name?: string, id?: string } }[];
1920
causeAreas: { causeArea?: { name?: string, id?: string } }[];
2021
desiredConnections: { connection?: { name?: string, id?: string } }[];
2122
promptAnswers: { prompt?: string; answer?: string, id?: string }[];
2223
images: string[];
2324
};
2425
}
2526

26-
export type DropdownKey = 'interests' | 'causeAreas' | 'connections' | 'coreValues';
27+
export type DropdownKey = 'interests' | 'causeAreas' | 'connections' | 'coreValues' | 'books';
2728
export type RangeKey = 'age' | 'introversion';
2829

2930
// type OtherKey = 'gender' | 'searchQuery';

lib/server/db-utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export async function retrieveUser(id: string) {
2929
intellectualInterests: {include: {interest: true}},
3030
causeAreas: {include: {causeArea: true}},
3131
coreValues: {include: {value: true}},
32+
books: {include: {value: true}},
3233
desiredConnections: {include: {connection: true}},
3334
promptAnswers: true,
3435
},

prisma/schema.prisma

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ model Profile {
4242
desiredConnections ProfileConnection[]
4343
intellectualInterests ProfileInterest[]
4444
coreValues ProfileValue[]
45+
books ProfileBook[]
4546
promptAnswers PromptAnswer[]
4647
}
4748

@@ -63,6 +64,12 @@ model Value {
6364
users ProfileValue[]
6465
}
6566

67+
model Book {
68+
id String @id @default(cuid())
69+
name String @unique
70+
users ProfileBook[]
71+
}
72+
6673
model CauseArea {
6774
id String @id @default(cuid())
6875
name String @unique
@@ -90,8 +97,17 @@ model ProfileInterest {
9097
model ProfileValue {
9198
profileId String
9299
valueId String
93-
profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade)
94100
value Value @relation(fields: [valueId], references: [id], onDelete: Cascade)
101+
profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade)
102+
103+
@@id([profileId, valueId])
104+
}
105+
106+
model ProfileBook {
107+
profileId String
108+
valueId String
109+
value Book @relation(fields: [valueId], references: [id], onDelete: Cascade)
110+
profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade)
95111
96112
@@id([profileId, valueId])
97113
}

0 commit comments

Comments
 (0)