diff --git a/src/components/MembershipCard.astro b/src/components/MembershipCard.astro new file mode 100644 index 0000000..3e018e3 --- /dev/null +++ b/src/components/MembershipCard.astro @@ -0,0 +1,145 @@ +--- +import type { UserPublic } from '../lib/db'; +import { readFocusTags } from '../lib/format'; + +interface Props { + member: UserPublic; +} + +const { member } = Astro.props; + +// Split on the last space — handles compound surnames better than first-space split. +const parts = member.name.trim().split(/\s+/); +const firstName = parts.length === 1 ? parts[0] : parts.slice(0, -1).join(' '); +const lastName = parts.length === 1 ? '' : parts[parts.length - 1]; + +const numberLabel = member.member_number != null + ? `COUNCIL · ${String(member.member_number).padStart(3, '0')}` + : 'COUNCIL · MEMBER'; + +// Member-since: prefer cab_joined_date, fall back to created_at. +const sinceISO = member.cab_joined_date ?? member.created_at; +const since = new Intl.DateTimeFormat('en-GB', { + month: 'long', year: 'numeric', timeZone: 'Europe/Copenhagen', +}).format(new Date(sinceISO.replace(' ', 'T') + (sinceISO.includes('T') ? '' : 'Z'))); + +const tags = readFocusTags(member.focus_tags); +--- +
+
+ + {numberLabel} +
+ +

+ {firstName} + {lastName && {lastName}} +

+ +

+ Member since + {since} +

+ + {tags.length > 0 && ( + + )} +
+ +