Files
chronus/src/pages/dashboard/team.astro
Atridad Lahiji 82e1b8a626
Some checks failed
Docker Deploy / build-and-push (push) Has been cancelled
Style updates
2026-01-18 01:40:22 -07:00

130 lines
4.7 KiB
Plaintext

---
import DashboardLayout from '../../layouts/DashboardLayout.astro';
import Avatar from '../../components/Avatar.astro';
import { Icon } from 'astro-icon/components';
import { db } from '../../db';
import { members, users } from '../../db/schema';
import { eq } from 'drizzle-orm';
const user = Astro.locals.user;
if (!user) return Astro.redirect('/login');
// Get current team from cookie
const currentTeamId = Astro.cookies.get('currentTeamId')?.value;
const userMemberships = await db.select()
.from(members)
.where(eq(members.userId, user.id))
.all();
if (userMemberships.length === 0) return Astro.redirect('/dashboard');
// Use current team or fallback to first membership
const userMembership = currentTeamId
? userMemberships.find(m => m.organizationId === currentTeamId) || userMemberships[0]
: userMemberships[0];
const teamMembers = await db.select({
member: members,
user: users,
})
.from(members)
.innerJoin(users, eq(members.userId, users.id))
.where(eq(members.organizationId, userMembership.organizationId))
.all();
const currentUserMember = teamMembers.find(m => m.user.id === user.id);
const isAdmin = currentUserMember?.member.role === 'owner' || currentUserMember?.member.role === 'admin';
---
<DashboardLayout title="Team - Chronus">
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-6">
<h1 class="text-3xl font-bold">Team Members</h1>
<div class="flex gap-2">
{isAdmin && (
<>
<a href="/dashboard/team/settings" class="btn btn-ghost">
<Icon name="heroicons:cog-6-tooth" class="w-5 h-5" />
Settings
</a>
<a href="/dashboard/team/invite" class="btn btn-primary">Invite Member</a>
</>
)}
</div>
</div>
<div class="card bg-base-100 shadow-xl border border-base-200">
<div class="card-body">
<div class="overflow-x-auto">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
<th>Joined</th>
{isAdmin && <th>Actions</th>}
</tr>
</thead>
<tbody>
{teamMembers.map(({ member, user: teamUser }) => (
<tr>
<td>
<div class="flex items-center gap-3">
<Avatar name={teamUser.name} />
<div>
<div class="font-bold">{teamUser.name}</div>
{teamUser.id === user.id && (
<span class="badge badge-sm">You</span>
)}
</div>
</div>
</td>
<td>{teamUser.email}</td>
<td>
<span class={`badge ${
member.role === 'owner' ? 'badge-primary' :
member.role === 'admin' ? 'badge-secondary' :
'badge-ghost'
}`}>
{member.role}
</span>
</td>
<td>{member.joinedAt?.toLocaleDateString() ?? 'N/A'}</td>
{isAdmin && (
<td>
{teamUser.id !== user.id && member.role !== 'owner' && (
<div class="dropdown dropdown-end">
<label tabindex="0" class="btn btn-ghost btn-sm">
<Icon name="heroicons:ellipsis-vertical" class="w-5 h-5" />
</label>
<ul tabindex="0" class="dropdown-content z-1 menu p-2 shadow bg-base-100 rounded-box w-52 border border-base-200">
<li>
<form method="POST" action={`/api/team/change-role`}>
<input type="hidden" name="userId" value={teamUser.id} />
<input type="hidden" name="role" value={member.role === 'admin' ? 'member' : 'admin'} />
<button type="submit">
{member.role === 'admin' ? 'Make Member' : 'Make Admin'}
</button>
</form>
</li>
<li>
<form method="POST" action={`/api/team/remove`}>
<input type="hidden" name="userId" value={teamUser.id} />
<button type="submit" class="text-error">Remove</button>
</form>
</li>
</ul>
</div>
)}
</td>
)}
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</DashboardLayout>