import { ApiKeys, AddressData, CreditData, FormData, KycData, LoanPartData, PersonData, TinkLoanData, UserData, Id, TinkAccountData, } from '../types'; import { useBaseModel, UseBaseModelType } from './use-base-model'; import { useAsync, UseAsyncResult } from './use-async'; import { UseHasMany, useHasMany } from './use-has-many'; import { useSDKEventBus } from './use-models'; import { useState, useEffect } from 'react'; import { CHANGE_EVENT_TYPE, UserModel } from '../models'; export type LoginTokenType = { token: string; }; export type UseUserModelType = UseBaseModelType & { login: () => UseAsyncResult; anonymousLogin: () => UseAsyncResult; formInit: (userId: Id) => UseAsyncResult; lookUpPerson: (userId: Id) => UseAsyncResult; forms: UseHasMany; persons: UseHasMany; addresses: UseHasMany; loanParts: UseHasMany; credits: UseHasMany; kycs: UseHasMany; tinkLoans: UseHasMany; tinkAccounts: UseHasMany; }; export const useUsers = (): UseUserModelType => { const modelHooks = useBaseModel(ApiKeys.USERS); const forms = useHasMany(modelHooks.model, 'forms'); const persons = useHasMany(modelHooks.model, 'persons'); const addresses = useHasMany(modelHooks.model, 'addresses'); const loanParts = useHasMany(modelHooks.model, 'loanParts'); const credits = useHasMany(modelHooks.model, 'credits'); const kycs = useHasMany(modelHooks.model, 'kycs'); const tinkLoans = useHasMany(modelHooks.model, 'tinkLoans'); const tinkAccounts = useHasMany( modelHooks.model, 'tinkAccounts', ); return { ...modelHooks, // @ts-ignore anonymousLogin: anonymousLogin(modelHooks.model), // @ts-ignore login: login(modelHooks.model), // @ts-ignore formInit: formInit(modelHooks.model), // @ts-ignore lookUpPerson: lookUpPerson(modelHooks.model), forms, persons, addresses, loanParts, credits, tinkLoans, tinkAccounts, kycs, }; }; const login = (model: UserModel) => (): UseAsyncResult => { return useAsync(model.login.bind(model)); }; const anonymousLogin = (model: UserModel) => (): UseAsyncResult< LoginTokenType > => { return useAsync(model.anonymousLogin.bind(model)); }; // TODO Subscribe this guy to changes. const formInit = (model: UserModel) => ( userId: Id, ): UseAsyncResult => { const eventBus = useSDKEventBus(); const [data, setData] = useState(); const [gotten, fetch, loading, error] = useAsync(model.formInit.bind(model)); async function handleChange() { if (gotten && gotten.id) { setData(await model.getLocalById(gotten.id)); } } useEffect(() => { eventBus.addEventListener(CHANGE_EVENT_TYPE, handleChange); return () => eventBus.removeEventListener(CHANGE_EVENT_TYPE, handleChange); }, [gotten]); useEffect(() => { setData(gotten); }, [gotten]); const exec = (...args: any[]) => fetch(userId, ...args); return [data, exec, loading, error]; }; const lookUpPerson = (model: UserModel) => ( userId: Id, ): UseAsyncResult => { const eventBus = useSDKEventBus(); const [data, setData] = useState(); const [gotten, fetch, loading, error] = useAsync( model.lookUpPerson.bind(model), ); useEffect(() => { async function handleChange() { if (gotten && gotten.id) { try { // @ts-ignore setData(await model.persons.getLocalById(gotten.id)); } catch (error) { // Do something with error } } } eventBus.addEventListener(CHANGE_EVENT_TYPE, handleChange); return () => eventBus.removeEventListener(CHANGE_EVENT_TYPE, handleChange); }, [gotten]); const exec = (...args: any[]) => fetch(userId, ...args); return [data, exec, loading, error]; };