Skip to content

Commit ab87c71

Browse files
committed
invite user and create account front end implementation
1 parent 037e53d commit ab87c71

File tree

8 files changed

+1380
-4
lines changed

8 files changed

+1380
-4
lines changed

public/assets/blue_arrow.svg

+3
Loading

src/app/account_management/page.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22

33
import AccountManagementScreen from "@/screens/AccountManagementScreen";
44

5-
export default AccountManagementScreen;
5+
export default function AccountManagementPage() {
6+
return <AccountManagementScreen />;
7+
}
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"use client";
2+
3+
import NavBarLayout from "@/components/NavBarLayout";
4+
import { usePathname } from "next/navigation";
5+
6+
export default function RootLayout({
7+
children,
8+
}: {
9+
children: React.ReactNode;
10+
}) {
11+
const pathname = usePathname();
12+
const hideNav = pathname.startsWith("/create-partner-account");
13+
14+
return (
15+
<html lang="en">
16+
<body>
17+
{hideNav ? (
18+
//if the path starts with /create-partner-account, render children ONLY
19+
children
20+
) : (
21+
//else wrap everything in NavBarLayout
22+
<NavBarLayout>{children}</NavBarLayout>
23+
)}
24+
</body>
25+
</html>
26+
);
27+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use client";
2+
3+
import CreatePartnerAccountScreen from "@/screens/CreatePartnerAccountScreen";
4+
5+
export default function CreatePartnerAccountPage() {
6+
return <CreatePartnerAccountScreen />;
7+
}

src/components/InviteUserForm.tsx

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"use client";
2+
3+
import { useState } from "react";
4+
import { UserType } from "@prisma/client";
5+
6+
interface InviteUserFormProps {
7+
closeModal: () => void;
8+
onSubmit: (role: UserType) => void;
9+
}
10+
11+
export default function InviteUserForm({ closeModal, onSubmit }: InviteUserFormProps) {
12+
const [name, setName] = useState("");
13+
const [email, setEmail] = useState("");
14+
const [role, setRole] = useState<UserType | "">("");
15+
const [step, setStep] = useState(1);
16+
17+
const handleSubmit = (event: React.FormEvent) => {
18+
event.preventDefault();
19+
20+
if (!role) {
21+
console.error("Role is not selected");
22+
return;
23+
}
24+
25+
if (role === "SUPER_ADMIN" || role === "ADMIN" || role === "STAFF") {
26+
onSubmit(role as UserType);
27+
setStep(2);
28+
} else {
29+
onSubmit(role as UserType);
30+
}
31+
};
32+
33+
return (
34+
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
35+
<div className="bg-white p-6 rounded-lg shadow-lg w-96">
36+
{step === 1 ? (
37+
<>
38+
<h2 className="text-xl font-bold mb-4">Add new account</h2>
39+
<button className="absolute top-4 right-4" onClick={closeModal}></button>
40+
<form onSubmit={handleSubmit}>
41+
<label className="block mb-2">Name</label>
42+
<input
43+
type="text"
44+
className="w-full p-2 border rounded mb-2"
45+
value={name}
46+
onChange={(e) => setName(e.target.value)}
47+
required
48+
/>
49+
50+
<label className="block mb-2">Email</label>
51+
<input
52+
type="email"
53+
className="w-full p-2 border rounded mb-2"
54+
value={email}
55+
onChange={(e) => setEmail(e.target.value)}
56+
required
57+
/>
58+
59+
<label className="block mb-2">Role</label>
60+
<select
61+
className="w-full p-2 border rounded mb-4"
62+
value={role}
63+
onChange={(e) => setRole(e.target.value as UserType)}
64+
required
65+
>
66+
<option value="" disabled>Select a role</option>
67+
{Object.values(UserType).map((roleOption) => (
68+
<option key={roleOption} value={roleOption}>{roleOption}</option>
69+
))}
70+
</select>
71+
72+
<div className="flex justify-between">
73+
<button
74+
type="button"
75+
className="border border-mainRed text-mainRed px-4 py-2 rounded"
76+
onClick={closeModal}
77+
>
78+
Cancel
79+
</button>
80+
<button
81+
type="submit"
82+
className="bg-mainRed text-white px-4 py-2 rounded"
83+
>
84+
{role === "PARTNER" ? "Next" : "Send invite link"}
85+
</button>
86+
</div>
87+
</form>
88+
</>
89+
) : (
90+
<>
91+
<h2 className="text-xl font-bold mb-4">Add new account</h2>
92+
<button className="absolute top-4 right-4" onClick={closeModal}></button>
93+
<p className="mb-4">An email has been sent to finalize account creation. This account is currently pending.</p>
94+
<p className="mb-4">You can view the current status from the account management page.</p>
95+
<div className="flex justify-center mb-4">
96+
<img src="/assets/blue_arrow.svg" alt="Blue Arrow" className="w-12 h-12" />
97+
</div>
98+
<button
99+
className="bg-mainRed text-white px-4 py-2 rounded w-full"
100+
onClick={closeModal}
101+
>
102+
Back to account management
103+
</button>
104+
</>
105+
)}
106+
</div>
107+
</div>
108+
);
109+
}
+48-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,52 @@
1+
"use client";
2+
3+
import { useState } from "react";
4+
import { useRouter } from "next/navigation";
5+
import InviteUserForm from "@/components/InviteUserForm";
6+
import { UserType } from "@prisma/client";
7+
18
export default function AccountManagementScreen() {
9+
const router = useRouter();
10+
const [isInviteModalOpen, setInviteModalOpen] = useState(false);
11+
12+
const handleInviteSubmit = (role: UserType) => {
13+
if (role === "PARTNER") {
14+
setInviteModalOpen(false);
15+
router.push("/create-partner-account");
16+
} else {
17+
console.log("Sending invite link for", role);
18+
}
19+
};
20+
221
return (
3-
<>
4-
<h1 className="text-2xl font-semibold">Account Management</h1>
5-
</>
22+
<div className="p-6">
23+
<div className="flex justify-between items-center mb-4">
24+
<h1 className="text-2xl font-semibold">Account Management</h1>
25+
<button
26+
className="bg-mainRed text-white px-4 py-2 rounded"
27+
onClick={() => setInviteModalOpen(true)}
28+
>
29+
+ Add Account
30+
</button>
31+
</div>
32+
33+
<input
34+
type="text"
35+
placeholder="Search"
36+
className="w-full p-2 border rounded mb-4"
37+
/>
38+
<div className="flex space-x-4 border-b mb-4">
39+
<button className="pb-2 font-semibold border-b-2 border-black">All</button>
40+
<button className="pb-2 font-semibold text-gray-500">Hope for Haiti Staff</button>
41+
<button className="pb-2 font-semibold text-gray-500">Partners</button>
42+
</div>
43+
44+
{isInviteModalOpen && (
45+
<InviteUserForm
46+
closeModal={() => setInviteModalOpen(false)}
47+
onSubmit={handleInviteSubmit}
48+
/>
49+
)}
50+
</div>
651
);
752
}

0 commit comments

Comments
 (0)