Skip to content

Commit 8e61e14

Browse files
committed
remove account reactivation
1 parent 98178dc commit 8e61e14

2 files changed

Lines changed: 164 additions & 139 deletions

File tree

‎apps/codebility/app/home/(dashboard)/_components/DashboardProfile.tsx‎

Lines changed: 162 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { useEffect, useState } from "react";
44
import Image from "next/image";
5+
import UserInactiveModal from "@/components/modals/UserInactiveModal";
56
import Badges from "@/components/shared/Badges";
67
import Box from "@/components/shared/dashboard/Box";
78
import { Skeleton } from "@/components/ui/skeleton/skeleton";
@@ -14,145 +15,169 @@ import { cn } from "@codevs/ui";
1415
import { Badge } from "@codevs/ui/badge";
1516

1617
import {
17-
fetchUserAvailabilityStatus,
18-
updateUserAvailabilityStatus,
18+
fetchUserAvailabilityStatus,
19+
updateUserAvailabilityStatus,
1920
} from "../actions";
2021
import DashboardCertificate from "./DashboardCertificate";
2122

2223
export default function DashboardProfile() {
23-
const { user } = useUserStore();
24-
const isLoading = !user;
25-
26-
const [active, setActive] = useState<boolean | null>(null);
27-
const [activeloading, setActiveLoading] = useState<boolean>(false);
28-
29-
useEffect(() => {
30-
if (!user) return;
31-
32-
const fetchStatus = async () => {
33-
try {
34-
const res = await fetchUserAvailabilityStatus(user?.id);
35-
setActive(res);
36-
} catch (error) {
37-
console.error(error);
38-
}
39-
};
40-
41-
fetchStatus();
42-
}, [user]);
43-
44-
const triggerRefresh = useSidebarStore((state) => state.triggerRefresh);
45-
46-
const handleStatusSwitch = async () => {
47-
if (!user) return;
48-
49-
setActiveLoading(true);
50-
51-
try {
52-
await updateUserAvailabilityStatus({
53-
userId: user?.id,
54-
status: !active,
55-
});
56-
57-
setActive((prev) => !prev);
58-
await useUserStore.getState().hydrate();
59-
} catch (error) {
60-
console.error(error);
61-
} finally {
62-
setActiveLoading(false);
63-
triggerRefresh();
64-
}
65-
};
66-
67-
return (
68-
<>
69-
{!isLoading ? (
70-
<Box className="relative flex-1 overflow-hidden">
71-
{/* Background decoration */}
72-
<div className="absolute inset-0 bg-gradient-to-br from-customBlue-50/30 to-purple-50/30 dark:from-customBlue-950/10 dark:to-purple-950/10" />
73-
<div className="absolute -top-4 -left-4 h-32 w-32 rounded-full bg-gradient-to-br from-yellow-400/10 to-orange-400/10 blur-2xl" />
74-
75-
{user && <DashboardCertificate />}
76-
<div className="relative mx-auto flex flex-col items-center gap-4">
77-
<div className="text-center">
78-
<h2 className="mt-2 sm:mt-4 text-2xl sm:text-3xl font-bold bg-gradient-to-r from-purple-600 to-customBlue-600 bg-clip-text text-transparent md:mt-0">
79-
Hello, {user?.first_name ?? ""}!
80-
</h2>
81-
<p className="text-xs sm:text-sm text-gray-500 dark:text-gray-400">Ready to level up today?</p>
82-
</div>
83-
84-
<div className="relative">
85-
{/* Profile picture with enhanced styling */}
86-
<div className="relative group">
87-
<div className="absolute inset-0 bg-gradient-to-br from-customBlue-500 to-purple-500 rounded-2xl blur-sm opacity-75 group-hover:opacity-100 transition-opacity"></div>
88-
<div className="relative bg-white dark:bg-gray-800 p-1 rounded-2xl">
89-
<Image
90-
alt={`Profile picture of ${user?.first_name} ${user?.last_name || ''}, ${user?.display_position || 'team member'}`}
91-
src={user?.image_url ? `${user.image_url}` : defaultAvatar}
92-
width={100}
93-
height={100}
94-
title={`${user?.first_name}'s Profile Picture`}
95-
className="h-[100px] w-[100px] rounded-xl object-cover transition-transform duration-300 group-hover:scale-105"
96-
/>
97-
</div>
98-
{/* Online status indicator */}
99-
<div className="absolute -bottom-1 -right-1 h-6 w-6 bg-white dark:bg-gray-800 rounded-full flex items-center justify-center">
100-
<div className="h-4 w-4 bg-green-500 rounded-full animate-pulse"></div>
101-
</div>
102-
</div>
103-
</div>
104-
105-
<div className="text-center">
106-
<p className="text-lg font-semibold text-gray-800 dark:text-gray-200">{user?.display_position}</p>
107-
<div className="mt-2">
108-
<Badges />
109-
</div>
110-
</div>
111-
</div>
112-
113-
{/* Enhanced status switch */}
114-
<div className="absolute right-2 top-2 sm:right-4 sm:top-4">
115-
{active !== null && (
116-
<div className="flex flex-col items-end gap-1 sm:gap-2">
117-
<Badge className={cn(
118-
"text-xs sm:text-sm font-medium transition-all duration-300 px-2 py-1",
119-
active
120-
? "bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400 border border-green-200 dark:border-green-800"
121-
: "bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400 border border-red-200 dark:border-red-800"
122-
)}>
123-
<div className="flex items-center gap-1">
124-
<div className={cn(
125-
"h-1.5 w-1.5 rounded-full",
126-
active ? "bg-green-600 dark:bg-green-400 animate-pulse" : "bg-red-600 dark:bg-red-400"
127-
)} />
128-
<span className="hidden sm:inline">{active ? "Active" : "Inactive"}</span>
129-
<span className="sm:hidden">{active ? "On" : "Off"}</span>
130-
</div>
131-
</Badge>
132-
133-
<SwitchStatusButton
134-
isActive={active}
135-
disabled={activeloading}
136-
handleSwitch={handleStatusSwitch}
137-
/>
138-
139-
<p className="hidden sm:block text-[10px] sm:text-xs text-gray-500 dark:text-gray-400 text-center max-w-[80px] leading-tight">
140-
{active ? "Available for work" : "Away"}
141-
</p>
142-
</div>
143-
)}
144-
</div>
145-
</Box>
146-
) : (
147-
<Box className="flex-1">
148-
<div className="mx-auto flex flex-col items-center gap-3">
149-
<Skeleton className="h-8 w-full" />
150-
<Skeleton className="h-32 w-full" />
151-
<Skeleton className="h-8 w-full" />
152-
<Skeleton className="h-24 w-full" />
153-
</div>
154-
</Box>
155-
)}
156-
</>
157-
);
24+
const { user } = useUserStore();
25+
const isLoading = !user;
26+
27+
const [active, setActive] = useState<boolean | null>(null);
28+
const [activeloading, setActiveLoading] = useState<boolean>(false);
29+
const [isModalOpen, setIsModalOpen] = useState(false);
30+
31+
useEffect(() => {
32+
if (!user) return;
33+
34+
const fetchStatus = async () => {
35+
try {
36+
const res = await fetchUserAvailabilityStatus(user?.id);
37+
setActive(res);
38+
} catch (error) {
39+
console.error(error);
40+
}
41+
};
42+
43+
fetchStatus();
44+
}, [user]);
45+
46+
const triggerRefresh = useSidebarStore((state) => state.triggerRefresh);
47+
48+
const handleStatusSwitch = async () => {
49+
if (!user) return;
50+
51+
setActiveLoading(true);
52+
53+
// if inactive, it cannot be set to active from here
54+
if (active === false) {
55+
setActiveLoading(false);
56+
setIsModalOpen(true);
57+
return;
58+
}
59+
60+
try {
61+
await updateUserAvailabilityStatus({
62+
userId: user?.id,
63+
status: !active,
64+
});
65+
66+
setActive((prev) => !prev);
67+
await useUserStore.getState().hydrate();
68+
} catch (error) {
69+
console.error(error);
70+
} finally {
71+
setActiveLoading(false);
72+
triggerRefresh();
73+
}
74+
};
75+
76+
return (
77+
<>
78+
<UserInactiveModal
79+
isOpen={isModalOpen}
80+
onClose={() => setIsModalOpen(false)}
81+
/>
82+
{!isLoading ? (
83+
<Box className="relative flex-1 overflow-hidden">
84+
{/* Background decoration */}
85+
<div className="from-customBlue-50/30 dark:from-customBlue-950/10 absolute inset-0 bg-gradient-to-br to-purple-50/30 dark:to-purple-950/10" />
86+
<div className="absolute -left-4 -top-4 h-32 w-32 rounded-full bg-gradient-to-br from-yellow-400/10 to-orange-400/10 blur-2xl" />
87+
88+
{user && <DashboardCertificate />}
89+
<div className="relative mx-auto flex flex-col items-center gap-4">
90+
<div className="text-center">
91+
<h2 className="to-customBlue-600 mt-2 bg-gradient-to-r from-purple-600 bg-clip-text text-2xl font-bold text-transparent sm:mt-4 sm:text-3xl md:mt-0">
92+
Hello, {user?.first_name ?? ""}!
93+
</h2>
94+
<p className="text-xs text-gray-500 dark:text-gray-400 sm:text-sm">
95+
Ready to level up today?
96+
</p>
97+
</div>
98+
99+
<div className="relative">
100+
{/* Profile picture with enhanced styling */}
101+
<div className="group relative">
102+
<div className="from-customBlue-500 absolute inset-0 rounded-2xl bg-gradient-to-br to-purple-500 opacity-75 blur-sm transition-opacity group-hover:opacity-100"></div>
103+
<div className="relative rounded-2xl bg-white p-1 dark:bg-gray-800">
104+
<Image
105+
alt={`Profile picture of ${user?.first_name} ${user?.last_name || ""}, ${user?.display_position || "team member"}`}
106+
src={user?.image_url ? `${user.image_url}` : defaultAvatar}
107+
width={100}
108+
height={100}
109+
title={`${user?.first_name}'s Profile Picture`}
110+
className="h-[100px] w-[100px] rounded-xl object-cover transition-transform duration-300 group-hover:scale-105"
111+
/>
112+
</div>
113+
{/* Online status indicator */}
114+
<div className="absolute -bottom-1 -right-1 flex h-6 w-6 items-center justify-center rounded-full bg-white dark:bg-gray-800">
115+
<div className="h-4 w-4 animate-pulse rounded-full bg-green-500"></div>
116+
</div>
117+
</div>
118+
</div>
119+
120+
<div className="text-center">
121+
<p className="text-lg font-semibold text-gray-800 dark:text-gray-200">
122+
{user?.display_position}
123+
</p>
124+
<div className="mt-2">
125+
<Badges />
126+
</div>
127+
</div>
128+
</div>
129+
130+
{/* Enhanced status switch */}
131+
<div className="absolute right-2 top-2 sm:right-4 sm:top-4">
132+
{active !== null && (
133+
<div className="flex flex-col items-end gap-1 sm:gap-2">
134+
<Badge
135+
className={cn(
136+
"px-2 py-1 text-xs font-medium transition-all duration-300 sm:text-sm",
137+
active
138+
? "border border-green-200 bg-green-100 text-green-800 dark:border-green-800 dark:bg-green-900/30 dark:text-green-400"
139+
: "border border-red-200 bg-red-100 text-red-800 dark:border-red-800 dark:bg-red-900/30 dark:text-red-400",
140+
)}
141+
>
142+
<div className="flex items-center gap-1">
143+
<div
144+
className={cn(
145+
"h-1.5 w-1.5 rounded-full",
146+
active
147+
? "animate-pulse bg-green-600 dark:bg-green-400"
148+
: "bg-red-600 dark:bg-red-400",
149+
)}
150+
/>
151+
<span className="hidden sm:inline">
152+
{active ? "Active" : "Inactive"}
153+
</span>
154+
<span className="sm:hidden">{active ? "On" : "Off"}</span>
155+
</div>
156+
</Badge>
157+
158+
<SwitchStatusButton
159+
isActive={active}
160+
disabled={activeloading}
161+
handleSwitch={handleStatusSwitch}
162+
/>
163+
164+
<p className="hidden max-w-[80px] text-center text-[10px] leading-tight text-gray-500 dark:text-gray-400 sm:block sm:text-xs">
165+
{active ? "Available for work" : "Away"}
166+
</p>
167+
</div>
168+
)}
169+
</div>
170+
</Box>
171+
) : (
172+
<Box className="flex-1">
173+
<div className="mx-auto flex flex-col items-center gap-3">
174+
<Skeleton className="h-8 w-full" />
175+
<Skeleton className="h-32 w-full" />
176+
<Skeleton className="h-8 w-full" />
177+
<Skeleton className="h-24 w-full" />
178+
</div>
179+
</Box>
180+
)}
181+
</>
182+
);
158183
}

‎apps/codebility/components/modals/UserInactiveModal.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ const UserInactiveModal: React.FC<UserInactiveModalProps> = ({
3030
</DialogTitle>
3131
</DialogHeader>
3232
<p className="text-gray text-center text-sm">
33-
Your account is currently inactive. You can change your status using
34-
the toggle switch above.
33+
Your account is currently inactive. Please Contanct Admins to reactivate
34+
your account.
3535
</p>
3636
</DialogContent>
3737
</Dialog>

0 commit comments

Comments
 (0)