Skip to content

Commit 7321a02

Browse files
Move trial management into admin modal and menus
1 parent aded720 commit 7321a02

8 files changed

Lines changed: 114 additions & 308 deletions

File tree

src/frontend/src/components/core/appHeaderComponent/components/AccountMenu/index.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ export const AccountMenu = () => {
6060
<HeaderMenuItems position="right" classNameSize="w-[272px]">
6161
<div className="divide-y divide-foreground/10">
6262
<div>
63+
{isAdmin && !autoLogin && (
64+
<div className="flex items-center justify-between rounded-md border border-border/40 bg-muted px-4 py-2 text-xs font-medium text-foreground">
65+
<span>You are an Admin</span>
66+
<span className="rounded-full bg-primary/10 px-2 py-0.5 text-[10px] uppercase tracking-wide text-primary">
67+
Admin
68+
</span>
69+
</div>
70+
)}
6371
<div className="h-[44px] items-center px-4 pt-3">
6472
<div className="flex items-center justify-between">
6573
<span
@@ -111,18 +119,6 @@ export const AccountMenu = () => {
111119
Admin Page
112120
</span>
113121
</HeaderMenuItemButton>
114-
<HeaderMenuItemButton
115-
onClick={() => {
116-
navigate("/admin/trial-access");
117-
}}
118-
>
119-
<span
120-
data-testid="menu_trial_access_button"
121-
id="menu_trial_access_button"
122-
>
123-
Trial Access
124-
</span>
125-
</HeaderMenuItemButton>
126122
</div>
127123
)}
128124
<HeaderMenuItemLink

src/frontend/src/constants/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,10 @@ export const CONTROL_NEW_USER = {
628628
password: "",
629629
is_active: false,
630630
is_superuser: false,
631+
optins: {
632+
trial_access_until: "",
633+
skip_trial_access: false,
634+
},
631635
};
632636

633637
export const tabsCode = [];

src/frontend/src/customization/components/ClerkAccountMenu.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { IS_CLERK_AUTH, useLogout } from "@/clerk/auth";
33
import { LogOut, Users, Settings, User } from "lucide-react";
44
import { AccountMenu } from "@/components/core/appHeaderComponent/components/AccountMenu";
55
import { cn } from "@/utils/utils";
6+
import useAuthStore from "@/stores/authStore";
67
import {
78
DropdownMenu,
89
DropdownMenuTrigger,
@@ -17,6 +18,7 @@ export function ClerkAccountMenu() {
1718
const { openUserProfile, openOrganizationProfile } = useClerk();
1819
const { user } = useUser();
1920
const [menuOpen, setMenuOpen] = useState(false);
21+
const isAdmin = useAuthStore((state) => state.isAdmin);
2022

2123
const handleLogout = () => {
2224
mutationLogout();
@@ -72,6 +74,14 @@ export function ClerkAccountMenu() {
7274

7375
{/* Menu Items */}
7476
<div className="pt-2 text-sm">
77+
{isAdmin ? (
78+
<div className="mx-4 mb-2 flex items-center justify-between rounded-md border border-border/40 bg-muted px-3 py-2 text-xs font-medium text-foreground">
79+
<span>You are an Admin</span>
80+
<span className="rounded-full bg-primary/10 px-2 py-0.5 text-[10px] uppercase tracking-wide text-primary">
81+
Admin
82+
</span>
83+
</div>
84+
) : null}
7585
{/* Manage Account */}
7686
<DropdownMenuItem
7787
onClick={handleOpenUserProfile}
@@ -90,6 +100,19 @@ export function ClerkAccountMenu() {
90100
Members
91101
</DropdownMenuItem>
92102

103+
{/* Admin */}
104+
<DropdownMenuItem
105+
asChild
106+
className="flex items-center gap-3 px-5 py-3 rounded-lg hover:bg-muted/30 transition"
107+
>
108+
<a href="/admin" className="flex items-center gap-3">
109+
<span className="inline-flex h-4 w-4 items-center justify-center rounded-full bg-primary/10 text-[10px] font-semibold uppercase text-primary">
110+
A
111+
</span>
112+
Admin
113+
</a>
114+
</DropdownMenuItem>
115+
93116
{/* Settings */}
94117
<DropdownMenuItem asChild>
95118
<a
@@ -122,4 +145,4 @@ export function ClerkAccountMenu() {
122145
);
123146
}
124147

125-
export default ClerkAccountMenu;
148+
export default ClerkAccountMenu;

src/frontend/src/modals/userManagementModal/index.tsx

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ export default function UserManagementModal({
3333
const [confirmPassword, setConfirmPassword] = useState(data?.password ?? "");
3434
const [isActive, setIsActive] = useState(data?.is_active ?? false);
3535
const [isSuperUser, setIsSuperUser] = useState(data?.is_superuser ?? false);
36+
const [trialDate, setTrialDate] = useState<string>(
37+
data?.optins?.trial_access_until
38+
? data.optins.trial_access_until.split("T")[0]
39+
: "",
40+
);
41+
const [skipTrial, setSkipTrial] = useState<boolean>(
42+
Boolean(data?.optins?.skip_trial_access),
43+
);
3644
const [inputState, setInputState] = useState<UserInputType>(CONTROL_NEW_USER);
3745
const { userData } = useContext(AuthContext);
3846

@@ -50,6 +58,12 @@ export default function UserManagementModal({
5058
setUserName(data.username);
5159
setIsActive(data.is_active);
5260
setIsSuperUser(data.is_superuser);
61+
setTrialDate(
62+
data.optins?.trial_access_until
63+
? data.optins.trial_access_until.split("T")[0]
64+
: "",
65+
);
66+
setSkipTrial(Boolean(data.optins?.skip_trial_access));
5367

5468
handleInput({ target: { name: "username", value: username } });
5569
handleInput({ target: { name: "is_active", value: isActive } });
@@ -64,6 +78,8 @@ export default function UserManagementModal({
6478
setConfirmPassword("");
6579
setIsActive(false);
6680
setIsSuperUser(false);
81+
setTrialDate("");
82+
setSkipTrial(false);
6783
}
6884

6985
return (
@@ -85,7 +101,21 @@ export default function UserManagementModal({
85101
return;
86102
}
87103
resetForm();
88-
onConfirm(1, inputState);
104+
const trialAccess = trialDate
105+
? new Date(trialDate).toISOString()
106+
: undefined;
107+
onConfirm(1, {
108+
...inputState,
109+
username,
110+
password,
111+
is_active: isActive,
112+
is_superuser: isSuperUser,
113+
optins: {
114+
...(data?.optins ?? {}),
115+
...(trialAccess ? { trial_access_until: trialAccess } : {}),
116+
skip_trial_access: skipTrial,
117+
},
118+
});
89119
setOpen(false);
90120
event.preventDefault();
91121
}}
@@ -278,6 +308,38 @@ export default function UserManagementModal({
278308
</Form.Field>
279309
)}
280310
</div>
311+
312+
<div className="grid gap-2">
313+
<Form.Label className="data-[invalid]:label-invalid">
314+
Trial end date
315+
</Form.Label>
316+
<Form.Control asChild>
317+
<input
318+
type="date"
319+
value={trialDate}
320+
className="primary-input"
321+
onChange={(event) => setTrialDate(event.target.value)}
322+
/>
323+
</Form.Control>
324+
<div className="flex items-center gap-2">
325+
<Checkbox
326+
checked={skipTrial}
327+
id="skip_trial_access"
328+
className="relative top-0.5"
329+
onCheckedChange={(value) => {
330+
setSkipTrial(Boolean(value));
331+
}}
332+
/>
333+
<Form.Label className="data-[invalid]:label-invalid">
334+
Skip trial for this user
335+
</Form.Label>
336+
</div>
337+
{data?.optins?.trial_access_until ? (
338+
<p className="text-xs text-muted-foreground">
339+
Stored value: {data.optins.trial_access_until}
340+
</p>
341+
) : null}
342+
</div>
281343
</div>
282344

283345
<div className="float-right">

0 commit comments

Comments
 (0)