Hallo, ich arbeite daran, eine Profilseite zu erstellen, und errege diesen persistenten Syntaxfehler in Zeile 381 und ich kann nicht herausfinden, wie ich es beheben kann. Wenn es eine einfache Lösung ist, könnte jemand einen Blick darauf werfen, was falsch ist? Ich habe die gesamte Datei aufgenommen, obwohl der Fehler das genaue Ende ist. Ich weiß nicht, ob es hier ein größeres strukturelles Problem gibt. Vielen Dank im Voraus. < /P>
import { useEffect, useState, useRef } from 'react';
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
);
export default function ProfilePage() {
const [user, setUser] = useState(null);
const [profile, setProfile] = useState({ full_name: '', role: '', bio: '', location: '', avatar_url: '', banner_url: '' });
const [bannerFile, setBannerFile] = useState(null);
const [bannerPreviewUrl, setBannerPreviewUrl] = useState(null);
const bannerInputRef = useRef(null);
const [avatarFile, setAvatarFile] = useState(null);
const [previewUrl, setPreviewUrl] = useState(null);
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
const fileInputRef = useRef(null);
const [isEditing, setIsEditing] = useState(true);
useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }) => {
const currentUser = session?.user;
setUser(currentUser);
if (currentUser) fetchProfile(currentUser.id);
});
supabase.auth.onAuthStateChange((_event, session) => {
const currentUser = session?.user;
setUser(currentUser);
if (currentUser) fetchProfile(currentUser.id);
});
}, []);
const fetchProfile = async (id) => {
setLoading(true);
const { data } = await supabase.from('users').select('*').eq('id', id).single();
if (data) {
setProfile({
full_name: data.full_name || '',
role: data.role || '',
bio: data.bio || '',
location: data.location || '',
avatar_url: data.avatar_url || '',
banner_url: data.banner_url || ''
});
}
setLoading(false);
};
const handleFileChange = (e) => {
const file = e.target.files[0];
if (file) {
setAvatarFile(file);
setPreviewUrl(URL.createObjectURL(file));
}
};
const handleChange = (e) => {
const { name, value } = e.target;
setProfile((prevProfile) => ({
...prevProfile,
[name]: value,
}));
};
const uploadAvatar = async () => {
if (!avatarFile || !user) return;
const cleanFileName = avatarFile.name.replace(/\s+/g, '_'); // replaces spaces with underscores
const filePath = `${user.id}/${cleanFileName}`;
console.log("Uploading file to path:", filePath);
console.log("User ID at upload:", user?.id);
const { error: uploadError } = await supabase.storage
.from('avatars')
.upload(filePath, avatarFile, { upsert: true });
if (uploadError) {
console.error('Upload failed:', uploadError.message);
return null;
}
const { data: urlData } = supabase.storage.from('avatars').getPublicUrl(filePath);
return urlData.publicUrl;
};
const uploadBanner = async () => {
if (!bannerFile || !user) return;
const cleanFileName = bannerFile.name.replace(/\s+/g, '_');
const filePath = `${user.id}/banner_${cleanFileName}`;
const { error: uploadError } = await supabase.storage
.from('avatars')
.upload(filePath, bannerFile, { upsert: true });
if (uploadError) {
console.error('Banner upload failed:', uploadError.message);
return null;
}
const { data: urlData } = supabase.storage.from('avatars').getPublicUrl(filePath);
return urlData.publicUrl;
};
const saveProfile = async () => {
if (!user) return;
setLoading(true);
setSuccess(false);
let avatarUrl = profile.avatar_url;
if (avatarFile) {
const uploadedUrl = await uploadAvatar();
if (uploadedUrl) avatarUrl = uploadedUrl;
}
let bannerUrl = profile.banner_url || '';
if (bannerFile) {
const uploadedBanner = await uploadBanner();
if (uploadedBanner) bannerUrl = uploadedBanner;
}
const updates = {
id: user.id,
full_name: profile.full_name,
role: profile.role,
bio: profile.bio,
location: profile.location,
avatar_url: avatarUrl,
banner_url: bannerUrl,
updated_at: new Date(),
};
console.log("Sending to Supabase:", updates);
const { error } = await supabase.from('users').upsert(updates);
if (!error) {
setSuccess(true);
setProfile((prev) => ({
...prev,
avatar_url: avatarUrl,
banner_url: bannerUrl
}));
setIsEditing(false);
} else {
console.error("Failed to save:", error.message);
}
setLoading(false);
};
return (
{bannerPreviewUrl || profile.banner_url ? (
[img]{bannerPreviewUrl || profile.banner_url}
className="w-full max-w-4xl h-[150px] object-cover rounded-md shadow-sm mb-6"
/>
) : null}
{isEditing && (
{previewUrl || profile.avatar_url ? (
[img]{previewUrl || profile.avatar_url}
className="rounded-full shadow-lg border-4 border-white object-cover"
style={{ width: "120px", height: "120px", marginTop: "-120px" }}
/>
) : null}
)}
{!user ? (
Please sign in to view your profile.
) : (
{isEditing ? (
Full Name
Role
Select Role
Artist
Investor
Gallery
Bio
= 1000 ? 'text-red-500' : 'text-gray-500'}`}>
{profile.bio.length} / 1000 characters
Location
Upload New Avatar
fileInputRef.current?.click()}
onDragOver={(e) => e.preventDefault()}
onDrop={(e) => {
e.preventDefault();
const file = e.dataTransfer.files[0];
if (file) {
setAvatarFile(file);
setPreviewUrl(URL.createObjectURL(file));
}
}}
className="w-full border-2 border-dashed border-gray-300 rounded-lg px-6 py-4 text-sm text-gray-500 text-center hover:bg-gray-50 transition cursor-pointer"
>
Drag and drop an image, or click to browse
Upload Banner Image
bannerInputRef.current?.click()}
onDragOver={(e) => e.preventDefault()}
onDrop={(e) => {
e.preventDefault();
const file = e.dataTransfer.files[0];
if (file) {
setBannerFile(file);
setBannerPreviewUrl(URL.createObjectURL(file));
}
}}
className="w-full border-2 border-dashed border-gray-300 rounded-lg px-6 py-4 text-sm text-gray-500 text-center hover:bg-gray-50 transition cursor-pointer"
>
Drag and drop a banner image, or click to browse
{
const file = e.target.files[0];
if (file) {
setBannerFile(file);
setBannerPreviewUrl(URL.createObjectURL(file));
}
}}
className="hidden"
/>
Save Profile
) : (
{profile.avatar_url && (
[img]{profile.avatar_url}
className="rounded-full border-2 border-gray-300 object-cover"
style={{
width: "140px",
height: "140px",
position: "absolute",
top: "-100px",
left: "40px",
zIndex: 1000
}}
/>
)}
{profile.full_name}
setIsEditing(true)}
className="px-6 py-2 bg-indigo-600 text-white font-semibold rounded-full shadow-lg transition duration-300 ease-in-out hover:bg-indigo-700 hover:scale-105"
>
Edit Profile
{profile.role}
{profile.bio}
{profile.location}
120
Followers
75
Following
9
Projects
)}
)}
{success && (
Profile saved successfully!
setSuccess(false)}
className="mt-2 text-sm underline text-green-700 hover:text-green-900 transition duration-200"
>
Dismiss
)}
);
}
< /code>
übereinstimmende JSX-Klammern < /p>
Ich habe versucht, einen unsachgemäß verschachtelten Satz von und < /> -Tags aufzuräumen und ein fehlendes Nicht-Bearbeitungs-(! Issiediting) Ansicht hinzugefügt. unten. Dieser spezifische Fehler wurde gelöscht - wir kehrten zu Syntax/EOF -Fehlern zurück.
Wie kann ich unerwartete Token- und EOF -Fehler in React JSX -Rücklaufblock einer Profilkomponente auflösen? ⇐ JavaScript
-
- Similar Topics
- Replies
- Views
- Last post