|
| 1 | +import { redirect } from "next/navigation"; |
| 2 | +import { createClient } from "~/utils/supabase/server"; |
| 3 | +import { |
| 4 | + removeFromGroup, |
| 5 | + getSessionBaseUserData, |
| 6 | +} from "~/utils/supabase/account"; |
| 7 | +import { Button } from "@repo/ui/components/ui/button"; |
| 8 | +import internalError from "~/utils/internalErrorSsr"; |
| 9 | + |
| 10 | +export const GroupMemberList = async ({ |
| 11 | + groupId, |
| 12 | + isAdmin, |
| 13 | + removeError, |
| 14 | +}: { |
| 15 | + groupId: string; |
| 16 | + isAdmin: boolean; |
| 17 | + removeError?: string; |
| 18 | +}) => { |
| 19 | + const client = await createClient(); |
| 20 | + const clientData = await getSessionBaseUserData(client); |
| 21 | + const myUserId = clientData?.id; |
| 22 | + if (!myUserId) { |
| 23 | + internalError({ error: "Not logged in" }); |
| 24 | + redirect( |
| 25 | + "/auth/error?error=" + |
| 26 | + encodeURIComponent("Not logged in.\nPlease log in from application."), |
| 27 | + ); |
| 28 | + } |
| 29 | + |
| 30 | + const pseudoAccountReq = await client |
| 31 | + .from("my_pseudo_accounts") |
| 32 | + .select() |
| 33 | + .eq("group_id", groupId); |
| 34 | + |
| 35 | + if (pseudoAccountReq.error) { |
| 36 | + internalError({ error: pseudoAccountReq.error }); |
| 37 | + redirect( |
| 38 | + "/auth/error?error=" + encodeURIComponent("Could not load group members"), |
| 39 | + ); |
| 40 | + } |
| 41 | + const pseudoAccountInfo = pseudoAccountReq.data ?? []; |
| 42 | + const numAdmins = pseudoAccountInfo |
| 43 | + .map((pa) => (pa.admin ? 1 : 0) as number) |
| 44 | + .reduce((acc, cur) => acc + cur, 0); |
| 45 | + |
| 46 | + const removeSpace = async (formData: FormData) => { |
| 47 | + "use server"; |
| 48 | + const memberId = formData.get("memberId"); |
| 49 | + if (typeof memberId !== "string") return; |
| 50 | + const c = await createClient(); |
| 51 | + const error = await removeFromGroup({ client: c, groupId, memberId }); |
| 52 | + if (error) { |
| 53 | + redirect( |
| 54 | + `/auth/group/${groupId}?removeError=` + encodeURIComponent(error), |
| 55 | + ); |
| 56 | + } |
| 57 | + redirect(`/auth/group/${groupId}`); |
| 58 | + }; |
| 59 | + |
| 60 | + return ( |
| 61 | + <section className="space-y-3"> |
| 62 | + <h2 className="text-lg font-semibold">Member spaces</h2> |
| 63 | + {removeError && <p className="text-destructive text-sm">{removeError}</p>} |
| 64 | + {pseudoAccountInfo.length === 0 ? ( |
| 65 | + <p className="text-muted-foreground text-sm">No spaces yet.</p> |
| 66 | + ) : ( |
| 67 | + <ul className="divide-y rounded-md border"> |
| 68 | + {pseudoAccountInfo.map((pseudoAccount) => { |
| 69 | + const memberId = pseudoAccount.dg_account; |
| 70 | + return ( |
| 71 | + <li |
| 72 | + key={`${pseudoAccount.id}-${pseudoAccount.space_id}`} |
| 73 | + className="flex items-center justify-between px-4 py-2" |
| 74 | + > |
| 75 | + <span> |
| 76 | + {pseudoAccount.name} |
| 77 | + <span className="text-muted-foreground ml-2 text-xs"> |
| 78 | + ({pseudoAccount.platform}) |
| 79 | + </span> |
| 80 | + {pseudoAccount.dg_account === myUserId && ( |
| 81 | + <span className="ml-2 rounded bg-blue-300 px-1.5 py-0.5 text-xs text-blue-900"> |
| 82 | + me |
| 83 | + </span> |
| 84 | + )} |
| 85 | + {pseudoAccount.admin && ( |
| 86 | + <span className="ml-2 rounded bg-blue-100 px-1.5 py-0.5 text-xs text-blue-700"> |
| 87 | + admin |
| 88 | + </span> |
| 89 | + )} |
| 90 | + </span> |
| 91 | + {memberId && |
| 92 | + // allow admins to remove others |
| 93 | + // admins should not remove self, unless there's another admin |
| 94 | + ((isAdmin && |
| 95 | + (numAdmins > 1 || pseudoAccount.dg_account !== myUserId)) || |
| 96 | + // non-admins can remove self. |
| 97 | + pseudoAccount.dg_account === myUserId) && ( |
| 98 | + <form action={removeSpace}> |
| 99 | + <input type="hidden" name="memberId" value={memberId} /> |
| 100 | + <Button type="submit" variant="destructive" size="sm"> |
| 101 | + Remove |
| 102 | + </Button> |
| 103 | + </form> |
| 104 | + )} |
| 105 | + </li> |
| 106 | + ); |
| 107 | + })} |
| 108 | + </ul> |
| 109 | + )} |
| 110 | + </section> |
| 111 | + ); |
| 112 | +}; |
0 commit comments