mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-05-11 00:24:51 -04:00
Add interest to profile creation
This commit is contained in:
45
app/api/interests/route.ts
Normal file
45
app/api/interests/route.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { prisma } from "@/lib/server/prisma";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
// Get all interests from the database
|
||||
const interests = await prisma.interest.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
orderBy: {
|
||||
name: 'asc'
|
||||
}
|
||||
});
|
||||
|
||||
const causeAreas = await prisma.causeArea.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
orderBy: {
|
||||
name: 'asc'
|
||||
}
|
||||
});
|
||||
|
||||
const connection = await prisma.connection.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
orderBy: {
|
||||
name: 'asc'
|
||||
}
|
||||
});
|
||||
|
||||
return NextResponse.json({ interests, causeAreas, connection });
|
||||
} catch (error) {
|
||||
console.error('Error fetching interests:', error);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to fetch interests" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -14,30 +14,64 @@ export async function POST(req: Request) {
|
||||
}
|
||||
|
||||
const data = await req.json();
|
||||
console.log(`Req: ${data}`)
|
||||
const { profile, image, interests = [] } = data;
|
||||
|
||||
// Update user with the new profile information
|
||||
const updatedUser = await prisma.user.update({
|
||||
where: {email: session.user.email},
|
||||
data: {
|
||||
...(data.image && { image: data.image }),
|
||||
profile: {
|
||||
upsert: {
|
||||
create: data.profile,
|
||||
update: data.profile,
|
||||
// Start a transaction to ensure data consistency
|
||||
const result = await prisma.$transaction(async (prisma) => {
|
||||
// First, update/create the profile
|
||||
const updatedUser = await prisma.user.update({
|
||||
where: { email: session.user.email },
|
||||
data: {
|
||||
...(image && { image }),
|
||||
profile: {
|
||||
upsert: {
|
||||
create: profile,
|
||||
update: profile,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// , // Only update image if provided
|
||||
// select: {
|
||||
// id: true,
|
||||
// email: true,
|
||||
// name: true,
|
||||
// image: true,
|
||||
// },
|
||||
include: {
|
||||
profile: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Process interests if any
|
||||
if (interests.length > 0 && updatedUser.profile) {
|
||||
// First, find or create all interests
|
||||
const interestOperations = interests.map((interest: { id?: string; name: string }) =>
|
||||
prisma.interest.upsert({
|
||||
where: { id: interest.id || '' },
|
||||
update: { name: interest.name },
|
||||
create: { name: interest.name },
|
||||
})
|
||||
);
|
||||
|
||||
const createdInterests = await Promise.all(interestOperations);
|
||||
|
||||
// Get the IDs of all created/updated interests
|
||||
const interestIds = createdInterests.map(interest => interest.id);
|
||||
|
||||
// First, remove all existing interests for this profile
|
||||
await prisma.profileInterest.deleteMany({
|
||||
where: { profileId: updatedUser.profile.id },
|
||||
});
|
||||
|
||||
// Then, create new connections
|
||||
if (interestIds.length > 0) {
|
||||
await prisma.profileInterest.createMany({
|
||||
data: interestIds.map(interestId => ({
|
||||
profileId: updatedUser.profile!.id,
|
||||
interestId,
|
||||
})),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return updatedUser;
|
||||
});
|
||||
|
||||
return NextResponse.json(updatedUser);
|
||||
return NextResponse.json(result);
|
||||
} catch (error) {
|
||||
console.error('Profile update error:', error);
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -18,36 +18,52 @@ export default function CompleteProfile() {
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [allInterests, setAllInterests] = useState<{id: string, name: string}[]>([]);
|
||||
const [selectedInterests, setSelectedInterests] = useState<Set<string>>(new Set());
|
||||
const [newInterest, setNewInterest] = useState('');
|
||||
const [showDropdown, setShowDropdown] = useState(false);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const router = useRouter();
|
||||
const {data: session, update} = useSession();
|
||||
|
||||
// const [selected, setSelected] = useState(new Set(selectedInterests));
|
||||
//
|
||||
// const toggleInterest = (interestId) => {
|
||||
// setSelected((prev) => {
|
||||
// const newSet = new Set(prev);
|
||||
// newSet.has(interestId) ? newSet.delete(interestId) : newSet.add(interestId);
|
||||
// return newSet;
|
||||
// });
|
||||
// };
|
||||
// Load existing interests and set up click-outside handler
|
||||
useEffect(() => {
|
||||
async function fetchInterests() {
|
||||
try {
|
||||
const res = await fetch('/api/interests');
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
setAllInterests(data.interests || []);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading interests:', error);
|
||||
}
|
||||
}
|
||||
fetchInterests();
|
||||
|
||||
// const handleInterestSubmit = (e) => {
|
||||
// e.preventDefault();
|
||||
// onSave(Array.from(selected)); // send to API
|
||||
// };
|
||||
// Close dropdown when clicking outside
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
||||
setShowDropdown(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleImageUpload = async (e: ChangeEvent<HTMLInputElement>) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (!file) return;
|
||||
|
||||
// Validate file type
|
||||
if (!file.type.startsWith('image/')) {
|
||||
setError('Please upload an image file');
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate file size (5MB max)
|
||||
if (file.size > 5 * 1024 * 1024) {
|
||||
setError('Image size must be less than 5MB');
|
||||
return;
|
||||
@@ -82,6 +98,51 @@ export default function CompleteProfile() {
|
||||
}
|
||||
};
|
||||
|
||||
const toggleInterest = (interestId: string) => {
|
||||
setSelectedInterests(prev => {
|
||||
const newSet = new Set(prev);
|
||||
if (newSet.has(interestId)) {
|
||||
newSet.delete(interestId);
|
||||
} else {
|
||||
newSet.add(interestId);
|
||||
}
|
||||
return newSet;
|
||||
});
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
addNewInterest();
|
||||
} else if (e.key === 'Escape') {
|
||||
setShowDropdown(false);
|
||||
}
|
||||
};
|
||||
|
||||
const addNewInterest = (e?: React.FormEvent) => {
|
||||
if (e) e.preventDefault();
|
||||
const interestToAdd = newInterest.trim();
|
||||
if (!interestToAdd) return;
|
||||
|
||||
// Check if interest already exists (case-insensitive)
|
||||
const existingInterest = allInterests.find(
|
||||
i => i.name.toLowerCase() === interestToAdd.toLowerCase()
|
||||
);
|
||||
|
||||
if (existingInterest) {
|
||||
// Toggle selection if it exists
|
||||
toggleInterest(existingInterest.id);
|
||||
} else {
|
||||
// Add new interest
|
||||
const newInterestObj = { id: `new-${Date.now()}`, name: interestToAdd };
|
||||
setAllInterests(prev => [...prev, newInterestObj]);
|
||||
setSelectedInterests(prev => new Set(prev).add(newInterestObj.id));
|
||||
}
|
||||
|
||||
setNewInterest('');
|
||||
setShowDropdown(false);
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -103,10 +164,14 @@ export default function CompleteProfile() {
|
||||
personalityType,
|
||||
conflictStyle,
|
||||
},
|
||||
interests: Array.from(selectedInterests).map(id => ({
|
||||
id: id.startsWith('new-') ? undefined : id,
|
||||
name: allInterests.find(i => i.id === id)?.name || id.replace('new-', '')
|
||||
})),
|
||||
...(key && {image: key}),
|
||||
});
|
||||
console.log(`Body: ${body}`)
|
||||
// alert(body)
|
||||
|
||||
const response = await fetch('/api/user/update-profile', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -118,13 +183,10 @@ export default function CompleteProfile() {
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
setError(errorData.error || 'Failed to update profile');
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the session to reflect the changes
|
||||
await update();
|
||||
|
||||
// Redirect to the home page or dashboard
|
||||
router.push('/');
|
||||
} catch (error) {
|
||||
console.error('Profile update error:', error);
|
||||
@@ -145,17 +207,6 @@ export default function CompleteProfile() {
|
||||
const personalityOptions = Object.values(PersonalityType);
|
||||
const conflictOptions = Object.values(ConflictStyle);
|
||||
|
||||
// const answers = [
|
||||
// {
|
||||
// prompt: 'What is your favorite color?',
|
||||
// answer: 'Blue',
|
||||
// },
|
||||
// {
|
||||
// prompt: 'What is your favorite animal?',
|
||||
// answer: 'Dog',
|
||||
// }
|
||||
// ]
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-md w-full space-y-8">
|
||||
@@ -224,8 +275,7 @@ export default function CompleteProfile() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pt-4">
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label htmlFor="gender" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Gender <span className="text-red-500">*</span>
|
||||
@@ -241,83 +291,183 @@ export default function CompleteProfile() {
|
||||
<option value="">Select your gender</option>
|
||||
{genderOptions.map((g) => (
|
||||
<option key={g} value={g}>
|
||||
{g.replace(/_/g, ' ')} {/* optional: format label */}
|
||||
{g.replace(/_/g, ' ')}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="pt-4">
|
||||
<div>
|
||||
<label htmlFor="location" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Location
|
||||
</label>
|
||||
<textarea
|
||||
<input
|
||||
id="location"
|
||||
name="location"
|
||||
rows={1}
|
||||
required
|
||||
type="text"
|
||||
value={location}
|
||||
onChange={(e) => setLocation(e.target.value)}
|
||||
className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
|
||||
placeholder="City, Country"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="pt-4">
|
||||
<label htmlFor="personality" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Personality <span className="text-red-500">*</span>
|
||||
<div>
|
||||
<label htmlFor="personalityType" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Personality Type
|
||||
</label>
|
||||
<select
|
||||
id="personality"
|
||||
name="personality"
|
||||
required
|
||||
id="personalityType"
|
||||
name="personalityType"
|
||||
value={personalityType}
|
||||
onChange={(e) => setPersonalityType(e.target.value as PersonalityType)}
|
||||
className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
|
||||
>
|
||||
<option value="">Select your personality</option>
|
||||
{personalityOptions.map((g) => (
|
||||
<option key={g} value={g}>
|
||||
{g.replace(/_/g, ' ')} {/* optional: format label */}
|
||||
<option value="">Select your personality type</option>
|
||||
{personalityOptions.map((type) => (
|
||||
<option key={type} value={type}>
|
||||
{type}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="pt-4">
|
||||
<div>
|
||||
<label htmlFor="conflictStyle" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Conflict / Disagreement Style <span className="text-red-500">*</span>
|
||||
Conflict Style
|
||||
</label>
|
||||
<select
|
||||
id="conflictStyle"
|
||||
name="conflictStyle"
|
||||
required
|
||||
value={conflictStyle}
|
||||
onChange={(e) => setConflictStyle(e.target.value as ConflictStyle)}
|
||||
className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
|
||||
>
|
||||
<option value="">Select your conflictStyle</option>
|
||||
{conflictOptions.map((g) => (
|
||||
<option key={g} value={g}>
|
||||
{g.replace(/_/g, ' ')} {/* optional: format label */}
|
||||
<option value="">Select your conflict style</option>
|
||||
{conflictOptions.map((style) => (
|
||||
<option key={style} value={style}>
|
||||
{style}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* <div className="pt-4">*/}
|
||||
{/* {allInterests.map((interest) => (*/}
|
||||
{/* <label key={interest.id} className="flex items-center space-x-2">*/}
|
||||
{/* <input*/}
|
||||
{/* type="checkbox"*/}
|
||||
{/* checked={selected.has(interest.id)}*/}
|
||||
{/* onChange={() => toggleInterest(interest.id)}*/}
|
||||
{/* />*/}
|
||||
{/* <span>{interest.name}</span>*/}
|
||||
{/* </label>*/}
|
||||
{/* ))}*/}
|
||||
{/*</div>*/}
|
||||
<div className="relative" ref={dropdownRef}>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Interests
|
||||
</label>
|
||||
|
||||
<div className="relative">
|
||||
<div className="flex items-center border border-gray-300 rounded-md shadow-sm">
|
||||
<input
|
||||
type="text"
|
||||
value={newInterest}
|
||||
onChange={(e) => setNewInterest(e.target.value)}
|
||||
onFocus={() => setShowDropdown(true)}
|
||||
onKeyDown={handleKeyDown}
|
||||
className="flex-1 min-w-0 block w-full px-3 py-2 rounded-l-md border-0 focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
|
||||
placeholder="Type to search or add new interest"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowDropdown(!showDropdown)}
|
||||
className="px-3 py-2 border-l border-gray-300 bg-gray-50 text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
|
||||
>
|
||||
<svg className="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={addNewInterest}
|
||||
disabled={!newInterest.trim()}
|
||||
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-r-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="pt-4">
|
||||
{(showDropdown || newInterest) && (
|
||||
<div className="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm">
|
||||
{/* New interest option */}
|
||||
{newInterest && !allInterests.some(i =>
|
||||
i.name.toLowerCase() === newInterest.toLowerCase()
|
||||
) && (
|
||||
<div
|
||||
className="text-gray-900 cursor-default select-none relative py-2 pl-3 pr-9 hover:bg-blue-50"
|
||||
onClick={() => addNewInterest()}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<span className="font-normal ml-3 block truncate">
|
||||
Add "{newInterest}"
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Filtered interests */}
|
||||
{allInterests
|
||||
.filter(interest =>
|
||||
interest.name.toLowerCase().includes(newInterest.toLowerCase())
|
||||
)
|
||||
.map((interest) => (
|
||||
<div
|
||||
key={interest.id}
|
||||
className="text-gray-900 cursor-default select-none relative py-2 pl-3 pr-9 hover:bg-blue-50"
|
||||
onClick={() => {
|
||||
toggleInterest(interest.id);
|
||||
setNewInterest('');
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||
checked={selectedInterests.has(interest.id)}
|
||||
onChange={() => {}}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
/>
|
||||
<span className="font-normal ml-3 block truncate">
|
||||
{interest.name}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Selected interests */}
|
||||
<div className="flex flex-wrap gap-2 mt-3">
|
||||
{Array.from(selectedInterests).map(interestId => {
|
||||
const interest = allInterests.find(i => i.id === interestId);
|
||||
if (!interest) return null;
|
||||
return (
|
||||
<span
|
||||
key={interestId}
|
||||
className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-blue-100 text-blue-800"
|
||||
>
|
||||
{interest.name}
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
toggleInterest(interestId);
|
||||
}}
|
||||
className="ml-1.5 inline-flex items-center justify-center h-4 w-4 rounded-full bg-blue-200 hover:bg-blue-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
||||
>
|
||||
<span className="sr-only">Remove {interest.name}</span>
|
||||
<svg className="h-2 w-2" fill="currentColor" viewBox="0 0 8 8">
|
||||
<path d="M4 3.293L6.646.646a.5.5 0 01.708.708L4.707 4l2.647 2.646a.5.5 0 01-.708.708L4 4.707l-2.646 2.647a.5.5 0 01-.708-.708L3.293 4 .646 1.354a.5.5 0 01.708-.708L4 3.293z" />
|
||||
</svg>
|
||||
</button>
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="description" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
About You <span className="text-red-500">*</span>
|
||||
</label>
|
||||
@@ -329,72 +479,38 @@ export default function CompleteProfile() {
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
|
||||
placeholder="Tell us a bit about yourself. You can link to social media profiles or dating / connection documents."
|
||||
placeholder="Tell us about yourself, your background, and what you're looking for in connections."
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/*<div className="pt-4">*/}
|
||||
{/* <label htmlFor="description" className="block text-sm font-medium text-gray-700 mb-1">*/}
|
||||
{/* Prompts*/}
|
||||
{/* </label>*/}
|
||||
{/* {answers.map(({ prompt, answer }) => (*/}
|
||||
{/* <div key={prompt}>*/}
|
||||
{/* <label className="block font-medium">{prompt}</label>*/}
|
||||
{/* <input*/}
|
||||
{/* type="text"*/}
|
||||
{/* value={answer}*/}
|
||||
{/* onChange={(e) => handleChange(prompt, e.target.value)}*/}
|
||||
{/* className="w-full border px-2 py-1"*/}
|
||||
{/* />*/}
|
||||
{/* </div>*/}
|
||||
{/* ))}*/}
|
||||
{/*</div>*/}
|
||||
|
||||
<div className="pt-4">
|
||||
<label htmlFor="contact" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Contact Info
|
||||
<div>
|
||||
<label htmlFor="contactInfo" className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Contact Information
|
||||
</label>
|
||||
<textarea
|
||||
id="contact"
|
||||
name="contact"
|
||||
rows={4}
|
||||
required
|
||||
id="contactInfo"
|
||||
name="contactInfo"
|
||||
rows={2}
|
||||
value={contactInfo}
|
||||
onChange={(e) => setContactInfo(e.target.value)}
|
||||
className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-blue-500 focus:border-blue-500 focus:z-10 sm:text-sm"
|
||||
placeholder="Add your contact info here (email, phone, Google Form, etc.) until the chat feature is ready"
|
||||
placeholder="How can people reach you? (Email, social media, etc.)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="pt-4">
|
||||
<p className="mt-1 text-xs text-gray-500">
|
||||
Note that all the information will be public and crawlable for now—in the future, we will add different
|
||||
levels of privacy.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className={`group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 ${
|
||||
isSubmitting ? 'opacity-70 cursor-not-allowed' : ''
|
||||
}`}
|
||||
disabled={isSubmitting || isUploading}
|
||||
className={`group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white ${
|
||||
isSubmitting || isUploading
|
||||
? 'bg-blue-400 cursor-not-allowed'
|
||||
: 'bg-blue-600 hover:bg-blue-700'
|
||||
} focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500`}
|
||||
>
|
||||
{isSubmitting || isUploading ? 'Saving...' : 'Save and Continue'}
|
||||
{isSubmitting || isUploading ? 'Saving...' : 'Save Profile'}
|
||||
</button>
|
||||
|
||||
{/*<div className="mt-4 text-center">*/}
|
||||
{/* <button*/}
|
||||
{/* type="button"*/}
|
||||
{/* onClick={() => router.push('/')}*/}
|
||||
{/* className="text-sm font-medium text-blue-600 hover:text-blue-500"*/}
|
||||
{/* >*/}
|
||||
{/* Skip for now*/}
|
||||
{/* </button>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@ import {prisma} from "@/lib/server/prisma";
|
||||
|
||||
|
||||
async function main() {
|
||||
// Create some interests & cause areas
|
||||
// Create some interests and cause areas
|
||||
await prisma.interest.createMany({
|
||||
data: [
|
||||
{name: 'Philosophy'},
|
||||
|
||||
Reference in New Issue
Block a user