Skip to content

Commit 4b32a61

Browse files
committed
User Friends page implementation selecting and managing individual friends
1 parent 0071f80 commit 4b32a61

3 files changed

Lines changed: 229 additions & 0 deletions

File tree

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// src/components/popups/user_groups_select_popup.tsx
2+
3+
import Link from "next/link";
4+
import React from "react";
5+
6+
type MyFriends = {
7+
id: number;
8+
name: string;
9+
};
10+
11+
type ItemModalProps = {
12+
isOpen: boolean;
13+
item: MyFriends | null;
14+
onClose: () => void;
15+
};
16+
17+
function UserFriendsSelectPopup({ isOpen, item, onClose }: ItemModalProps) {
18+
if (!isOpen || !item) return null;
19+
return (
20+
<div
21+
className="fixed inset-0 z-50 flex items-center justify-center bg-black/40"
22+
onClick={onClose}
23+
>
24+
<div className="w-full max-w-md rounded-xl bg-white p-6 shadow-lg">
25+
{/* Header */}
26+
<div className="mb-3 flex items-center justify-between">
27+
<div className="relative flex h-24 w-24 items-center justify-center overflow-hidden rounded-full bg-blue-500">
28+
<div className="absolute top-5 h-12 w-12 rounded-full bg-blue-200"></div>
29+
<div className="absolute -bottom-2 left-1/2 h-12 w-16 -translate-x-1/2 rounded-full bg-blue-200"></div>
30+
</div>
31+
{/* <div className="flex justify-between items-center border-b pb-3"> */}
32+
{/* Body */}
33+
<div className="space-y-2 py-4">
34+
<Link href="/user_friends">
35+
<h2 className="cursor-pointer text-2xl font-bold hover:text-gray-900 hover:underline">
36+
{item.name}
37+
</h2>
38+
</Link>
39+
<div className="mb-3 flex items-center justify-between">
40+
<p className="text-gray-500">User: {item.id} </p> &nbsp; &nbsp;{" "}
41+
{/* Unique Profile Identifier */}
42+
<p className="cursor-pointer text-gray-500 hover:text-gray-900 hover:underline">
43+
Mutual Groups: {item.id}
44+
</p>{" "}
45+
{/* Add link/popup here? */}
46+
</div>
47+
</div>
48+
<div></div>
49+
<button
50+
onClick={onClose}
51+
className="-translate-y-10 text-gray-500 hover:text-gray-800"
52+
>
53+
54+
</button>
55+
{/* </div> */}
56+
</div>
57+
58+
{/* Footer */}
59+
<div className="flex justify-end gap-3 border-t pt-4">
60+
<Link href="/user_friends">
61+
<button className="rounded bg-blue-200 px-4 py-2 hover:bg-blue-300">
62+
<div className="flex items-center justify-between">
63+
<svg
64+
viewBox="0 0 24 24"
65+
fill="currentColor"
66+
className="h-6 w-6 rounded-full text-blue-500"
67+
>
68+
<path d="M2 3h20v14H6l-4 4V3z" />
69+
</svg>{" "}
70+
&nbsp; Message
71+
</div>
72+
</button>
73+
</Link>
74+
<button
75+
onClick={onClose}
76+
className="rounded bg-red-600 px-4 py-2 text-white hover:bg-red-700"
77+
>
78+
<div className="flex items-center justify-between">
79+
<svg
80+
xmlns="http://www.w3.org/2000/svg"
81+
width="24"
82+
height="24"
83+
viewBox="0 0 24 24"
84+
fill="none"
85+
stroke="currentColor"
86+
stroke-width="2"
87+
stroke-linecap="round"
88+
stroke-linejoin="round"
89+
className="lucide lucide-log-out-icon lucide-log-out"
90+
>
91+
<path d="m16 17 5-5-5-5" />
92+
<path d="M21 12H9" />
93+
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
94+
</svg>
95+
&nbsp; Remove {/* Backend remove action */}
96+
</div>
97+
</button>
98+
<button
99+
onClick={onClose}
100+
className="rounded bg-gray-200 px-4 py-2 hover:bg-gray-300"
101+
>
102+
X Close
103+
</button>
104+
</div>
105+
</div>
106+
</div>
107+
);
108+
}
109+
export default UserFriendsSelectPopup;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// src/pages/user_dashboard.tsx (Update the import path)
2+
//import "";
3+
import { useEffect,useState } from "react";
4+
5+
import FriendItemModal from "../popups/user_friends_select_popup";
6+
7+
export type MyFriends = {
8+
id: number;
9+
name: string;
10+
};
11+
12+
const UserFriendsTable = () => {
13+
const [selectedItem, setSelectedItem] = useState<MyFriends | null>(null);
14+
const [isModalOpen, setIsModalOpen] = useState(false);
15+
16+
// Mock data (replace with Django API call later)
17+
const [friends, SetFriends] = useState<MyFriends[]>([]);
18+
// Mock data (replace with Django API call later)
19+
useEffect(() => {
20+
const mockFriend: MyFriends[] = Array.from({ length: 30 }, (_, i) => ({
21+
id: i + 1,
22+
name: `Friend ${i + 1}`,
23+
}));
24+
SetFriends(mockFriend);
25+
}, []);
26+
27+
return (
28+
<>
29+
{/* Scrollable container */}
30+
<div className="flex-1 cursor-pointer overflow-y-auto rounded-md border">
31+
{/* logic for clicking to open pop-up window to edit/resolve an item*/}
32+
33+
{friends.length === 0 ? (
34+
<p className="py-6 text-center text-gray-500">No friends found.</p>
35+
) : (
36+
friends.map((item) => (
37+
<div
38+
key={item.id}
39+
onClick={() => {
40+
setSelectedItem(item);
41+
setIsModalOpen(true);
42+
}}
43+
className="flex items-center justify-between border-b px-3 py-3 last:border-b-0 hover:bg-gray-50"
44+
>
45+
<span className="font-medium text-gray-800">{item.name}</span>
46+
</div>
47+
))
48+
)}
49+
</div>
50+
<FriendItemModal
51+
isOpen={isModalOpen}
52+
item={selectedItem}
53+
onClose={() => setIsModalOpen(false)}
54+
/>
55+
</>
56+
);
57+
};
58+
export default UserFriendsTable;

client/src/pages/user_friends.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// src/pages/user_dashboard.tsx (Update the import path)
2+
//import "";
3+
4+
import Head from "next/head";
5+
import { useState } from "react";
6+
7+
// import {useState, useEffect} from "react";
8+
import UserFriendsAddPopup from "../components/ui/popups/user_friends_add_popup";
9+
import UserNavbar from "../components/ui/user_navbar";
10+
import UserFriendsTable from "../components/ui/user_tables/user_friends_table";
11+
12+
const UserFriendsPage = () => {
13+
const [isModalOpen, setIsModalOpen] = useState(false);
14+
return (
15+
<>
16+
<Head>
17+
<title>My Friends</title>
18+
</Head>
19+
{/* Navbar */}
20+
<UserNavbar />
21+
{/* Page background */}
22+
<div className="min-h-screen bg-gray-100 p-6">
23+
{/* 2. Main content wrapper */}
24+
<main className="mx-auto h-[80vh] max-w-6xl">
25+
{/* Components for Statistics, Recent Activity, and Quick Actions */}
26+
<h1 className="mb-6 text-3xl font-bold">My Friends</h1>
27+
28+
{/* Inventory Grid */}
29+
<div className="grid h-full grid-flow-col grid-rows-1 gap-4">
30+
<div className="row-span-4 flex flex-col rounded-xl bg-white p-4 shadow">
31+
<div className="mb-3 flex items-center justify-between">
32+
<h2 className="mb-2 text-xl font-semibold">My Friends</h2>
33+
34+
<button
35+
className="cursor-pointer text-sm font-semibold text-blue-600 hover:underline"
36+
onClick={() => {
37+
setIsModalOpen(true);
38+
}}
39+
>
40+
+ Friends{" "}
41+
</button>
42+
</div>
43+
{/* <Link href="/user_inventory">
44+
<button className="text-sm font-semibold cursor-pointer text-blue-600 hover:underline">
45+
View My Inventory
46+
</button>
47+
</Link> */}
48+
<UserFriendsTable />
49+
</div>
50+
</div>
51+
</main>
52+
<UserFriendsAddPopup
53+
isOpen={isModalOpen}
54+
onClose={() => setIsModalOpen(false)}
55+
/>
56+
</div>
57+
</>
58+
);
59+
};
60+
61+
// export to make the function available to other parts of the app
62+
export default UserFriendsPage;

0 commit comments

Comments
 (0)