Profile Friend stuff
This commit is contained in:
@@ -4,147 +4,198 @@ import { useEffect, useState } from "react";
|
|||||||
import { useDevice } from "@/lib/context/DeviceContext";
|
import { useDevice } from "@/lib/context/DeviceContext";
|
||||||
|
|
||||||
function Mobile() {
|
function Mobile() {
|
||||||
const { isAuthenticated, session } = useDevice();
|
const { isAuthenticated, session } = useDevice();
|
||||||
const [bio, setBio] = useState(session?.bio || "");
|
const [bio, setBio] = useState(session?.bio || "");
|
||||||
const [username, setUsername] = useState(session?.username || "");
|
const [username, setUsername] = useState(session?.username || "");
|
||||||
|
const [points, setPoints] = useState(session?.points || 0);
|
||||||
|
const [friends, setFriends] = useState(session?.friends || []);
|
||||||
|
const [requests, setRequests] = useState(session?.requests || []);
|
||||||
|
const [friendCode, setFriendCode] = useState(""); // Input for sending friend requests
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (session) {
|
if (isAuthenticated && session) {
|
||||||
setBio(session.bio || "");
|
setBio(session.bio || "");
|
||||||
setUsername(session.username || "");
|
setUsername(session.username || "");
|
||||||
}
|
setPoints(session.points || 0);
|
||||||
}, [session]);
|
setFriends(session.friends || []);
|
||||||
|
setRequests(session.requests || []);
|
||||||
|
}
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
function handleSubmit(e: React.FormEvent) {
|
function handleSubmit(e: React.FormEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (bio.length > 0 || username.length > 0) {
|
if (bio.length > 0 || username.length > 0) {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
if (bio.length > 0) formData.append("bio", bio);
|
if (bio.length > 0) formData.append("bio", bio);
|
||||||
if (username.length > 0) formData.append("username", username);
|
if (username.length > 0) formData.append("username", username);
|
||||||
|
|
||||||
fetch("/api/me", {
|
fetch("/api/me", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: formData, // Automatically sets Content-Type to multipart/form-data
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.message === "User updated successfully") {
|
if (data.message === "User updated successfully") {
|
||||||
alert("Profile updated successfully!");
|
alert("Profile updated successfully!");
|
||||||
} else {
|
setPoints(data.updatedPoints || points);
|
||||||
alert("Failed to update profile.");
|
} else {
|
||||||
}
|
alert("Failed to update profile.");
|
||||||
})
|
}
|
||||||
.catch((err) => {
|
})
|
||||||
console.error("Error updating profile:", err);
|
.catch((err) => {
|
||||||
alert("An error occurred while updating your profile.");
|
console.error("Error updating profile:", err);
|
||||||
});
|
alert("An error occurred while updating your profile.");
|
||||||
} else {
|
});
|
||||||
alert("Please enter a bio or username.");
|
} else {
|
||||||
}
|
alert("Please enter a bio or username.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
function handleSendFriendRequest(e: React.FormEvent) {
|
||||||
<div className="px-6 py-10 my-10 max-w-full lg:max-w-1/2 mx-auto font-sans text-neutral-100">
|
e.preventDefault();
|
||||||
<div className="bg-[color:var(--color-surface-600)]/70 backdrop-blur-md rounded-xl px-6 py-5 my-6 shadow-sm">
|
if (friendCode.length !== 5) {
|
||||||
<h1 className="text-2xl sm:text-3xl font-bold tracking-[-.01em] text-center">
|
alert("Friend code must be exactly 5 characters.");
|
||||||
Hi, {username || ""}!!
|
return;
|
||||||
</h1>
|
}
|
||||||
|
|
||||||
<div className="flex flex-col items-center mt-6 my-4">
|
const formData = new FormData();
|
||||||
{isAuthenticated && (
|
formData.append("friendCode", friendCode);
|
||||||
<img
|
|
||||||
src={"/avatar/p" + session?.avatar + ".png"}
|
|
||||||
alt="Profile Preview"
|
|
||||||
className="w-42 h-42 rounded-full object-cover bg-surface-700"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="mb-6 space-y-4">
|
fetch(`/api/user/${session?.id}`, {
|
||||||
{/* Username Input */}
|
method: "POST",
|
||||||
<input
|
body: formData,
|
||||||
type="text"
|
})
|
||||||
className="w-full p-2 rounded bg-neutral-800 text-white"
|
.then((res) => res.json())
|
||||||
onChange={(e) => setUsername(e.target.value)}
|
.then((data) => {
|
||||||
value={username || ""}
|
if (data.message === "Friend request sent successfully") {
|
||||||
placeholder="Update your username..."
|
alert("Friend request sent!");
|
||||||
/>
|
setRequests((prev: any) => [...prev, friendCode]);
|
||||||
|
setFriendCode(""); // Clear the input field
|
||||||
|
} else {
|
||||||
|
alert(data.message || "Failed to send friend request.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("Error sending friend request:", err);
|
||||||
|
alert("An error occurred while sending the friend request.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
{/* Bio Input */}
|
return (
|
||||||
<textarea
|
<div className="px-6 py-10 my-10 max-w-full lg:max-w-1/2 mx-auto font-sans text-neutral-100">
|
||||||
className="w-full p-2 rounded bg-neutral-800 text-white"
|
<div className="bg-[color:var(--color-surface-800)]/70 backdrop-blur-md rounded-xl px-6 py-5 my-6 shadow-sm">
|
||||||
onChange={(e) => setBio(e.target.value)}
|
<h1 className="text-2xl sm:text-3xl font-bold tracking-[-.01em] text-center">
|
||||||
value={bio || ""}
|
Hi, {username || ""}!!
|
||||||
placeholder="Update your bio..."
|
</h1>
|
||||||
rows={3}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Submit Button */}
|
<div className="flex flex-col items-center mt-6 my-4">
|
||||||
<button
|
{isAuthenticated && (
|
||||||
type="submit"
|
<img
|
||||||
className="w-full px-4 py-2 bg-success-600 text-white rounded"
|
src={"/avatar/p" + session?.avatar + ".png"}
|
||||||
>
|
alt="Profile Preview"
|
||||||
Save Profile
|
className="w-42 h-42 rounded-full object-cover bg-surface-700"
|
||||||
</button>
|
/>
|
||||||
</form>
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Friends */}
|
<form onSubmit={handleSubmit} className="mb-6 space-y-4">
|
||||||
<div className="bg-[color:var(--color-surface-600)] rounded-xl px-6 py-5 my-6 shadow-md">
|
{/* Username Input */}
|
||||||
<h2 className="text-3xl font-bold tracking-[-.01em] text-[color:var(--color-warning-300)]">
|
<input
|
||||||
Friends
|
type="text"
|
||||||
</h2>
|
className="w-full p-2 rounded bg-neutral-800 text-white"
|
||||||
<p className="text-lg text-neutral-100">[ friendsCount variable ]</p>
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
</div>
|
value={username || ""}
|
||||||
|
placeholder="Update your username..."
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Total Points */}
|
{/* Bio Input */}
|
||||||
<div className="bg-[color:var(--color-success-600)] rounded-xl px-6 py-6 my-6 shadow-md">
|
<textarea
|
||||||
<h2 className="text-3xl font-bold text-[color:var(--color-warning-300)] mb-2">
|
className="w-full p-2 rounded bg-neutral-800 text-white"
|
||||||
Total Points
|
onChange={(e) => setBio(e.target.value)}
|
||||||
</h2>
|
value={bio || ""}
|
||||||
<p className="text-lg text-neutral-100">[ totalPoints variable? ]</p>
|
placeholder="Update your bio..."
|
||||||
</div>
|
rows={3}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Daily Stats */}
|
{/* Submit Button */}
|
||||||
<div className="bg-[color:var(--color-surface-600)]/70 backdrop-blur-md rounded-xl px-6 py-5 my-6 shadow-sm">
|
<button
|
||||||
<h2 className="text-xl font-semibold text-[color:var(--color-warning-300)] mt-0 mb-2">
|
type="submit"
|
||||||
Daily Stats
|
className="w-full px-4 py-2 bg-success-600 text-white rounded"
|
||||||
</h2>
|
>
|
||||||
<ul className="list-disc pl-5 text-neutral-200 space-y-1">
|
Save Profile
|
||||||
<li>Points Logged: [ dailyPoints variable ]</li>
|
</button>
|
||||||
<li>Caffeine Logged (mg): [ daily caffeine variable ]</li>
|
</form>
|
||||||
<li>Sugar Logged (g): [ daily sugar variable ]</li>
|
</div>
|
||||||
</ul>
|
|
||||||
<p className="font-semibold italic text-[color:var(--color-success-300)] mt-1">
|
|
||||||
Don't forget you have a 400mg caffeine limit and 30.5g sugar limit!
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button type="button" className="btn bg-surface-800 w-full">
|
|
||||||
<a href="/auth/logout">Logout</a>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Web() {
|
{/* Friends, Friend Requests, and Send Friend Request Section */}
|
||||||
const { isAuthenticated, session } = useDevice();
|
<div className="bg-[color:var(--color-surface-800)] rounded-xl px-6 py-5 my-6 shadow-md">
|
||||||
|
<h2 className="text-3xl font-bold tracking-[-.01em] text-[color:var(--color-warning-300)] mb-4">
|
||||||
|
Friends & Requests
|
||||||
|
</h2>
|
||||||
|
|
||||||
return (
|
{/* Friend Code */}
|
||||||
<main className="flex flex-col row-start-2 items-center mt-10">
|
<div className="mb-4">
|
||||||
<h1 className="text-3xl sm:text-4xl font-bold tracking-[-.01em] text-center sm:text-left text-white">
|
<p className="text-lg text-neutral-100">
|
||||||
{isAuthenticated ? `Welcome, ${session.username} !!` : ""}
|
<strong>Friend Code:</strong> <code>{session?.id}</code>
|
||||||
</h1>
|
</p>
|
||||||
<span className="text-white">
|
</div>
|
||||||
Use the mobile app for a better experience!
|
|
||||||
</span>
|
{/* Friends List */}
|
||||||
</main>
|
<div className="mb-6">
|
||||||
);
|
<h3 className="text-2xl font-semibold text-[color:var(--color-warning-200)] mb-2">
|
||||||
|
Friends
|
||||||
|
</h3>
|
||||||
|
<ul className="list-disc pl-5 text-neutral-200 space-y-1">
|
||||||
|
{friends.length > 0 ? (
|
||||||
|
friends.map((friend: any, index: any) => <li key={index}>{friend}</li>)
|
||||||
|
) : (
|
||||||
|
<p className="text-neutral-400">No friends yet.</p>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Friend Requests */}
|
||||||
|
<div className="mb-6">
|
||||||
|
<h3 className="text-2xl font-semibold text-[color:var(--color-warning-200)] mb-2">
|
||||||
|
Friend Requests
|
||||||
|
</h3>
|
||||||
|
<ul className="list-disc pl-5 text-neutral-200 space-y-1">
|
||||||
|
{requests.length > 0 ? (
|
||||||
|
requests.map((request: any, index: any) => <li key={index}>{request}</li>)
|
||||||
|
) : (
|
||||||
|
<p className="text-neutral-400">No friend requests yet.</p>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Send Friend Request */}
|
||||||
|
<div>
|
||||||
|
<h3 className="text-2xl font-semibold text-[color:var(--color-warning-200)] mb-2">
|
||||||
|
Send Friend Request
|
||||||
|
</h3>
|
||||||
|
<form onSubmit={handleSendFriendRequest} className="space-y-4">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="w-full p-2 rounded bg-neutral-800 text-white"
|
||||||
|
onChange={(e) => setFriendCode(e.target.value)}
|
||||||
|
value={friendCode}
|
||||||
|
placeholder="Enter friend's code..."
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="w-full px-4 py-2 bg-success-600 text-white rounded"
|
||||||
|
>
|
||||||
|
Send Request
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProfilePage() {
|
export default function ProfilePage() {
|
||||||
const { isMobile, isSafari } = useDevice();
|
const { isMobile, isSafari } = useDevice();
|
||||||
if (isMobile && isSafari) return Mobile();
|
if (isMobile && isSafari) return <Mobile />;
|
||||||
else return Mobile();
|
else return <Mobile />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,15 @@ export async function POST(req: Request) {
|
|||||||
userData = await db.users.update(userData.id, { inventory: inventoryData });
|
userData = await db.users.update(userData.id, { inventory: inventoryData });
|
||||||
if (!userData) return NextResponse.json({ message: "Failed to update inventory" }, { status: 500 });
|
if (!userData) return NextResponse.json({ message: "Failed to update inventory" }, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let friends = formData.get("friends");
|
||||||
|
if(friends) {
|
||||||
|
let friendsData = userData.friends;
|
||||||
|
if (!friendsData) friendsData = [];
|
||||||
|
friendsData.push(friends.toString());
|
||||||
|
userData = await db.users.update(userData.id, { friends: friendsData });
|
||||||
|
if (!userData) return NextResponse.json({ message: "Failed to update friends" }, { status: 500 });
|
||||||
|
}
|
||||||
|
|
||||||
return NextResponse.json({ message: "User updated successfully", user: userData }, { status: 200 });
|
return NextResponse.json({ message: "User updated successfully", user: userData }, { status: 200 });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -34,3 +34,38 @@ export async function GET(req: Request, { params }: any) {
|
|||||||
return NextResponse.json({ message: "Internal server error" }, { status: 500 });
|
return NextResponse.json({ message: "Internal server error" }, { status: 500 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for making friend requests
|
||||||
|
export async function POST(req: Request, { params }: any) {
|
||||||
|
try {
|
||||||
|
if (!(await authenticateUser())) return;
|
||||||
|
|
||||||
|
const { id } = params;
|
||||||
|
|
||||||
|
let user = await db.users.findById(id);
|
||||||
|
|
||||||
|
let formData = await req.formData();
|
||||||
|
if (!formData) return NextResponse.json({ message: "No form data found" }, { status: 400 });
|
||||||
|
|
||||||
|
let friendCode = formData.get("friendCode");
|
||||||
|
|
||||||
|
if (!friendCode) return NextResponse.json({ message: "No friend code found" }, { status: 400 });
|
||||||
|
let friendCodeString = friendCode.toString();
|
||||||
|
if (friendCodeString.length !== 5) return NextResponse.json({ message: "Invalid friend code" }, { status: 400 });
|
||||||
|
|
||||||
|
let requests = user.requests || [];
|
||||||
|
|
||||||
|
if (requests.includes(friendCodeString)) {
|
||||||
|
return NextResponse.json({ message: "Already sent a friend request" }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
requests.push(friendCodeString);
|
||||||
|
user = await db.users.update(user.id, { requests });
|
||||||
|
if (!user) return NextResponse.json({ message: "Failed to update requests" }, { status: 500 });
|
||||||
|
return NextResponse.json({ message: "Friend request sent successfully" }, { status: 200 });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error sending friend request:", error);
|
||||||
|
return NextResponse.json({ message: "Internal server error" }, { status: 500 });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -29,3 +29,7 @@ body {
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
@apply dark:bg-[url('/darkmodebackground.png')] bg-[url('/lightmodebackground.png')];
|
@apply dark:bg-[url('/darkmodebackground.png')] bg-[url('/lightmodebackground.png')];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
@apply bg-[#f5f5f5] text-[#333] dark:bg-[#333] dark:text-[#f5f5f5] p-1 rounded-md;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user