feat: add Angular member and user models + API services
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
export type MemberStatus = 'Member' | 'Visitor' | 'Inactive' | 'Former';
|
||||
|
||||
export interface MemberListItemDto {
|
||||
id: number;
|
||||
firstName_en: string;
|
||||
lastName_en: string;
|
||||
nickName: string | null;
|
||||
firstName_zh: string | null;
|
||||
lastName_zh: string | null;
|
||||
status: MemberStatus;
|
||||
email: string | null;
|
||||
phoneCell: string | null;
|
||||
joinDate: string | null;
|
||||
linkedUserId: string | null;
|
||||
}
|
||||
|
||||
export interface MemberDto extends MemberListItemDto {
|
||||
gender: string | null;
|
||||
dateOfBirth: string | null;
|
||||
baptismDate: string | null;
|
||||
baptismChurch: string | null;
|
||||
phoneHome: string | null;
|
||||
address: string | null;
|
||||
city: string | null;
|
||||
state: string | null;
|
||||
zipCode: string | null;
|
||||
country: string;
|
||||
photoBlobPath: string | null;
|
||||
languagePreference: string;
|
||||
notes: string | null;
|
||||
familyUnitId: number | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface CreateMemberRequest {
|
||||
firstName_en: string;
|
||||
lastName_en: string;
|
||||
nickName: string | null;
|
||||
firstName_zh: string | null;
|
||||
lastName_zh: string | null;
|
||||
gender: string | null;
|
||||
dateOfBirth: string | null;
|
||||
baptismDate: string | null;
|
||||
baptismChurch: string | null;
|
||||
email: string | null;
|
||||
phoneCell: string | null;
|
||||
phoneHome: string | null;
|
||||
address: string | null;
|
||||
city: string | null;
|
||||
state: string | null;
|
||||
zipCode: string | null;
|
||||
country: string;
|
||||
status: string;
|
||||
languagePreference: string;
|
||||
joinDate: string | null;
|
||||
notes: string | null;
|
||||
familyUnitId: number | null;
|
||||
}
|
||||
|
||||
export type UpdateMemberRequest = CreateMemberRequest;
|
||||
|
||||
export interface PagedResult<T> {
|
||||
items: T[];
|
||||
totalCount: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
totalPages: number;
|
||||
}
|
||||
|
||||
export interface MemberQueryParams {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
search?: string;
|
||||
status?: string;
|
||||
hasUser?: boolean;
|
||||
}
|
||||
|
||||
/** Display name: NickName (if present) else FirstName_en, plus LastName_en */
|
||||
export function memberDisplayName(
|
||||
m: Pick<MemberListItemDto, 'nickName' | 'firstName_en' | 'lastName_en'>
|
||||
): string {
|
||||
return `${m.nickName ?? m.firstName_en} ${m.lastName_en}`;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ApiConfigService } from '../../../core/services/api-config.service';
|
||||
import {
|
||||
MemberDto, MemberListItemDto, CreateMemberRequest,
|
||||
UpdateMemberRequest, MemberQueryParams, PagedResult
|
||||
} from '../models/member.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class MemberApiService {
|
||||
private readonly endpoint: string;
|
||||
|
||||
constructor(private http: HttpClient, apiConfig: ApiConfigService) {
|
||||
this.endpoint = apiConfig.getApiUrl('members');
|
||||
}
|
||||
|
||||
getPaged(params: MemberQueryParams = {}): Observable<PagedResult<MemberListItemDto>> {
|
||||
let p = new HttpParams()
|
||||
.set('page', params.page ?? 1)
|
||||
.set('pageSize', params.pageSize ?? 20);
|
||||
if (params.search !== undefined && params.search !== '') p = p.set('search', params.search);
|
||||
if (params.status !== undefined && params.status !== '') p = p.set('status', params.status);
|
||||
if (params.hasUser !== undefined) p = p.set('hasUser', params.hasUser);
|
||||
return this.http.get<PagedResult<MemberListItemDto>>(this.endpoint, { params: p });
|
||||
}
|
||||
|
||||
getById(id: number): Observable<MemberDto> {
|
||||
return this.http.get<MemberDto>(`${this.endpoint}/${id}`);
|
||||
}
|
||||
|
||||
create(request: CreateMemberRequest): Observable<{ id: number }> {
|
||||
return this.http.post<{ id: number }>(this.endpoint, request);
|
||||
}
|
||||
|
||||
update(id: number, request: UpdateMemberRequest): Observable<void> {
|
||||
return this.http.put<void>(`${this.endpoint}/${id}`, request);
|
||||
}
|
||||
|
||||
delete(id: number): Observable<void> {
|
||||
return this.http.delete<void>(`${this.endpoint}/${id}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
export interface UserListItemDto {
|
||||
id: string;
|
||||
email: string;
|
||||
memberId: number | null;
|
||||
memberDisplayName: string | null;
|
||||
roles: string[];
|
||||
isActive: boolean;
|
||||
languagePreference: string;
|
||||
lastLoginAt: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export type UserDto = UserListItemDto;
|
||||
|
||||
export interface CreateUserRequest {
|
||||
memberId: number;
|
||||
email: string;
|
||||
roles: string[];
|
||||
languagePreference: string;
|
||||
}
|
||||
|
||||
export interface CreateUserResult {
|
||||
userId: string;
|
||||
tempPassword: string;
|
||||
}
|
||||
|
||||
export interface UpdateUserRequest {
|
||||
email: string;
|
||||
roles: string[];
|
||||
isActive: boolean;
|
||||
languagePreference: string;
|
||||
}
|
||||
|
||||
export interface UserQueryParams {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
search?: string;
|
||||
}
|
||||
|
||||
export interface PagedResult<T> {
|
||||
items: T[];
|
||||
totalCount: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
totalPages: number;
|
||||
}
|
||||
|
||||
export const ALL_ROLES = [
|
||||
'super_admin','pastor','board_member','coworker_chair','ministry_leader',
|
||||
'district_leader','cell_leader','coworker','finance','secretary',
|
||||
'worship_leader','member','visitor'
|
||||
] as const;
|
||||
@@ -0,0 +1,46 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ApiConfigService } from '../../../core/services/api-config.service';
|
||||
import {
|
||||
UserDto, UserListItemDto, CreateUserRequest, CreateUserResult,
|
||||
UpdateUserRequest, UserQueryParams, PagedResult
|
||||
} from '../models/user.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UserApiService {
|
||||
private readonly endpoint: string;
|
||||
|
||||
constructor(private http: HttpClient, apiConfig: ApiConfigService) {
|
||||
this.endpoint = apiConfig.getApiUrl('users');
|
||||
}
|
||||
|
||||
getPaged(params: UserQueryParams = {}): Observable<PagedResult<UserListItemDto>> {
|
||||
let p = new HttpParams()
|
||||
.set('page', params.page ?? 1)
|
||||
.set('pageSize', params.pageSize ?? 20);
|
||||
if (params.search) p = p.set('search', params.search);
|
||||
return this.http.get<PagedResult<UserListItemDto>>(this.endpoint, { params: p });
|
||||
}
|
||||
|
||||
getById(id: string): Observable<UserDto> {
|
||||
return this.http.get<UserDto>(`${this.endpoint}/${id}`);
|
||||
}
|
||||
|
||||
createUser(request: CreateUserRequest): Observable<CreateUserResult> {
|
||||
return this.http.post<CreateUserResult>(this.endpoint, request);
|
||||
}
|
||||
|
||||
update(id: string, request: UpdateUserRequest): Observable<void> {
|
||||
return this.http.put<void>(`${this.endpoint}/${id}`, request);
|
||||
}
|
||||
|
||||
deactivate(id: string): Observable<void> {
|
||||
return this.http.delete<void>(`${this.endpoint}/${id}`);
|
||||
}
|
||||
|
||||
resetPassword(id: string): Observable<{ tempPassword: string }> {
|
||||
return this.http.post<{ tempPassword: string }>(
|
||||
`${this.endpoint}/${id}/reset-password`, {});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user