Files
myeasycms-v2/apps/web/app/admin/users/[uid]/page.tsx
giancarlo cb8b23e8c0 Remove billing and checkout redirect buttons and related services
Deleted the billing-redirect-button, checkout-redirect-button, and embedded-stripe-checkout components. Additionally, removed the shadcn directory, which encompassed billing-related icons. This change streamlines the subscription settings interface and organizes the system's payment management. This update is a stepping stone towards improving the billing system's overall architecture.
2024-03-25 11:39:41 +08:00

239 lines
6.2 KiB
TypeScript

import Link from 'next/link';
import { PageBody } from '@/components/app/Page';
import configuration from '@/config/app.config';
import type MembershipRole from '@/lib/organizations/types/membership-role';
import { ChevronRightIcon } from 'lucide-react';
import getSupabaseServerComponentClient from '@packages/supabase/server-component-client';
import { Badge } from '@kit/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card';
import { Input } from '@kit/ui/input';
import { Label } from '@kit/ui/label';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@kit/ui/table';
import RoleBadge from '../../../(app)/[account]/account/organization/components/RoleBadge';
import AdminGuard from '../../../../packages/admin/components/AdminGuard';
import AdminHeader from '../../../../packages/admin/components/AdminHeader';
import UserActionsDropdown from './components/UserActionsDropdown';
interface Params {
params: {
uid: string;
};
}
export const metadata = {
title: `Manage User | ${configuration.name}`,
};
async function AdminUserPage({ params }: Params) {
const uid = params.uid;
const data = await loadData(uid);
const { auth, user } = data;
const displayName = user?.displayName;
const authUser = auth?.user;
const email = authUser?.email;
const phone = authUser?.phone;
const organizations = data.organizations ?? [];
const isBanned = Boolean(
authUser && 'banned_until' in authUser && authUser.banned_until !== 'none',
);
return (
<div className={'flex flex-1 flex-col'}>
<AdminHeader>Manage User</AdminHeader>
<PageBody>
<div className={'flex flex-col space-y-6'}>
<div className={'flex justify-between'}>
<Breadcrumbs displayName={displayName ?? email ?? ''} />
<div>
<UserActionsDropdown uid={uid} isBanned={isBanned} />
</div>
</div>
<Card>
<CardHeader>
<CardTitle>User Details</CardTitle>
</CardHeader>
<CardContent>
<div className={'flex items-center space-x-2'}>
<div>
<Label>Status</Label>
</div>
<div className={'inline-flex'}>
{isBanned ? (
<Badge variant={'destructive'}>Banned</Badge>
) : (
<Badge variant={'success'}>Active</Badge>
)}
</div>
</div>
<Label>
Display name
<Input
className={'max-w-sm'}
defaultValue={displayName ?? ''}
disabled
/>
</Label>
<Label>
Email
<Input
className={'max-w-sm'}
defaultValue={email ?? ''}
disabled
/>
</Label>
<Label>
Phone number
<Input
className={'max-w-sm'}
defaultValue={phone ?? ''}
disabled
/>
</Label>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Organizations</CardTitle>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
<TableHead>Organization ID</TableHead>
<TableHead>UUID</TableHead>
<TableHead>Organization</TableHead>
<TableHead>Role</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{organizations.map((membership) => {
const organization = membership.organization;
const href = `/admin/organizations/${organization.uuid}/members`;
return (
<TableRow key={membership.id}>
<TableCell>{organization.id}</TableCell>
<TableCell>{organization.uuid}</TableCell>
<TableCell>
<Link className={'hover:underline'} href={href}>
{organization.name}
</Link>
</TableCell>
<TableCell>
<div className={'inline-flex'}>
<RoleBadge role={membership.role} />
</div>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</CardContent>
</Card>
</div>
</PageBody>
</div>
);
}
export default AdminGuard(AdminUserPage);
async function loadData(uid: string) {
const client = getSupabaseServerComponentClient({ admin: true });
const authUser = client.auth.admin.getUserById(uid);
const userData = client
.from('users')
.select(
`
id,
displayName: display_name,
photoURL: photo_url,
onboarded
`,
)
.eq('id', uid)
.single();
const organizationsQuery = client
.from('memberships')
.select<
string,
{
id: number;
role: MembershipRole;
organization: {
id: number;
uuid: string;
name: string;
};
}
>(
`
id,
role,
organization: organization_id !inner (
id,
uuid,
name
)
`,
)
.eq('user_id', uid);
const [auth, user, organizations] = await Promise.all([
authUser,
userData,
organizationsQuery,
]);
return {
auth: auth.data,
user: user.data,
organizations: organizations.data,
};
}
function Breadcrumbs(
props: React.PropsWithChildren<{
displayName: string;
}>,
) {
return (
<div className={'flex items-center space-x-1 p-2 text-xs'}>
<Link href={'/admin'}>Admin</Link>
<ChevronRightIcon className={'w-3'} />
<Link href={'/admin/users'}>Users</Link>
<ChevronRightIcon className={'w-3'} />
<span>{props.displayName}</span>
</div>
);
}