267 lines
6.0 KiB
TypeScript
267 lines
6.0 KiB
TypeScript
import { SupabaseClient } from '@supabase/supabase-js';
|
|
|
|
import { Database } from '@kit/supabase/database';
|
|
|
|
import { UserAnalysis } from '../types/accounts';
|
|
|
|
export type AccountWithParams =
|
|
Database['medreport']['Tables']['accounts']['Row'] & {
|
|
account_params:
|
|
| Pick<
|
|
Database['medreport']['Tables']['account_params']['Row'],
|
|
'weight' | 'height'
|
|
>[]
|
|
| null;
|
|
};
|
|
|
|
/**
|
|
* Class representing an API for interacting with user accounts.
|
|
* @constructor
|
|
* @param {SupabaseClient<Database>} client - The Supabase client instance.
|
|
*/
|
|
class AccountsApi {
|
|
constructor(private readonly client: SupabaseClient<Database>) {}
|
|
|
|
/**
|
|
* @name getAccount
|
|
* @description Get the account data for the given ID.
|
|
* @param id
|
|
*/
|
|
async getAccount(id: string): Promise<AccountWithParams> {
|
|
const { data, error } = await this.client
|
|
.schema('medreport')
|
|
.from('accounts')
|
|
.select('*, account_params: account_params (weight, height)')
|
|
.eq('id', id)
|
|
.single();
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* @name getAccountWorkspace
|
|
* @description Get the account workspace data.
|
|
*/
|
|
async getAccountWorkspace() {
|
|
const { data, error } = await this.client
|
|
.schema('medreport')
|
|
.from('user_account_workspace')
|
|
.select(`*`)
|
|
.single();
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* @name loadUserAccounts
|
|
* Load only user-owned accounts (not just memberships).
|
|
*/
|
|
async loadUserAccounts() {
|
|
const authUser = await this.client.auth.getUser();
|
|
|
|
const { data, error: userError } = authUser;
|
|
|
|
if (userError) {
|
|
console.error('Failed to get user', userError);
|
|
throw userError;
|
|
}
|
|
|
|
const { user } = data;
|
|
|
|
const { data: accounts, error } = await this.client
|
|
.schema('medreport')
|
|
.from('accounts_memberships')
|
|
.select(
|
|
`
|
|
account_id,
|
|
accounts (
|
|
name,
|
|
slug,
|
|
picture_url,
|
|
application_role
|
|
)
|
|
`,
|
|
)
|
|
.eq('user_id', user.id)
|
|
.eq('account_role', 'owner');
|
|
|
|
if (error) {
|
|
console.error('error', error);
|
|
throw error;
|
|
}
|
|
|
|
return accounts.map(({ accounts }) => ({
|
|
label: accounts.name,
|
|
value: accounts.slug,
|
|
image: accounts.picture_url,
|
|
application_role: accounts.application_role,
|
|
}));
|
|
}
|
|
|
|
async loadTempUserAccounts() {
|
|
const { data: accounts, error } = await this.client
|
|
.schema('medreport')
|
|
.from('user_accounts')
|
|
.select(`name, slug`);
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return accounts.map(({ name, slug }) => {
|
|
return {
|
|
label: name,
|
|
value: slug,
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @name getSubscription
|
|
* Get the subscription data for the given user.
|
|
* @param accountId
|
|
*/
|
|
async getSubscription(accountId: string) {
|
|
const response = await this.client
|
|
.schema('medreport')
|
|
.from('subscriptions')
|
|
.select('*, items: subscription_items !inner (*)')
|
|
.eq('account_id', accountId)
|
|
.maybeSingle();
|
|
|
|
if (response.error) {
|
|
throw response.error;
|
|
}
|
|
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Get the orders data for the given account.
|
|
* @param accountId
|
|
*/
|
|
async getOrder(accountId: string) {
|
|
const response = await this.client
|
|
.schema('medreport')
|
|
.from('orders')
|
|
.select('*, items: order_items !inner (*)')
|
|
.eq('account_id', accountId)
|
|
.maybeSingle();
|
|
|
|
if (response.error) {
|
|
throw response.error;
|
|
}
|
|
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* @name getCustomerId
|
|
* Get the billing customer ID for the given user.
|
|
* If the user does not have a billing customer ID, it will return null.
|
|
* @param accountId
|
|
*/
|
|
async getCustomerId(accountId: string) {
|
|
const response = await this.client
|
|
.schema('medreport')
|
|
.from('billing_customers')
|
|
.select('customer_id')
|
|
.eq('account_id', accountId)
|
|
.maybeSingle();
|
|
|
|
if (response.error) {
|
|
throw response.error;
|
|
}
|
|
|
|
return response.data?.customer_id;
|
|
}
|
|
|
|
async getUserAnalysis(): Promise<UserAnalysis | null> {
|
|
const authUser = await this.client.auth.getUser();
|
|
const { data, error: userError } = authUser;
|
|
|
|
if (userError) {
|
|
console.error('Failed to get user', userError);
|
|
throw userError;
|
|
}
|
|
|
|
const { user } = data;
|
|
|
|
const { data: analysisResponses } = await this.client
|
|
.schema('medreport')
|
|
.from('analysis_responses')
|
|
.select('*')
|
|
.eq('user_id', user.id);
|
|
|
|
if (!analysisResponses) {
|
|
return null;
|
|
}
|
|
|
|
const analysisResponseIds = analysisResponses.map((r) => r.id);
|
|
|
|
const { data: analysisResponseElements } = await this.client
|
|
.schema('medreport')
|
|
.from('analysis_response_elements')
|
|
.select('*')
|
|
.in('analysis_response_id', analysisResponseIds);
|
|
|
|
if (!analysisResponseElements) {
|
|
return null;
|
|
}
|
|
|
|
return analysisResponses.map((r) => ({
|
|
...r,
|
|
elements: analysisResponseElements.filter(
|
|
(e) => e.analysis_response_id === r.id,
|
|
),
|
|
}));
|
|
}
|
|
|
|
async hasAccountTeamMembership(accountId?: string) {
|
|
if (!accountId) {
|
|
return false;
|
|
}
|
|
|
|
const { count, error } = await this.client
|
|
.schema('medreport')
|
|
.from('accounts_memberships')
|
|
.select('account_id', { count: 'exact', head: true })
|
|
.eq('account_id', accountId);
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return (count ?? 0) > 0;
|
|
}
|
|
|
|
async fetchBmiThresholds() {
|
|
// Fetch BMI
|
|
const { data, error } = await this.client
|
|
.schema('medreport')
|
|
.from('bmi_thresholds')
|
|
.select(
|
|
'age_min,age_max,underweight_max,normal_min,normal_max,overweight_min,strong_min,obesity_min',
|
|
)
|
|
.order('age_min', { ascending: true });
|
|
|
|
if (error) {
|
|
console.error('Error fetching BMI thresholds:', error);
|
|
throw error;
|
|
}
|
|
return data;
|
|
}
|
|
}
|
|
|
|
export function createAccountsApi(client: SupabaseClient<Database>) {
|
|
return new AccountsApi(client);
|
|
}
|