GeneIT/geneit_app/src/api/MemberApi.ts

349 lines
7.8 KiB
TypeScript

import { APIClient } from "./ApiClient";
import { Couple } from "./CoupleApi";
export type Sex = "M" | "F";
export interface MemberDataApi {
id: number;
family_id: number;
first_name?: string;
last_name?: string;
birth_last_name?: string;
photo_id?: number;
signed_photo_id?: number;
email?: string;
phone?: string;
address?: string;
city?: string;
postal_code?: string;
country?: string;
sex?: Sex;
time_create?: number;
time_update?: number;
mother?: number;
father?: number;
birth_year?: number;
birth_month?: number;
birth_day?: number;
dead: boolean;
death_year?: number;
death_month?: number;
death_day?: number;
note?: string;
}
export interface DateValue {
year?: number;
month?: number;
day?: number;
}
export class Member implements MemberDataApi {
id: number;
family_id: number;
first_name?: string;
last_name?: string;
birth_last_name?: string;
photo_id?: number;
signed_photo_id?: number;
email?: string;
phone?: string;
address?: string;
city?: string;
postal_code?: string;
country?: string;
sex?: Sex;
time_create?: number;
time_update?: number;
mother?: number;
father?: number;
birth_year?: number;
birth_month?: number;
birth_day?: number;
dead!: boolean;
death_year?: number;
death_month?: number;
death_day?: number;
note?: string;
constructor(m: MemberDataApi) {
this.id = m.id;
this.family_id = m.family_id;
this.first_name = m.first_name;
this.last_name = m.last_name;
this.birth_last_name = m.birth_last_name;
this.photo_id = m.photo_id;
this.signed_photo_id = m.signed_photo_id;
this.email = m.email;
this.phone = m.phone;
this.address = m.address;
this.city = m.city;
this.postal_code = m.postal_code;
this.country = m.country;
this.sex = m.sex;
this.time_create = m.time_create;
this.time_update = m.time_update;
this.mother = m.mother;
this.father = m.father;
this.birth_year = m.birth_year;
this.birth_month = m.birth_month;
this.birth_day = m.birth_day;
this.dead = m.dead;
this.death_year = m.death_year;
this.death_month = m.death_month;
this.death_day = m.death_day;
this.note = m.note;
}
/**
* Create an empty member object
*/
static New(family_id: number): Member {
return new Member({
id: 0,
dead: false,
family_id: family_id,
sex: "M",
});
}
get fullName(): string {
const firstName = this.first_name ?? "";
return firstName.length === 0
? this.last_name ?? ""
: `${firstName} ${this.last_name?.toUpperCase() ?? ""}`;
}
get invertedFullName(): string {
const lastName = this.last_name ?? "";
return lastName.length === 0
? this.last_name ?? ""
: `${lastName} ${this.first_name ?? ""}`;
}
get hasPhoto(): boolean {
return this.photo_id !== null;
}
get photoURL(): string | null {
if (!this.signed_photo_id) return null;
return `${APIClient.backendURL()}/photo/${this.signed_photo_id}`;
}
get thumbnailURL(): string | null {
if (!this.signed_photo_id) return null;
return `${APIClient.backendURL()}/photo/${this.signed_photo_id}/thumbnail`;
}
get dateOfBirth(): DateValue | undefined {
if (!this.birth_day && !this.birth_month && !this.birth_year)
return undefined;
return {
year: this.birth_year,
month: this.birth_month,
day: this.birth_day,
};
}
get dateOfDeath(): DateValue | undefined {
if (!this.death_day && !this.death_month && !this.death_year)
return undefined;
return {
year: this.death_year,
month: this.death_month,
day: this.death_day,
};
}
get displayBirthDeath(): string {
let birthDeath = [];
if (this.dateOfBirth) birthDeath.push(fmtDate(this.dateOfBirth));
if (this.dateOfDeath) birthDeath.push(fmtDate(this.dateOfDeath));
return birthDeath.join(" - ");
}
get hasContactInfo(): boolean {
return this.email ||
this.phone ||
this.address ||
this.city ||
this.postal_code ||
this.country
? true
: false;
}
get hasNote(): boolean {
return (this.note?.length ?? 0) > 0;
}
}
export function fmtDate(d?: DateValue): string {
if (d?.year && !d.month && !d.day)
return d?.year?.toString().padStart(4, "0");
return `${d?.day?.toString().padStart(2, "0") ?? "__"}/${
d?.month?.toString().padStart(2, "0") ?? "__"
}/${d?.year?.toString().padStart(4, "0") ?? "__"}`;
}
const OLD_TIME = -58991812735;
export function dateTimestamp(d?: DateValue): number {
if (!d) return OLD_TIME;
const date = new Date();
date.setFullYear(d.year ?? 1010, (d.month ?? 1) - 1, d.day ?? 1);
return date.getTime() / 1000;
}
export class MembersList {
private list: Member[];
private map: Map<number, Member>;
constructor(list: Member[]) {
this.list = list;
this.map = new Map();
for (const m of list) {
this.map.set(m.id, m);
}
this.list.sort((a, b) =>
a.invertedFullName
.toLowerCase()
.localeCompare(b.invertedFullName.toLocaleLowerCase())
);
}
public get isEmpty(): boolean {
return this.list.length === 0;
}
public get size(): number {
return this.list.length;
}
public get fullList(): Member[] {
return this.list;
}
filter(predicate: (m: Member) => boolean): Member[] {
return this.list.filter(predicate);
}
get(id: number): Member | undefined {
return this.map.get(id);
}
children(id: number): Member[] {
return this.list.filter((m) => m.mother === id || m.father === id);
}
childrenOfCouple(c: Couple): Member[] {
if (!c.husband && !c.wife) return [];
return this.list.filter(
(m) => m.mother === c.wife && m.father === c.husband
);
}
siblings(id: number): Member[] {
const p = this.get(id);
return this.list.filter(
(m) =>
m.id !== p?.id &&
((m.mother && m.mother === p?.mother) ||
(m.father && m.father === p?.father))
);
}
}
export class MemberApi {
/**
* Create a new member
*/
static async Create(m: Member): Promise<Member> {
const res = await APIClient.exec({
uri: `/family/${m.family_id}/member/create`,
method: "POST",
jsonData: m,
});
return new Member(res.data);
}
/**
* Get the information about a single member
*/
static async GetSingle(
family_id: number,
member_id: number
): Promise<Member> {
const res = await APIClient.exec({
uri: `/family/${family_id}/member/${member_id}`,
method: "GET",
});
return new Member(res.data);
}
/**
* Get the entire list of family members of a family
*/
static async GetEntireList(family_id: number): Promise<MembersList> {
const res = await APIClient.exec({
uri: `/family/${family_id}/members`,
method: "GET",
});
return new MembersList(res.data.map((d: any) => new Member(d)));
}
/**
* Update a member information
*/
static async Update(m: Member): Promise<void> {
await APIClient.exec({
uri: `/family/${m.family_id}/member/${m.id}`,
method: "PUT",
jsonData: m,
});
}
/**
* Set a new photo for a member
*/
static async SetMemberPhoto(m: Member, b: Blob): Promise<void> {
const fd = new FormData();
fd.append("photo", b);
await APIClient.exec({
uri: `/family/${m.family_id}/member/${m.id}/photo`,
method: "PUT",
formData: fd,
});
}
/**
* Remove the photo of a member
*/
static async RemoveMemberPhoto(m: Member): Promise<void> {
await APIClient.exec({
uri: `/family/${m.family_id}/member/${m.id}/photo`,
method: "DELETE",
});
}
/**
* Delete a family member
*/
static async Delete(m: Member): Promise<void> {
await APIClient.exec({
uri: `/family/${m.family_id}/member/${m.id}`,
method: "DELETE",
});
}
}