feat(member): improve assistant roster awareness

This commit is contained in:
2026-03-11 15:10:20 +04:00
parent 79f96ba45b
commit 0787847c19
27 changed files with 1429 additions and 3 deletions

View File

@@ -146,6 +146,35 @@ export interface MiniAppAdminService {
reason: 'not_admin' | 'member_not_found'
}
>
updateOwnDisplayName(input: {
householdId: string
actorMemberId: string
displayName: string
}): Promise<
| {
status: 'ok'
member: HouseholdMemberRecord
}
| {
status: 'rejected'
reason: 'invalid_display_name' | 'member_not_found'
}
>
updateMemberDisplayName(input: {
householdId: string
actorIsAdmin: boolean
memberId: string
displayName: string
}): Promise<
| {
status: 'ok'
member: HouseholdMemberRecord
}
| {
status: 'rejected'
reason: 'not_admin' | 'invalid_display_name' | 'member_not_found'
}
>
updateMemberAbsencePolicy(input: {
householdId: string
actorIsAdmin: boolean
@@ -171,6 +200,16 @@ function periodFromLocalDate(localDate: Temporal.PlainDate): string {
return `${localDate.year}-${String(localDate.month).padStart(2, '0')}`
}
function normalizeDisplayName(raw: string): string | null {
const trimmed = raw.trim()
if (trimmed.length < 2 || trimmed.length > 80) {
return null
}
return trimmed.replace(/\s+/g, ' ')
}
export function createMiniAppAdminService(
repository: HouseholdConfigurationRepository
): MiniAppAdminService {
@@ -445,6 +484,69 @@ export function createMiniAppAdminService(
}
},
async updateOwnDisplayName(input) {
const displayName = normalizeDisplayName(input.displayName)
if (!displayName) {
return {
status: 'rejected',
reason: 'invalid_display_name'
}
}
const member = await repository.updateHouseholdMemberDisplayName(
input.householdId,
input.actorMemberId,
displayName
)
if (!member) {
return {
status: 'rejected',
reason: 'member_not_found'
}
}
return {
status: 'ok',
member
}
},
async updateMemberDisplayName(input) {
if (!input.actorIsAdmin) {
return {
status: 'rejected',
reason: 'not_admin'
}
}
const displayName = normalizeDisplayName(input.displayName)
if (!displayName) {
return {
status: 'rejected',
reason: 'invalid_display_name'
}
}
const member = await repository.updateHouseholdMemberDisplayName(
input.householdId,
input.memberId,
displayName
)
if (!member) {
return {
status: 'rejected',
reason: 'member_not_found'
}
}
return {
status: 'ok',
member
}
},
async updateMemberAbsencePolicy(input) {
if (!input.actorIsAdmin) {
return {