category icons
This commit is contained in:
@@ -2,8 +2,367 @@ import type { EntityManager } from '@mikro-orm/core';
|
||||
import { Category } from '../modules/foods/entities/category.entity';
|
||||
import type { Restaurant } from '../modules/restaurants/entities/restaurant.entity';
|
||||
import { categoriesData } from './data/categories.data';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
interface IconData {
|
||||
index: number;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export class CategoriesSeeder {
|
||||
private icons: IconData[] = [];
|
||||
private iconIndex = 0;
|
||||
|
||||
private loadIcons(): void {
|
||||
if (this.icons.length > 0) return;
|
||||
|
||||
const iconsPath = path.join(process.cwd(), 'dump', 'named_icons.csv');
|
||||
const csvContent = fs.readFileSync(iconsPath, 'utf-8');
|
||||
const lines = csvContent.split('\n').slice(1); // Skip header
|
||||
|
||||
this.icons = lines
|
||||
.filter(line => line.trim())
|
||||
.map(line => {
|
||||
const parts = line.split(',');
|
||||
return {
|
||||
index: parseInt(parts[0].replace(/"/g, '')),
|
||||
name: parts[1].replace(/"/g, ''),
|
||||
url: parts[2].replace(/"/g, '')
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private getIconForCategory(categoryTitle: string): string | undefined {
|
||||
this.loadIcons();
|
||||
|
||||
if (this.icons.length === 0) return undefined;
|
||||
|
||||
// Create a mapping of keywords to icon names
|
||||
const iconMapping: Record<string, string[]> = {
|
||||
// Pizza
|
||||
'پیتزا': ['pizza'],
|
||||
|
||||
// Pasta
|
||||
'پاستا': ['fast-food'],
|
||||
|
||||
// Steak
|
||||
'استیک': ['meat', 'meat 2'],
|
||||
|
||||
// Burger
|
||||
'برگر': ['hanburger'],
|
||||
|
||||
// Salad
|
||||
'سالاد': ['broccoli'],
|
||||
|
||||
// Appetizer/Appetizers
|
||||
'پیش غذا': ['chicken', 'fast-food'],
|
||||
|
||||
// Main Course
|
||||
'غذای اصلی': ['hanburger', 'meat'],
|
||||
'خوراک': ['hanburger', 'meat'],
|
||||
'ناهار': ['hanburger', 'meat'],
|
||||
|
||||
// Sandwich
|
||||
'ساندویچ': ['bread'],
|
||||
|
||||
// Fried foods
|
||||
'سوخاری': ['chicken', 'fast-food'],
|
||||
|
||||
// Cake/Dessert
|
||||
'کیک': ['cookie1', 'cookie2'],
|
||||
'دسر': ['cookie1', 'cookie2'],
|
||||
|
||||
// Ice Cream
|
||||
'بستنی': ['ice cream', 'ice cream 3'],
|
||||
'آیس': ['ice cream'],
|
||||
|
||||
// Breakfast
|
||||
'صبحانه': ['bread', 'egg'],
|
||||
|
||||
// Drinks - general
|
||||
'نوشیدنی': ['drink', 'drink2', 'bottle1', 'bottle2'],
|
||||
|
||||
// Coffee
|
||||
'قهوه': ['drink', 'drink2'],
|
||||
'اسپرسو': ['drink'],
|
||||
'کافی': ['drink'],
|
||||
|
||||
// Tea
|
||||
'چای': ['drink', 'drink2'],
|
||||
'دمنوش': ['drink', 'drink2'],
|
||||
|
||||
// Cocktail/Mocktail
|
||||
'ماکتل': ['wine glass', 'wine glass 2'],
|
||||
'موهیتو': ['wine glass'],
|
||||
|
||||
// Shake/Smoothie
|
||||
'شیک': ['ice cream'],
|
||||
'اسموتی': ['ice cream'],
|
||||
|
||||
// Juice
|
||||
'آبمیوه': ['juice', 'juice2', 'juice3'],
|
||||
'ویتامینه': ['juice', 'juice2', 'juice3'],
|
||||
|
||||
// Hot Dog
|
||||
'هات داگ': ['hot dog'],
|
||||
|
||||
// BBQ
|
||||
'باربیکیو': ['barbecue', 'barbeque2'],
|
||||
|
||||
// BBQ Skewers
|
||||
'کباب': ['skewer'],
|
||||
|
||||
// Soup
|
||||
'آش': ['jar', 'dish'],
|
||||
|
||||
// Bread
|
||||
'نان': ['bread'],
|
||||
|
||||
// Donut
|
||||
'دونات': ['donuts'],
|
||||
|
||||
// Fish
|
||||
'دریایی': ['fish'],
|
||||
'ماهی': ['fish'],
|
||||
|
||||
// Chicken
|
||||
'مرغ': ['chicken'],
|
||||
|
||||
// Egg
|
||||
'تخم': ['egg', 'fried egg'],
|
||||
|
||||
// Vegetable
|
||||
'سبزی': ['broccoli'],
|
||||
|
||||
// Fruit
|
||||
'میوه': ['strawberry', 'cherry', 'grape', 'watermelon'],
|
||||
|
||||
// Milk
|
||||
'شیر': ['bottle1'], // Note: there's no milk icon, using a generic one
|
||||
|
||||
// Cookie
|
||||
'کوکی': ['cookie1', 'cookie2'],
|
||||
|
||||
// French Fries
|
||||
'سیب زمینی': ['french fries'],
|
||||
|
||||
// Fast Food
|
||||
'فست فود': ['fast-food'],
|
||||
|
||||
// Bakery
|
||||
'نانوایی': ['bread'],
|
||||
|
||||
// Ice Tea
|
||||
'آیس تی': ['drink', 'drink2'],
|
||||
|
||||
// Hot Pot
|
||||
'حلیم': ['jar', 'dish'],
|
||||
|
||||
// Taco
|
||||
'تاکو': ['taco'],
|
||||
|
||||
// Nachos
|
||||
'ناچو': ['fast-food'],
|
||||
|
||||
// Sushi
|
||||
'سوشی': ['fish'],
|
||||
|
||||
// Dumpling
|
||||
'غالوش': ['basket'],
|
||||
|
||||
// Tempura
|
||||
'تمپورا': ['fish'],
|
||||
|
||||
// Tofu
|
||||
'توفو': ['jar'],
|
||||
|
||||
// Bibimbap
|
||||
'بیبیمباب': ['fast-food'],
|
||||
|
||||
// Boba
|
||||
'بوبا': ['drink', 'drink2'],
|
||||
|
||||
// Fish and Chips
|
||||
'فیش اند چیپس': ['fish', 'french fries'],
|
||||
|
||||
// Focaccia
|
||||
'فوکاچیا': ['bread'],
|
||||
|
||||
// Martini
|
||||
'مارتینی': ['wine glass'],
|
||||
|
||||
// Mochi
|
||||
'موچی': ['donuts'],
|
||||
|
||||
// Pancake
|
||||
'پن کیک': ['bread'],
|
||||
|
||||
// Quesadilla
|
||||
'کوئزادیا': ['quesadilla'],
|
||||
|
||||
// Origami
|
||||
'اوريگامي': ['basket'],
|
||||
|
||||
// Pudding
|
||||
'پودینگ': ['jar'],
|
||||
|
||||
// Sweet
|
||||
'شیرین': ['candy'],
|
||||
|
||||
// Crossant
|
||||
'کروسان': ['bread'],
|
||||
|
||||
// Bio
|
||||
'بیو': ['broccoli'],
|
||||
|
||||
// Lemon
|
||||
'لیمو': ['lemon'],
|
||||
|
||||
// Candy
|
||||
'شیرینی': ['candy'],
|
||||
|
||||
// Lollipop
|
||||
'آب نبات': ['lollipop'],
|
||||
|
||||
// Cherry
|
||||
'گیلاس': ['cherry'],
|
||||
|
||||
// Strawberry
|
||||
'توت فرنگی': ['strawberry'],
|
||||
|
||||
// Watermelon
|
||||
'هندوانه': ['watermelon'],
|
||||
|
||||
// Avocado
|
||||
'آووکادو': ['avocado'],
|
||||
|
||||
// Banana
|
||||
'موز': ['banana'],
|
||||
|
||||
// Carrot
|
||||
'هویج': ['carrot'],
|
||||
|
||||
// Cheese
|
||||
'پنیر': ['cheese', 'cheese2'],
|
||||
|
||||
// Tomato
|
||||
'گوجه': ['tomato'], // Note: no tomato icon
|
||||
|
||||
// Onion
|
||||
'پیاز': ['onion'],
|
||||
|
||||
// Olive
|
||||
'زیتون': ['olive'],
|
||||
|
||||
// Nuts
|
||||
'آجیل': ['nuts'],
|
||||
|
||||
// Scales (for weighing)
|
||||
'ترازو': ['scales'],
|
||||
|
||||
// Whisk
|
||||
'همزن': ['whisk', 'whisk'],
|
||||
|
||||
// Mortar
|
||||
'هاون': ['mortar'],
|
||||
|
||||
// Rolling pin
|
||||
'والت': ['rolling pin'],
|
||||
|
||||
// Knife
|
||||
'چاقو': ['knife'],
|
||||
|
||||
// Baby food
|
||||
'کودک': ['baby bottle', 'baby bottle', 'baby pacifier'],
|
||||
|
||||
// Hat (chef hat)
|
||||
'کلاه': ['hat robe', 'hat robe 2'],
|
||||
|
||||
// Bread
|
||||
'نان': ['bread', 'loaf of bread', 'loaf of bread 2'],
|
||||
|
||||
// Candle (birthday)
|
||||
'شمع': ['candle'],
|
||||
|
||||
// Fire
|
||||
'آتش': ['fire'],
|
||||
|
||||
// Refrigerator
|
||||
'یخچال': ['refrigerator'],
|
||||
|
||||
// Kitchen stove
|
||||
'اجاق': ['kitchen stove'],
|
||||
|
||||
// Mixer
|
||||
'میکسر': ['mixer'],
|
||||
|
||||
// Jar
|
||||
'شیشه': ['jar'],
|
||||
|
||||
// Jelly
|
||||
'ژله': ['jelly'],
|
||||
|
||||
// Soap
|
||||
'صابون': ['soap'],
|
||||
|
||||
// Dish
|
||||
'ظرف': ['dish'],
|
||||
|
||||
// Basket
|
||||
'سبد': ['basket'],
|
||||
|
||||
// Salt
|
||||
'نمک': ['solt'],
|
||||
|
||||
// Eggplant
|
||||
'بادمجان': ['egg plant'],
|
||||
|
||||
// Wine
|
||||
'شراب': ['wine glass', 'wine glass 2', 'wine glass 3'],
|
||||
|
||||
// Plate
|
||||
'بشقاب': ['dish'],
|
||||
|
||||
// Fork and knife
|
||||
'چنگال': ['spoon and fork 1', 'spoon and fork 2', 'spoon and knife', 'fork and knife'],
|
||||
|
||||
// Toast
|
||||
'تست': ['toast']
|
||||
};
|
||||
|
||||
// Find matching icon based on category title
|
||||
for (const [keyword, iconNames] of Object.entries(iconMapping)) {
|
||||
if (categoryTitle.includes(keyword)) {
|
||||
// Find the first available icon from the list
|
||||
for (const iconName of iconNames) {
|
||||
const icon = this.icons.find(i => i.name.toLowerCase() === iconName.toLowerCase());
|
||||
if (icon) {
|
||||
return icon.url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: try to find any icon that might be related by partial name match
|
||||
for (const icon of this.icons) {
|
||||
const lowerTitle = categoryTitle.toLowerCase();
|
||||
const lowerIconName = icon.name.toLowerCase();
|
||||
|
||||
// Check if any word in the category title matches part of the icon name
|
||||
const titleWords = lowerTitle.split(/\s+/);
|
||||
for (const word of titleWords) {
|
||||
if (word.length > 2 && lowerIconName.includes(word)) {
|
||||
return icon.url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Final fallback: return a random icon
|
||||
const randomIndex = Math.floor(Math.random() * this.icons.length);
|
||||
return this.icons[randomIndex]?.url;
|
||||
}
|
||||
async run(em: EntityManager, restaurantsMap: Map<string, Restaurant>): Promise<Map<string, Category>> {
|
||||
const categoriesMap = new Map<string, Category>();
|
||||
|
||||
@@ -17,10 +376,12 @@ export class CategoriesSeeder {
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
const avatarUrl = this.getIconForCategory(catData.title);
|
||||
const category = em.create(Category, {
|
||||
title: catData.title,
|
||||
restaurant,
|
||||
isActive: true,
|
||||
avatarUrl,
|
||||
});
|
||||
em.persist(category);
|
||||
categoriesMap.set(`${catData.restaurantSlug}-${catData.title}`, category);
|
||||
|
||||
+3096
-3096
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user