283 lines
6.1 KiB
TypeScript
283 lines
6.1 KiB
TypeScript
export interface Store {
|
|
id: number;
|
|
created_at: string;
|
|
name: string;
|
|
logo_url?: string | null;
|
|
}
|
|
|
|
export interface Flyer {
|
|
id: number;
|
|
created_at: string;
|
|
file_name: string;
|
|
image_url: string;
|
|
checksum?: string;
|
|
store_id?: number;
|
|
valid_from?: string | null;
|
|
valid_to?: string | null;
|
|
store_address?: string | null;
|
|
store?: Store;
|
|
}
|
|
|
|
export interface UnitPrice {
|
|
value: number;
|
|
unit: string; // e.g., 'g', 'kg', 'ml', 'l', 'oz', 'lb', 'each'
|
|
}
|
|
|
|
export interface FlyerItem {
|
|
id?: number;
|
|
flyer_id?: number;
|
|
created_at?: string;
|
|
item: string;
|
|
price_display: string;
|
|
price_in_cents: number | null;
|
|
quantity: string;
|
|
quantity_num?: number | null;
|
|
master_item_id?: number;
|
|
master_item_name?: string | null;
|
|
category_id?: number | null;
|
|
category_name?: string | null;
|
|
unit_price?: UnitPrice | null;
|
|
product_id?: number | null;
|
|
}
|
|
|
|
export interface MasterGroceryItem {
|
|
id: number;
|
|
created_at: string;
|
|
name: string;
|
|
category_id?: number | null;
|
|
category_name?: string | null;
|
|
}
|
|
|
|
export interface Brand {
|
|
id: number;
|
|
name: string;
|
|
}
|
|
|
|
export interface Product {
|
|
id: number;
|
|
master_item_id: number;
|
|
brand_id?: number | null;
|
|
name: string;
|
|
description?: string | null;
|
|
size?: string | null;
|
|
upc_code?: string | null;
|
|
}
|
|
|
|
export interface DealItem {
|
|
item: string;
|
|
price_display: string;
|
|
price_in_cents: number | null;
|
|
quantity: string;
|
|
storeName: string;
|
|
master_item_name?: string | null;
|
|
unit_price?: UnitPrice | null;
|
|
}
|
|
|
|
// User-specific types
|
|
export interface Profile {
|
|
id: string; // UUID
|
|
updated_at?: string;
|
|
full_name?: string | null;
|
|
avatar_url?: string | null;
|
|
preferences?: {
|
|
darkMode?: boolean;
|
|
unitSystem?: 'metric' | 'imperial';
|
|
} | null;
|
|
}
|
|
|
|
export interface UserAlert {
|
|
id: number;
|
|
user_watched_item_id: number;
|
|
alert_type: 'PRICE_BELOW' | 'PERCENT_OFF_AVERAGE';
|
|
threshold_value: number;
|
|
is_active: boolean;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface Notification {
|
|
id: number;
|
|
user_id: string; // UUID
|
|
content: string;
|
|
link_url?: string | null;
|
|
is_read: boolean;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface ShoppingList {
|
|
id: number;
|
|
user_id: string; // UUID
|
|
name: string;
|
|
created_at: string;
|
|
items: ShoppingListItem[]; // Nested items
|
|
}
|
|
|
|
export interface ShoppingListItem {
|
|
id: number;
|
|
shopping_list_id: number;
|
|
master_item_id?: number | null;
|
|
custom_item_name?: string | null;
|
|
quantity: number;
|
|
is_purchased: boolean;
|
|
added_at: string;
|
|
// Joined data for display
|
|
master_item?: {
|
|
name: string;
|
|
} | null;
|
|
}
|
|
|
|
|
|
export interface SuggestedCorrection {
|
|
id: number;
|
|
flyer_item_id: number;
|
|
user_id: string; // UUID
|
|
correction_type: string; // e.g., 'WRONG_PRICE', 'INCORRECT_ITEM_LINK'
|
|
suggested_value: string;
|
|
status: 'pending' | 'approved' | 'rejected';
|
|
created_at: string;
|
|
reviewed_notes?: string | null;
|
|
reviewed_at?: string | null;
|
|
}
|
|
|
|
export interface UserSubmittedPrice {
|
|
id: number;
|
|
user_id: string; // UUID
|
|
master_item_id: number;
|
|
store_id: number;
|
|
price_in_cents: number;
|
|
photo_url?: string | null;
|
|
upvotes: number;
|
|
downvotes: number;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface ItemPriceHistory {
|
|
id: number;
|
|
master_item_id: number;
|
|
summary_date: string; // DATE
|
|
min_price_in_cents?: number | null;
|
|
max_price_in_cents?: number | null;
|
|
avg_price_in_cents?: number | null;
|
|
data_points_count: number;
|
|
}
|
|
|
|
export interface MasterItemAlias {
|
|
id: number;
|
|
master_item_id: number;
|
|
alias: string;
|
|
}
|
|
|
|
export interface Recipe {
|
|
id: number;
|
|
user_id?: string | null; // UUID
|
|
name: string;
|
|
description?: string | null;
|
|
instructions?: string | null;
|
|
prep_time_minutes?: number | null;
|
|
cook_time_minutes?: number | null;
|
|
servings?: number | null;
|
|
photo_url?: string | null;
|
|
calories_per_serving?: number | null;
|
|
protein_grams?: number | null;
|
|
fat_grams?: number | null;
|
|
carb_grams?: number | null;
|
|
avg_rating: number;
|
|
rating_count: number;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface RecipeIngredient {
|
|
id: number;
|
|
recipe_id: number;
|
|
master_item_id: number;
|
|
quantity: number;
|
|
unit: string;
|
|
}
|
|
|
|
export interface Tag {
|
|
id: number;
|
|
name: string;
|
|
}
|
|
|
|
export interface RecipeTag {
|
|
recipe_id: number;
|
|
tag_id: number;
|
|
}
|
|
|
|
export interface RecipeRating {
|
|
id: number;
|
|
recipe_id: number;
|
|
user_id: string; // UUID
|
|
rating: number;
|
|
comment?: string | null;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface MenuPlan {
|
|
id: number;
|
|
user_id: string; // UUID
|
|
name: string;
|
|
start_date: string; // DATE
|
|
end_date: string; // DATE
|
|
created_at: string;
|
|
}
|
|
|
|
export interface PlannedMeal {
|
|
id: number;
|
|
menu_plan_id: number;
|
|
recipe_id: number;
|
|
plan_date: string; // DATE
|
|
meal_type: string;
|
|
servings_to_cook?: number | null;
|
|
}
|
|
|
|
export interface PantryItem {
|
|
id: number;
|
|
user_id: string; // UUID
|
|
master_item_id: number;
|
|
quantity: number;
|
|
unit?: string | null;
|
|
best_before_date?: string | null; // DATE
|
|
updated_at: string;
|
|
}
|
|
|
|
export interface StoreLocation {
|
|
id: number;
|
|
store_id: number;
|
|
address: string;
|
|
city?: string | null;
|
|
province_state?: string | null;
|
|
postal_code?: string | null;
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
location?: any; // Represents PostGIS GEOGRAPHY(Point, 4326)
|
|
}
|
|
|
|
export interface FlyerLocation {
|
|
flyer_id: number;
|
|
store_location_id: number;
|
|
}
|
|
|
|
export enum AnalysisType {
|
|
QUICK_INSIGHTS = 'QUICK_INSIGHTS',
|
|
DEEP_DIVE = 'DEEP_DIVE',
|
|
WEB_SEARCH = 'WEB_SEARCH',
|
|
PLAN_TRIP = 'PLAN_TRIP',
|
|
GENERATE_IMAGE = 'GENERATE_IMAGE',
|
|
}
|
|
|
|
export type StageStatus = 'pending' | 'in-progress' | 'completed' | 'error';
|
|
|
|
export interface ProcessingStage {
|
|
name: string;
|
|
status: StageStatus;
|
|
detail?: string;
|
|
critical?: boolean;
|
|
progress?: { current: number; total: number } | null;
|
|
}
|
|
|
|
export const CATEGORIES = [
|
|
'Fruits & Vegetables', 'Meat & Seafood', 'Dairy & Eggs', 'Bakery & Bread',
|
|
'Pantry & Dry Goods', 'Beverages', 'Frozen Foods', 'Snacks', 'Household & Cleaning',
|
|
'Personal Care & Health', 'Baby & Child', 'Pet Supplies', 'Deli & Prepared Foods',
|
|
'Canned Goods', 'Condiments & Spices', 'Breakfast & Cereal', 'Organic',
|
|
'International Foods', 'Other/Miscellaneous'
|
|
]; |