mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 12:15:23 +02:00
138 lines
3.6 KiB
TypeScript
138 lines
3.6 KiB
TypeScript
|
|
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
|
import { VendorDailyRow } from '../types';
|
|
|
|
export type { VendorDailyRow };
|
|
|
|
const supabaseUrl = process.env.SUPABASE_URL || '';
|
|
const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || '';
|
|
|
|
let _client: SupabaseClient | null = null;
|
|
|
|
const getClient = (): SupabaseClient => {
|
|
if (!_client) {
|
|
if (!supabaseUrl || !supabaseAnonKey) {
|
|
throw new Error('Supabase credentials not configured. Add SUPABASE_URL and SUPABASE_ANON_KEY to environment variables.');
|
|
}
|
|
// Disable auth persistence to avoid LockManager timeout issues
|
|
_client = createClient(supabaseUrl, supabaseAnonKey, {
|
|
auth: {
|
|
autoRefreshToken: false,
|
|
persistSession: false,
|
|
detectSessionInUrl: false,
|
|
storage: false as any
|
|
}
|
|
});
|
|
}
|
|
return _client;
|
|
};
|
|
|
|
export interface VendorFilters {
|
|
markets?: string[];
|
|
tags?: string[];
|
|
asins?: string[];
|
|
dateFrom?: string;
|
|
dateTo?: string;
|
|
years?: number[];
|
|
}
|
|
|
|
export const fetchVendorData = async (filters: VendorFilters): Promise<VendorDailyRow[]> => {
|
|
const allRows: VendorDailyRow[] = [];
|
|
let offset = 0;
|
|
const pageSize = 1000;
|
|
let hasMore = true;
|
|
|
|
while (hasMore) {
|
|
let query = getClient()
|
|
.from('vendor_daily_data')
|
|
.select('*')
|
|
.order('date', { ascending: true })
|
|
.range(offset, offset + pageSize - 1);
|
|
|
|
if (filters.markets?.length) {
|
|
query = query.in('market', filters.markets);
|
|
}
|
|
if (filters.tags?.length) {
|
|
// Use ilike for partial match on tags
|
|
query = query.or(filters.tags.map(t => `tags.ilike.%${t}%`).join(','));
|
|
}
|
|
if (filters.asins?.length) {
|
|
query = query.in('asin', filters.asins);
|
|
}
|
|
if (filters.dateFrom) {
|
|
query = query.gte('date', filters.dateFrom);
|
|
}
|
|
if (filters.dateTo) {
|
|
query = query.lte('date', filters.dateTo);
|
|
}
|
|
if (filters.years?.length) {
|
|
// Filter by year using date range
|
|
const yearFilters = filters.years.map(y => ({
|
|
from: `${y}-01-01`,
|
|
to: `${y}-12-31`
|
|
}));
|
|
const dateConditions = yearFilters.flatMap(f => [
|
|
`date.gte.${f.from}`,
|
|
`date.lte.${f.to}`
|
|
]);
|
|
// Build OR condition for multiple years
|
|
query = query.or(
|
|
filters.years.map(y => `and(date.gte.${y}-01-01,date.lte.${y}-12-31)`).join(',')
|
|
);
|
|
}
|
|
|
|
const { data, error } = await query;
|
|
if (error) throw error;
|
|
if (data) {
|
|
allRows.push(...data);
|
|
hasMore = data.length === pageSize;
|
|
offset += pageSize;
|
|
} else {
|
|
hasMore = false;
|
|
}
|
|
}
|
|
|
|
return allRows;
|
|
};
|
|
|
|
export const fetchVendorFilterOptions = async (): Promise<{
|
|
markets: string[];
|
|
tags: string[];
|
|
dateRange: { min: string; max: string } | null;
|
|
}> => {
|
|
const client = getClient();
|
|
|
|
const { data: marketData } = await client
|
|
.from('vendor_daily_data')
|
|
.select('market')
|
|
.limit(100000);
|
|
|
|
const { data: tagData } = await client
|
|
.from('vendor_daily_data')
|
|
.select('tags')
|
|
.limit(100000);
|
|
|
|
const { data: dateMin } = await client
|
|
.from('vendor_daily_data')
|
|
.select('date')
|
|
.order('date', { ascending: true })
|
|
.limit(1);
|
|
|
|
const { data: dateMax } = await client
|
|
.from('vendor_daily_data')
|
|
.select('date')
|
|
.order('date', { ascending: false })
|
|
.limit(1);
|
|
|
|
const markets = [...new Set((marketData || []).map((r: any) => r.market as string))].sort();
|
|
const tags = [...new Set((tagData || []).map((r: any) => r.tags as string).filter(Boolean))].sort();
|
|
|
|
return {
|
|
markets,
|
|
tags,
|
|
dateRange: dateMin?.[0] && dateMax?.[0]
|
|
? { min: dateMin[0].date, max: dateMax[0].date }
|
|
: null,
|
|
};
|
|
};
|