diff --git a/src/app/(app)/profile/page.tsx b/src/app/(app)/profile/page.tsx
index 9a79623..98faeea 100644
--- a/src/app/(app)/profile/page.tsx
+++ b/src/app/(app)/profile/page.tsx
@@ -6,28 +6,40 @@ import { useDevice } from "@/lib/context/DeviceContext";
function Mobile() {
const { isAuthenticated, session } = useDevice();
const [bio, setBio] = useState(session?.bio || "");
+ const [username, setUsername] = useState(session?.username || "");
useEffect(() => {
if (session) {
setBio(session.bio || "");
+ setUsername(session.username || "");
}
}, [session]);
function handleSubmit(e: React.FormEvent) {
e.preventDefault();
- if (bio.length > 0) {
+ if (bio.length > 0 || username.length > 0) {
const formData = new FormData();
- formData.append("bio", bio);
+ if (bio.length > 0) formData.append("bio", bio);
+ if (username.length > 0) formData.append("username", username);
fetch("/api/me", {
method: "POST",
body: formData, // Automatically sets Content-Type to multipart/form-data
- });
-
- // Show a success message
- alert("Bio saved!");
+ })
+ .then((res) => res.json())
+ .then((data) => {
+ if (data.message === "User updated successfully") {
+ alert("Profile updated successfully!");
+ } else {
+ alert("Failed to update profile.");
+ }
+ })
+ .catch((err) => {
+ console.error("Error updating profile:", err);
+ alert("An error occurred while updating your profile.");
+ });
} else {
- alert("Please enter a bio.");
+ alert("Please enter a bio or username.");
}
}
@@ -35,7 +47,7 @@ function Mobile() {
- Hi, {session?.username || ""}!!
+ Hi, {username || ""}!!
@@ -46,12 +58,19 @@ function Mobile() {
className="w-42 h-42 rounded-full object-cover bg-surface-700"
/>
)}
- {/* {uploadMessage && (
-
{uploadMessage}
- )} */}
-
diff --git a/src/app/(app)/shop/page.tsx b/src/app/(app)/shop/page.tsx
index 766be17..b779ffd 100644
--- a/src/app/(app)/shop/page.tsx
+++ b/src/app/(app)/shop/page.tsx
@@ -3,120 +3,171 @@
import { useDevice } from "@/lib/context/DeviceContext";
import React, { useState } from "react";
-
-// please change names of pics below
-
+// Default Profile Pictures are /avatar/p1.png to /avatar/p5.png
const defaultPics = [
- "/pfps/default1.png",
- "/pfps/default2.png",
- "/pfps/default3.png",
- "/pfps/default4.png",
+ { src: "/avatar/p1.png", id: 1 },
+ { src: "/avatar/p2.png", id: 2 },
+ { src: "/avatar/p3.png", id: 3 },
+ { src: "/avatar/p4.png", id: 4 },
+ { src: "/avatar/p5.png", id: 5 },
];
+// Purchaseable Profile Pictures are /avatar/p6.png to /avatar/p16.png
const purchasablePics = [
- { src: "/pfps/pic1.png", price: 250 },
- { src: "/pfps/pic2.png", price: 250 },
- { src: "/pfps/pic3.png", price: 2000 },
- { src: "/pfps/pic4.png", price: 2000 },
- { src: "/pfps/pic5.png", price: 2000 },
- { src: "/pfps/pic6.png", price: 2000 },
- { src: "/pfps/pic11.png", price: 2000 },
- { src: "/pfps/pic12.png", price: 2000 },
- { src: "/pfps/pic7.png", price: 10000 },
- { src: "/pfps/pic8.png", price: 10000 },
- { src: "/pfps/pic9.png", price: 10000 },
- { src: "/pfps/pic10.png", price: 10000 },
+ { src: "/avatar/p6.png", price: 250 },
+ { src: "/avatar/p7.png", price: 250 },
+ { src: "/avatar/p8.png", price: 2000 },
+ { src: "/avatar/p9.png", price: 2000 },
+ { src: "/avatar/p10.png", price: 2000 },
+ { src: "/avatar/p11.png", price: 2000 },
+ { src: "/avatar/p12.png", price: 2000 },
+ { src: "/avatar/p13.png", price: 10000 },
+ { src: "/avatar/p14.png", price: 10000 },
+ { src: "/avatar/p15.png", price: 10000 },
+ { src: "/avatar/p16.png", price: 10000 },
];
export default function ShopPage() {
- const { isAuthenticated, session } = useDevice();
- const [totalPoints, setTotalPoints] = useState(0); // placeholder PLEASE PUT SMTH HERE
- const [ownedPics, setOwnedPics] = useState
([...defaultPics]);
- const [currentPic, setCurrentPic] = useState(defaultPics[0]);
+ const { isAuthenticated, session } = useDevice();
+ const [points, setPoints] = useState(session?.points || 0);
+ const [avatar, setAvatar] = useState(session?.avatar || 1);
+ const [ownedPics, setOwnedPics] = useState(session?.ownedPics || []);
- const handlePurchase = (src: string, price: number) => {
- if (ownedPics.includes(src)) return;
- if (totalPoints >= price) {
- setTotalPoints(totalPoints - price);
- setOwnedPics([...ownedPics, src]);
- } else {
- alert("Not enough points!");
- }
- };
+ const handleAvatarSelect = async (id: number) => {
+ const formData = new FormData();
+ formData.append("avatar", id.toString());
- return (
-
- {/* User Header */}
-
-
-

-
-
-
-
- {isAuthenticated ? session.username : "Username"}
-
-
-
-
+ try {
+ const response = await fetch("/api/me", {
+ method: "POST",
+ body: formData,
+ });
-
-
Total Points
-
{totalPoints}
-
+ const data = await response.json();
+ if (response.ok) {
+ alert("Avatar updated successfully!");
+ setAvatar(id);
+ } else {
+ alert(data.message || "Failed to update avatar.");
+ }
+ } catch (error) {
+ console.error("Error updating avatar:", error);
+ alert("An error occurred while updating the avatar.");
+ }
+ };
+ const handlePurchase = async (src: string, price: number) => {
+ if (points < price) {
+ alert("You don't have enough points to purchase this profile picture.");
+ return;
+ }
-
-
-
Default Profile Pics
-
-
- {defaultPics.map((src) => (
-

- ))}
-
-
+ // Update the user's avatar and points on the server
+ const formData = new FormData();
+ formData.append("avatar", src);
+ formData.append("points", (points - price).toString());
- {/* Shop Grid */}
-
-
-
Purchase New Profile Pics!
-
-
- {purchasablePics.map((pic) => (
-
-

-
{pic.price} pts
-
+ try {
+ const response = await fetch("/api/me", {
+ method: "POST",
+ body: formData,
+ });
+
+ const data = await response.json();
+ if (response.ok) {
+ alert("Profile picture purchased successfully!");
+ setPoints(points - price);
+ setAvatar(src);
+ setOwnedPics([...ownedPics, src]);
+ } else {
+ alert(data.message || "Failed to purchase profile picture.");
+ }
+ } catch (error) {
+ console.error("Error purchasing profile picture:", error);
+ alert("An error occurred while purchasing the profile picture.");
+ }
+ };
+
+ return (
+
+ {/* User Header */}
+
+
+
+

+
+
+ {isAuthenticated ? session.username : "Username"}
+
+
+
+
+ {/* Total Points */}
+
+
+ Total Points
+
+
{points}
+
+
+ {/* Default Profile Pictures */}
+
+
+
+ Default Profile Pics
+
+
+
+ {defaultPics.map((pfp) => (
+
handleAvatarSelect(pfp.id)}
+ >
+

+
+ ))}
+
+
+
+ {/* Purchaseable Profile Pictures */}
+
+
+
+ Purchase New Profile Pics!
+
+
+
+ {purchasablePics.map((pic) => (
+
+

+
{pic.price} pts
+
+
+ ))}
+
- ))}
-
-
-
-
-
-
-
-
-
- );
+ );
}
diff --git a/src/app/api/me/route.ts b/src/app/api/me/route.ts
index 42a55d9..3f27e2d 100644
--- a/src/app/api/me/route.ts
+++ b/src/app/api/me/route.ts
@@ -12,16 +12,43 @@ export async function POST(req: Request) {
if (!userData) return NextResponse.json({ message: "User not found" }, { status: 404 });
const formData = await req.formData();
-
+ if (!formData) return NextResponse.json({ message: "No form data found" }, { status: 400 });
let bio = formData.get("bio");
if(bio) {
- userData = await db.users.update(userData.id, { bio: bio.toString() });
+ userData = await db.users.update(userData.id, { bio: bio });
if (!userData) return NextResponse.json({ message: "Failed to update bio" }, { status: 500 });
- return NextResponse.json({ message: "Bio updated successfully" }, { status: 200 });
}
+
+ let avatar = formData.get("avatar");
+ if(avatar) {
+ userData = await db.users.update(userData.id, { avatar: parseInt(avatar.toString()) });
+ if (!userData) return NextResponse.json({ message: "Failed to update avatar" }, { status: 500 });
+ }
+
+ let username = formData.get("username");
+ if(username) {
+ userData = await db.users.update(userData.id, { username: username });
+ if (!userData) return NextResponse.json({ message: "Failed to update username" }, { status: 500 });
+ }
+
+ let points = formData.get("points");
+ if(points) {
+ userData = await db.users.update(userData.id, { points: parseInt(points.toString()) });
+ if (!userData) return NextResponse.json({ message: "Failed to update points" }, { status: 500 });
+ }
+
+ let inventory = formData.get("inventory");
+ if(inventory) {
+ let inventoryData = userData.inventory;
+ if (!inventoryData) inventoryData = [];
+ inventoryData.push(inventory.toString());
+
+ userData = await db.users.update(userData.id, { inventory: inventoryData });
+ if (!userData) return NextResponse.json({ message: "Failed to update inventory" }, { status: 500 });
+ }
- return NextResponse.json({ message: "No Update" }, { status: 400 });
+ return NextResponse.json({ message: "User updated successfully", user: userData }, { status: 200 });
} catch (error) {
console.error("Error updating user bio:", error);
return NextResponse.json(
diff --git a/src/lib/components/MobileNav.jsx b/src/lib/components/MobileNav.jsx
index 7dbdec3..9b778b3 100644
--- a/src/lib/components/MobileNav.jsx
+++ b/src/lib/components/MobileNav.jsx
@@ -6,7 +6,8 @@ import {
Home as IconHome,
BookText as BookImage,
User as UserImage,
- Plus as PlusImage
+ Plus as PlusImage,
+ ShoppingCart as ShoppingCartImage,
} from "lucide-react";
import { useDevice } from "@/lib/context/DeviceContext";
@@ -28,6 +29,11 @@ const MobileNav = () => {
) : null}
+ {isAuthenticated ? (
+
+
+
+ ) : null}
{isAuthenticated ? (
diff --git a/src/lib/scripts/User.ts b/src/lib/scripts/User.ts
index de64cc0..9b3edd8 100644
--- a/src/lib/scripts/User.ts
+++ b/src/lib/scripts/User.ts
@@ -72,7 +72,8 @@ export class User {
}
async update(Id: string, data: any) {
- return await this.model.updateOne({ id: Id }, { $set: data }, this.upsert);
+ await this.model.updateOne({ id: Id }, { $set: data }, this.upsert);
+ return await this.model.findOne({ id: Id });
}
async delete(Id: string) {