feat: initial commit - Band Management application

This commit is contained in:
2026-01-06 03:11:46 +01:00
commit 34e12e00b3
24543 changed files with 3991790 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
import { createMongoAbility } from '@casl/ability'
export const ability = createMongoAbility()

View File

@@ -0,0 +1,3 @@
import { useAbility as useCaslAbility } from '@casl/vue'
export const useAbility = () => useCaslAbility()

View File

@@ -0,0 +1,11 @@
import { createMongoAbility } from '@casl/ability'
import { abilitiesPlugin } from '@casl/vue'
export default defineNuxtPlugin(nuxtApp => {
const userAbilityRules = useCookie('userAbilityRules')
const initialAbility = createMongoAbility(userAbilityRules.value ?? [])
nuxtApp.vueApp.use(abilitiesPlugin, initialAbility, {
useGlobalProperties: true,
})
})

View File

@@ -0,0 +1,237 @@
{
"UI Elements": "عناصر واجهة المستخدم",
"Forms & Tables": "النماذج والجداول",
"Pages": "الصفحات",
"Charts & Maps": "الرسوم البيانية والخرائط",
"Others": "آحرون",
"Typography": "الطباعة",
"Cards": "البطاقات",
"Basic": "أساسي",
"Advance": "يتقدم",
"Widgets": "الحاجيات",
"Actions": "أجراءات",
"Components": "عناصر",
"Alert": "انذار",
"Close Alert": "أغلق التنبيه",
"Avatar": "الصورة الرمزية",
"Badge": "شارة",
"Button": "زر",
"Calendar": "تقويم",
"Kanban": "مجلس كانبان",
"Image": "صورة",
"Pagination": "ترقيم الصفحات",
"Progress Circular": "تقدم التعميم",
"Progress Linear": "تقدم خطي",
"Autocomplete": "الإكمال التلقائي",
"Tooltip": "تلميح",
"Slider": "المنزلق",
"Date Time Picker": "منتقي التاريخ والوقت",
"Select": "يختار",
"Switch": "يُحوّل",
"Checkbox": "خانة اختيار",
"Radio": "مذياع",
"Textarea": "تيكستاريا",
"Rating": "تقييم",
"File Input": "إدخال الملف",
"Otp Input": "إدخال أوتب",
"Form Layout": "تخطيط النموذج",
"Form Validation": "التحقق من صحة النموذج",
"Charts": "الرسوم البيانية",
"Apex Chart": "مخطط أبيكس",
"Chartjs": "تشارتجس",
"Account Settings": "إعدادت الحساب",
"User Profile": "ملف تعريفي للمستخدم",
"FAQ": "التعليمات",
"Dialog Examples": "أمثلة على الحوار",
"Pricing": "التسعير",
"List": "قائمة",
"Edit": "يحرر",
"Nav Levels": "مستويات التنقل",
"Level 2.1": "المستوى 2.1",
"Level 2.2": "مستوى 2.2",
"Level 3.1": "المستوى 3.1",
"Level 3.2": "المستوى 3.2",
"Raise Support": "رفع الدعم",
"Documentation": "توثيق",
"Dashboards": "لوحات القيادة",
"Apps & Pages": "التطبيقات والصفحات",
"Email": "البريد الإلكتروني",
"Chat": "دردشة",
"Invoice": "فاتورة",
"Preview": "معاينة",
"Add": "يضيف",
"User": "المستعمل",
"View": "رأي",
"Login v1": "تسجيل الدخول v1",
"Login v2": "تسجيل الدخول v2",
"Login": "تسجيل الدخول",
"Register v1": "تسجيل v1",
"Register v2": "تسجيل v2",
"Register": "تسجيل",
"Forget Password v1": "نسيت كلمة المرور v1",
"Forget Password v2": "نسيت كلمة المرور v2",
"Forgot Password v1": "نسيت كلمة المرور v1",
"Forgot Password v2": "نسيت كلمة المرور v2",
"Forgot Password": "نسيت كلمة المرور",
"Reset Password v1": "إعادة تعيين كلمة المرور v1",
"Reset Password v2": "إعادة تعيين كلمة المرور v2",
"Reset Password": "إعادة تعيين كلمة المرور",
"Miscellaneous": "متفرقات",
"Coming Soon": "قريبا",
"Not Authorized": "غير مخول",
"Under Maintenance": "تحت الصيانة",
"Error": "خطأ",
"Statistics": "إحصائيات",
"Analytics": "تحليلات",
"Access Control": "صلاحية التحكم صلاحية الدخول",
"User Interface": "واجهة المستخدم",
"CRM": "سي آر إم",
"Icons": "أيقونات",
"Chip": "رقاقة",
"Dialog": "حوار",
"Expansion Panel": "لوحة التوسع",
"Combobox": "صندوق التحرير",
"Textfield": "مجال التحرير مكان كتابة النص",
"Range Slider": "نطاق المنزلق",
"Menu": "قائمة الطعام",
"Snackbar": "مطعم الوجبات الخفيفة",
"Tabs": "نوافذ التبويب",
"Form Elements": "عناصر النموذج",
"Form Layouts": "تخطيطات النموذج",
"Authentication": "المصادقة",
"Page Not Found - 404": "الصفحة غير موجودة - 404",
"Not Authorized - 401": "غير مصرح - 401",
"Server Error - 500": "خطأ في الخادم - 500",
"2": "2",
"Forms": "نماذج",
"Timeline": "الجدول الزمني",
"Disabled Menu": "قائمة المعوقين",
"Help Center": "مركز المساعدة",
"Verify Email": "التحقق من البريد الإلكتروني",
"Verify Email v1": "تحقق من البريد الإلكتروني v1",
"Verify Email v2": "تحقق من البريد الإلكتروني v2",
"Two Steps": "خطوتين",
"Two Steps v1": "خطوتين v1.0",
"Two Steps v2": "خطوتين v2.0",
"Custom Input": "إدخال مخصص",
"Extensions": "ملحقات",
"Tour": "رحلة",
"Register Multi-Steps": "تسجيل خطوات متعددة",
"Wizard Examples": "أمثلة المعالج",
"Checkout": "الدفع",
"Create Deal": "إنشاء صفقة",
"Property Listing": "قائمة الممتلكات ",
"Roles & Permissions": "الأدوار والأذونات",
"Roles": "الأدوار",
"Permissions": "الأذونات",
"Simple Table": "جدول بسيط",
"Tables": "الجداول",
"DataTable": "جدول البيانات",
"Data Table": "جدول البيانات",
"Apps": "التطبيقات",
"Misc": "متفرقات",
"Wizard Pages": "صفحات المعالج",
"eCommerce": "التجارة الإلكترونية",
"Form Wizard": "معالج النموذج",
"Numbered": "مرقم",
"ecommerce": "التجارة الإلكترونية",
"Ecommerce": "التجارة الإلكترونية",
"Product": "المنتج",
"Category": "الفئة",
"Order": "طلب",
"Details": "تفاصيل",
"Customer": "الزبون",
"Manage Review": "إدارة المراجعة",
"Referrals": "الإحالات",
"Settings": "الإعدادات",
"Course Details": "تفاصيل الدورة التدريبية",
"My Course": "دورتي",
"Overview": "نظرة عامة",
"Academy": "أكاديمية",
"Logistics": "الخدمات اللوجستية",
"Dashboard": "لوحة القيادة",
"Fleet": "الأسطول",
"Editors": "المحررين",
"Front Pages": "الصفحات الأمامية",
"Landing": "المقصودة",
"checkout": "الدفع",
"Payment": "دفع",
"Swiper": "المنزلق",
"Shortcut": "اختصار",
"Appointments": "المواعيد",
"Invoice App": "تطبيق الفاتورة",
"Manage Accounts": "إدارة الحسابات",
"Users": "المستخدمون",
"Manage Users": "إدارة المستخدمين",
"Role Management": "إدارة الأدوار",
"Permission": "إذن",
"Dashboard Analytics": "تحليلات لوحة القيادة",
"3": "3",
"5": "5",
"10": "10",
"20": "20",
"25": "25",
"50": "50",
"100": "100",
"$vuetify": {
"badge": "شارة",
"noDataText": "لا تتوافر بيانات",
"close": "قريب",
"open": "افتح",
"loading": "جار التحميل",
"carousel": {
"ariaLabel": {
"delimiter": "تحديد"
}
},
"colorPicker": {
"ariaLabel": {
"hueSlider": "شريط تدرج اللون",
"eyedropper": "قطارة",
"hexInput": "إدخال هيكس"
}
},
"dataFooter": {
"itemsPerPageText": "مواد لكل صفحة:",
"itemsPerPageAll": "الجميع",
"pageText": "{0} - {1} من {2}",
"firstPage": "الصفحة الأولى",
"prevPage": "الصفحة السابقة",
"nextPage": "الصفحة التالية",
"lastPage": "آخر صفحة"
},
"pagination": {
"ariaLabel": {
"root": "جذر",
"previous": "السابق",
"first": "أولاً",
"last": "آخر",
"next": "التالي",
"currentPage": "الصفحه الحاليه",
"page": "صفحة"
}
},
"input": {
"clear": "صافي",
"appendAction": "إلحاق الإجراء",
"prependAction": "قبل العمل",
"otp": "أوتب"
},
"fileInput": {
"counterSize": "حجم العداد"
},
"rating": {
"ariaLabel": {
"item": "العنصر"
}
},
"video": {
"seek": "يطلب",
"play": "يلعب",
"pause": "يوقف",
"showVolume": "إظهار الحجم",
"enterFullscreen": "أدخل ملء الشاشة",
"volume": "مقدار"
}
}
}

View File

@@ -0,0 +1,237 @@
{
"UI Elements": "UI Elements",
"Forms & Tables": "Forms & Tables",
"Pages": "Pages",
"Charts & Maps": "Charts & Maps",
"Others": "Others",
"Typography": "Typography",
"Cards": "Cards",
"Basic": "Basic",
"Advance": "Advance",
"Widgets": "Widgets",
"Components": "Components",
"Alert": "Alert",
"Close Alert": "Close Alert",
"Avatar": "Avatar",
"Badge": "Badge",
"Button": "Button",
"Calendar": "Calendar",
"Kanban": "Kanban",
"Image": "Image",
"Pagination": "Pagination",
"Progress Circular": "Progress Circular",
"Progress Linear": "Progress Linear",
"Autocomplete": "Autocomplete",
"Tooltip": "Tooltip",
"Slider": "Slider",
"Date Time Picker": "Date Time Picker",
"Select": "Select",
"Switch": "Switch",
"Checkbox": "Checkbox",
"Radio": "Radio",
"Textarea": "Textarea",
"Rating": "Rating",
"File Input": "File Input",
"Otp Input": "Otp Input",
"Form Layout": "Form Layout",
"Form Validation": "Form Validation",
"Charts": "Charts",
"Apex Chart": "Apex Chart",
"Chartjs": "Chartjs",
"Account Settings": "Account Settings",
"User Profile": "User Profile",
"FAQ": "FAQ",
"Dialog Examples": "Dialog Examples",
"Pricing": "Pricing",
"List": "List",
"Edit": "Edit",
"Nav Levels": "Nav Levels",
"Level 2.1": "Level 2.1",
"Level 2.2": "Level 2.2",
"Level 3.1": "Level 3.1",
"Level 3.2": "Level 3.2",
"Raise Support": "Raise Support",
"Documentation": "Documentation",
"Dashboards": "Dashboards",
"Analytics": "Analytics",
"Apps & Pages": "Apps & Pages",
"Email": "Email",
"Chat": "Chat",
"Invoice": "Invoice",
"Preview": "Preview",
"Add": "Add",
"User": "User",
"View": "View",
"Login v1": "Login v1",
"Login v2": "Login v2",
"Login": "Login",
"Register v1": "Register v1",
"Register v2": "Register v2",
"Register": "Register",
"Forget Password v1": "Forget Password v1",
"Forget Password v2": "Forget Password v2",
"Forgot Password v1": "Forgot Password v1",
"Forgot Password v2": "Forgot Password v2",
"Forgot Password": "Forgot Password",
"Reset Password v1": "Reset Password v1",
"Reset Password v2": "Reset Password v2",
"Reset Password": "Reset Password",
"Miscellaneous": "Miscellaneous",
"Coming Soon": "Coming Soon",
"Not Authorized": "Not Authorized",
"Under Maintenance": "Under Maintenance",
"Error": "Error",
"Statistics": "Statistics",
"Actions": "Actions",
"Access Control": "Access Control",
"User Interface": "User Interface",
"CRM": "CRM",
"eCommerce": "eCommerce",
"Icons": "Icons",
"Chip": "Chip",
"Dialog": "Dialog",
"Expansion Panel": "Expansion Panel",
"Combobox": "Combobox",
"Textfield": "Textfield",
"Range Slider": "Range Slider",
"Menu": "Menu",
"Snackbar": "Snackbar",
"Tabs": "Tabs",
"Form Elements": "Form Elements",
"Form Layouts": "Form Layouts",
"Authentication": "Authentication",
"Page Not Found - 404": "Page Not Found - 404",
"Not Authorized - 401": "Not Authorized - 401",
"Server Error - 500": "Server Error - 500",
"2": "2",
"Forms": "Forms",
"Timeline": "Timeline",
"Disabled Menu": "Disabled Menu",
"Help Center": "Help Center",
"Verify Email": "Verify Email",
"Verify Email v1": "Verify Email v1",
"Verify Email v2": "Verify Email v2",
"Two Steps": "Two Steps",
"Two Steps v1": "Two Steps v1",
"Two Steps v2": "Two Steps v2",
"Custom Input": "Custom Input",
"Extensions": "Extensions",
"Tour": "Tour",
"Register Multi-Steps": "Register Multi-Steps",
"Wizard Examples": "Wizard Examples",
"Checkout": "Checkout",
"Create Deal": "Create Deal",
"Property Listing": "Property Listing",
"Roles & Permissions": "Roles & Permissions",
"Roles": "Roles",
"Simple Table": "Simple Table",
"Tables": "Tables",
"Data Table": "Data Table",
"Permissions": "Permissions",
"Apps": "Apps",
"Misc": "Misc",
"Wizard Pages": "Wizard Pages",
"Form Wizard": "Form Wizard",
"Numbered": "Numbered",
"3": "3",
"ecommerce": "ecommerce",
"Ecommerce": "Ecommerce",
"Editors": "Editors",
"Front Pages": "Front Pages",
"Landing": "Landing",
"checkout": "checkout",
"Payment": "Payment",
"Swiper": "Swiper",
"Product": "Product",
"Category": "Category",
"Order": "Order",
"Details": "Details",
"Customer": "Customer",
"Manage Review": "Manage Review",
"Referrals": "Referrals",
"Settings": "Settings",
"Overview": "Overview",
"My Course": "My Course",
"Course Details": "Course Details",
"Academy": "Academy",
"Logistics": "Logistics",
"Dashboard": "Dashboard",
"Fleet": "Fleet",
"Shortcut": "Shortcut",
"Appointments": "Appointments",
"Invoice App": "Invoice App",
"Manage Accounts": "Manage Accounts",
"Users": "Users",
"Manage Users": "Manage Users",
"Role Management": "Role Management",
"Permission": "Permission",
"Dashboard Analytics": "Dashboard Analytics",
"5": "5",
"10": "10",
"20": "20",
"25": "25",
"50": "50",
"100": "100",
"$vuetify": {
"badge": "Badge",
"noDataText": "No data available",
"close": "Close",
"open": "open",
"loading": "loading",
"carousel": {
"ariaLabel": {
"delimiter": "delimiter"
}
},
"colorPicker": {
"ariaLabel": {
"hueSlider": "Hue Slider",
"eyedropper": "Eye Dropper",
"hexInput": "Hex Input"
}
},
"dataFooter": {
"itemsPerPageText": "Items per page:",
"itemsPerPageAll": "All",
"pageText": "{0}-{1} of {2}",
"firstPage": "First Page",
"prevPage": "Previous Page",
"nextPage": "Next Page",
"lastPage": "Last Page"
},
"pagination": {
"ariaLabel": {
"root": "root",
"previous": "previous",
"first": "first",
"last": "last",
"next": "next",
"currentPage": "currentPage",
"page": "page"
}
},
"input": {
"clear": "clear",
"appendAction": "appendAction",
"prependAction": "prependAction",
"counterSize": "counterSize",
"otp": "otp"
},
"fileInput": {
"counterSize": "counterSize"
},
"rating": {
"ariaLabel": {
"item": "item"
}
},
"video": {
"seek": "Seek",
"play": "Play",
"pause": "Pause",
"showVolume": "Show Volume",
"enterFullscreen": "Enter Fullscreen",
"volume": "Volume"
}
}
}

View File

@@ -0,0 +1,238 @@
{
"UI Elements": "ÉLÉMENTS DE L'UI",
"Forms & Tables": "Formulaires et tableaux",
"Pages": "Des pages",
"Charts & Maps": "Graphiques et cartes",
"Others": "Autres",
"Typography": "Typographie",
"Cards": "Cartes",
"Basic": "De base",
"Advance": "Avance",
"Widgets": "Widget",
"Card Action": "Action de la carte",
"Components": "Composants",
"Alert": "Alerte",
"Close Alert": "Fermer l'alerte",
"Avatar": "Avatar",
"Badge": "Badge",
"Button": "Bouton",
"Calendar": "Calendrier",
"Kanban": "Tableau Kanban",
"Image": "Image",
"Pagination": "Pagination",
"Progress Circular": "Progrès circulaire",
"Progress Linear": "Progrès Linéaire",
"Autocomplete": "Saisie automatique",
"Tooltip": "Info-bulle",
"Slider": "Glissière",
"Date Time Picker": "Sélecteur de date et d'heure",
"Select": "Sélectionner",
"Switch": "Commutateur",
"Checkbox": "Case à cocher",
"Radio": "Radio",
"Textarea": "Textarea",
"Rating": "Évaluation",
"File Input": "Entrée de fichier",
"Otp Input": "Entrée Otp",
"Form Layout": "Disposition du formulaire",
"Form Validation": "Validation de formulaire",
"Charts": "Graphiques",
"Apex Chart": "Graphique Apex",
"Chartjs": "Chartjs",
"Account Settings": "Paramètres du compte",
"User Profile": "Profil de l'utilisateur",
"FAQ": "FAQ",
"Dialog Examples": "Exemples de dialogue",
"Pricing": "Tarification",
"List": "liste",
"Edit": "Éditer",
"Nav Levels": "Niveaux de navigation",
"Level 2.1": "Niveau 2.1",
"Level 2.2": "Niveau 2.2",
"Level 3.1": "Niveau 3.1",
"Level 3.2": "Niveau 3.2",
"Raise Support": "Augmenter le soutien",
"Documentation": "Documentation",
"Dashboards": "Tableaux de bord",
"Analytics": "Analytique",
"Apps & Pages": "Applications et pages",
"Email": "Email",
"Chat": "Bavarder",
"Invoice": "Facture d'achat",
"Preview": "Aperçu",
"Add": "Ajouter",
"User": "Utilisateur",
"View": "Vue",
"Login v1": "Connexion v1",
"Login v2": "Connexion v2",
"Login": "Connexion",
"Register v1": "S'inscrire v1",
"Register v2": "S'inscrire v2",
"Register": "S'inscrire",
"Forget Password v1": "Oubliez le mot de passe v1",
"Forget Password v2": "Oubliez le mot de passe v2",
"Forgot Password v1": "Oubliez le mot de passe v1",
"Forgot Password v2": "Oubliez le mot de passe v2",
"Forgot Password": "Oubliez le mot de passe",
"Reset Password v1": "Réinitialiser le mot de passe v1",
"Reset Password v2": "Réinitialiser le mot de passe v2",
"Reset Password": "Réinitialiser le mot de passe",
"Miscellaneous": "Divers",
"Coming Soon": "Bientôt disponible",
"Not Authorized": "Pas autorisé",
"Under Maintenance": "En maintenance",
"Error": "Erreur",
"Statistics": "Statistiques",
"Card Actions": "Actions de la carte",
"Actions": "Actions",
"Access Control": "Contrôle d'accès",
"User Interface": "Interface utilisateur",
"CRM": "CRM",
"eCommerce": "commerce électronique",
"Icons": "Icône",
"Chip": "Ébrécher",
"Dialog": "Dialogue",
"Expansion Panel": "Panneau d'extension",
"Combobox": "Boîte combo",
"Textfield": "Champ de texte",
"Range Slider": "Curseur Gamme",
"Menu": "Menu",
"Snackbar": "Casse-croûte",
"Tabs": "Onglets",
"Form Elements": "Éléments de formulaire",
"Form Layouts": "Dispositions de formulaire",
"Authentication": "Authentification",
"Page Not Found - 404": "Page introuvable - 404",
"Not Authorized - 401": "Non autorisé - 401",
"Server Error - 500": "Erreur de serveur - 500",
"2": "2",
"Forms": "Formes",
"Timeline": "Chronologie",
"Disabled Menu": "Menu désactivé",
"Help Center": "Centre d'aide",
"Verify Email": "Vérifier les courriels",
"Verify Email v1": "Vérifier l'e-mail v1",
"Verify Email v2": "Vérifier l'e-mail v2",
"Two Steps": "Deux étapes",
"Two Steps v1": "Deux étapes v1",
"Two Steps v2": "Deux étapes v2",
"Custom Input": "Entrée personnalisée",
"Extensions": "Rallonges",
"Tour": "Tour",
"Register Multi-Steps": "Enregistrer plusieurs étapes",
"Wizard Examples": "Exemples de guide",
"Checkout": "Check-out",
"Create Deal": "Créer une offre",
"Property Listing": "Liste des propriétés",
"Roles & Permissions": "Rôles et autorisations",
"Roles": "Rôles",
"Permissions": "Autorisations",
"Simple Table": "Table simple",
"Tables": "Tables",
"Data Table": "Table de données",
"Apps": "Applications",
"Misc": "Divers",
"Wizard Pages": "Pages de l'assistant",
"Form Wizard": "Assistant de formulaire",
"Numbered": "Numéroté",
"3": "3",
"ecommerce": "commerce électronique",
"Ecommerce": "Commerce électronique",
"Product": "Produit",
"Category": "Catégorie",
"Order": "Ordre",
"Details": "Détails",
"Customer": "Client",
"Manage Review": "Gérer la revue",
"Referrals": "Références",
"Settings": "Paramètres",
"Course Details": "Détails du cours",
"My Course": "Mon cours",
"Overview": "Aperçu",
"Academy": "Académie",
"Logistics": "Logistique",
"Dashboard": "Tableau de bord",
"Fleet": "Flotte",
"Editors": "Éditeurs",
"Front Pages": "Pages frontales",
"Landing": "d'atterrissage",
"checkout": "Check-out",
"Payment": "Paiement",
"Swiper": "Swiper",
"Shortcut": "Raccourci",
"Appointments": "Rendez-vous",
"Invoice App": "Application de facturation",
"Manage Accounts": "Gérer les comptes",
"Users": "Utilisateurs",
"Manage Users": "Gérer les utilisateurs",
"Role Management": "Gestion des rôles",
"Permission": "Autorisation",
"Dashboard Analytics": "Analyse du tableau de bord",
"5": "5",
"10": "10",
"20": "20",
"25": "25",
"50": "50",
"100": "100",
"$vuetify": {
"badge": "Badge",
"loading": "Chargement",
"noDataText": "Pas de données disponibles",
"close": "Fermer",
"open": "Ouvert",
"carousel": {
"ariaLabel": {
"delimiter": "délimiteur"
}
},
"colorPicker": {
"ariaLabel": {
"hueSlider": "curseur de teinte",
"eyedropper": "compte-gouttes",
"hexInput": "entrée hexadécimale"
}
},
"dataFooter": {
"itemsPerPageText": "Objets par page:",
"itemsPerPageAll": "Tout",
"pageText": "{0}-{1} of {2}",
"firstPage": "Première page",
"prevPage": "Page précédente",
"nextPage": "Page suivante",
"lastPage": "Dernière page"
},
"pagination": {
"ariaLabel": {
"root": "racine",
"previous": "précédente",
"first": "d'abord",
"last": "dernière",
"next": "suivante",
"currentPage": "page actuelle",
"page": "page"
}
},
"input": {
"clear": "dégager",
"appendAction": "ajouter une action",
"prependAction": "préfixer l'action",
"otp": "otp"
},
"fileInput": {
"counterSize": "Taille du compteur"
},
"rating": {
"ariaLabel": {
"item": "Objet"
}
},
"video": {
"seek": "Rechercher",
"play": "Jouer",
"pause": "Pause",
"showVolume": "Afficher le volume",
"enterFullscreen": "Entrer en plein écran",
"volume": "Volume"
}
}
}

View File

@@ -0,0 +1,212 @@
/**
* This is an advanced example for creating icon bundles for Iconify SVG Framework.
*
* It creates a bundle from:
* - All SVG files in a directory.
* - Custom JSON files.
* - Iconify icon sets.
* - SVG framework.
*
* This example uses Iconify Tools to import and clean up icons.
* For Iconify Tools documentation visit https://docs.iconify.design/tools/tools2/
*/
import { promises as fs } from 'node:fs';
import { createRequire } from 'node:module';
import { dirname, join } from 'node:path';
// Installation: npm install --save-dev @iconify/tools @iconify/utils @iconify/json @iconify/iconify
import { cleanupSVG, importDirectory, isEmptyColor, parseColors, runSVGO } from '@iconify/tools';
import { getIcons, getIconsCSS, stringToIcon } from '@iconify/utils';
// Create require function for ES modules
const require = createRequire(import.meta.url);
const sources = {
svg: [
// {
// dir: 'assets/images/iconify-svg',
// monotone: true,
// prefix: 'custom',
// },
// {
// dir: 'emojis',
// monotone: false,
// prefix: 'emoji',
// },
],
icons: [
// 'mdi:home',
// 'mdi:account',
// 'mdi:login',
// 'mdi:logout',
// 'octicon:book-24',
// 'octicon:code-square-24',
],
json: [
// Custom JSON file
// 'json/gg.json',
// Iconify JSON file (@iconify/json is a package name, /json/ is directory where files are, then filename)
require.resolve('@iconify-json/tabler/icons.json'),
{
filename: require.resolve('@iconify-json/mdi/icons.json'),
icons: [
'close-circle',
'language-javascript',
'language-typescript',
],
},
{
filename: require.resolve('@iconify-json/fa/icons.json'),
icons: [
'circle',
],
},
// Custom file with only few icons
// {
// filename: require.resolve('@iconify-json/line-md/icons.json'),
// icons: [
// 'home-twotone-alt',
// 'github',
// 'document-list',
// 'document-code',
// 'image-twotone',
// ],
// },
],
};
// File to save bundle to
const target = join(__dirname, 'icons.css');
(async function () {
// Create directory for output if missing
const dir = dirname(target);
try {
await fs.mkdir(dir, {
recursive: true,
});
}
catch (err) {
//
}
const allIcons = [];
/**
* Convert sources.icons to sources.json
*/
if (sources.icons) {
const sourcesJSON = sources.json ? sources.json : (sources.json = []);
// Sort icons by prefix
const organizedList = organizeIconsList(sources.icons);
for (const prefix in organizedList) {
const filename = require.resolve(`@iconify/json/json/${prefix}.json`);
sourcesJSON.push({
filename,
icons: organizedList[prefix],
});
}
}
/**
* Bundle JSON files and collect icons
*/
if (sources.json) {
for (let i = 0; i < sources.json.length; i++) {
const item = sources.json[i];
// Load icon set
const filename = typeof item === 'string' ? item : item.filename;
const content = JSON.parse(await fs.readFile(filename, 'utf8'));
for (const key in content) {
if (key === 'prefix' && content.prefix === 'tabler') {
for (const k in content.icons)
content.icons[k].body = content.icons[k].body.replace(/stroke-width="2"/g, 'stroke-width="1.5"');
}
}
// Filter icons
if (typeof item !== 'string' && item.icons?.length) {
const filteredContent = getIcons(content, item.icons);
if (!filteredContent)
throw new Error(`Cannot find required icons in ${filename}`);
// Collect filtered icons
allIcons.push(filteredContent);
}
else {
// Collect all icons from the JSON file
allIcons.push(content);
}
}
}
/**
* Bundle custom SVG icons and collect icons
*/
if (sources.svg) {
for (let i = 0; i < sources.svg.length; i++) {
const source = sources.svg[i];
// Import icons
const iconSet = await importDirectory(source.dir, {
prefix: source.prefix,
});
// Validate, clean up, fix palette, etc.
await iconSet.forEach(async (name, type) => {
if (type !== 'icon')
return;
// Get SVG instance for parsing
const svg = iconSet.toSVG(name);
if (!svg) {
// Invalid icon
iconSet.remove(name);
return;
}
// Clean up and optimise icons
try {
// Clean up icon code
await cleanupSVG(svg);
if (source.monotone) {
// Replace color with currentColor, add if missing
// If icon is not monotone, remove this code
await parseColors(svg, {
defaultColor: 'currentColor',
callback: (attr, colorStr, color) => {
return !color || isEmptyColor(color) ? colorStr : 'currentColor';
},
});
}
// Optimise
await runSVGO(svg);
}
catch (err) {
// Invalid icon
console.error(`Error parsing ${name} from ${source.dir}:`, err);
iconSet.remove(name);
return;
}
// Update icon from SVG instance
iconSet.fromSVG(name, svg);
});
// Collect the SVG icon
allIcons.push(iconSet.export());
}
}
// Generate CSS from collected icons
const cssContent = allIcons
.map(iconSet => getIconsCSS(iconSet, Object.keys(iconSet.icons), {
iconSelector: '.{prefix}-{name}',
mode: 'mask',
}))
.join('\n');
// Save the CSS to a file
await fs.writeFile(target, cssContent, 'utf8');
console.log(`Saved CSS to ${target}!`);
})().catch(err => {
console.error(err);
});
/**
* Sort icon names by prefix
*/
function organizeIconsList(icons) {
const sorted = Object.create(null);
icons.forEach(icon => {
const item = stringToIcon(icon);
if (!item)
return;
const prefix = item.prefix;
const prefixList = sorted[prefix] ? sorted[prefix] : (sorted[prefix] = []);
const name = item.name;
if (!prefixList.includes(name))
prefixList.push(name);
});
return sorted;
}

View File

@@ -0,0 +1,4 @@
;
export default defineNuxtPlugin(() => {
// This plugin just requires icons import
})

View File

@@ -0,0 +1,10 @@
import { createLayouts } from '@layouts'
import { layoutConfig } from '@themeConfig'
// Styles
import '@layouts/styles/index.scss'
export default defineNuxtPlugin(nuxtApp => {
// We generate layout config from our themeConfig so you don't have to write config twice
nuxtApp.vueApp.use(createLayouts(layoutConfig))
})

View File

@@ -0,0 +1,196 @@
export default {
IconBtn: {
icon: true,
color: 'default',
variant: 'text',
},
VAlert: {
density: 'comfortable',
VBtn: {
color: undefined,
},
},
VAvatar: {
// Remove after next release
variant: 'flat',
},
VBadge: {
// set v-badge default color to primary
color: 'primary',
},
VBtn: {
// set v-btn default color to primary
color: 'primary',
},
VChip: {
label: true,
},
VDataTable: {
VPagination: {
showFirstLastPage: true,
firstIcon: 'tabler-chevrons-left',
lastIcon: 'tabler-chevrons-right',
},
},
VDataTableServer: {
VPagination: {
showFirstLastPage: true,
firstIcon: 'tabler-chevrons-left',
lastIcon: 'tabler-chevrons-right',
},
},
VExpansionPanel: {
expandIcon: 'tabler-chevron-right',
collapseIcon: 'tabler-chevron-right',
},
VExpansionPanelTitle: {
expandIcon: 'tabler-chevron-right',
collapseIcon: 'tabler-chevron-right',
},
VList: {
color: 'primary',
density: 'compact',
VCheckboxBtn: {
density: 'compact',
},
VListItem: {
ripple: false,
VAvatar: {
size: 40,
},
},
},
VMenu: {
offset: '2px',
},
VPagination: {
density: 'comfortable',
variant: 'tonal',
},
VTabs: {
// set v-tabs default color to primary
color: 'primary',
density: 'comfortable',
VSlideGroup: {
showArrows: true,
},
},
VTooltip: {
// set v-tooltip default location to top
location: 'top',
},
VCheckboxBtn: {
color: 'primary',
},
VCheckbox: {
// set v-checkbox default color to primary
color: 'primary',
density: 'comfortable',
hideDetails: 'auto',
},
VRadioGroup: {
color: 'primary',
density: 'comfortable',
hideDetails: 'auto',
},
VRadio: {
density: 'comfortable',
hideDetails: 'auto',
},
VSelect: {
variant: 'outlined',
color: 'primary',
density: 'comfortable',
hideDetails: 'auto',
VChip: {
label: true,
},
},
VRangeSlider: {
// set v-range-slider default color to primary
color: 'primary',
trackSize: 6,
thumbSize: 22,
density: 'comfortable',
thumbLabel: true,
hideDetails: 'auto',
},
VRating: {
// set v-rating default color to primary
color: 'warning',
},
VProgressLinear: {
height: 6,
roundedBar: true,
rounded: true,
bgColor: 'rgba(var(--v-track-bg))',
},
VSlider: {
// set v-range-slider default color to primary
color: 'primary',
thumbLabel: true,
hideDetails: 'auto',
thumbSize: 22,
trackSize: 6,
elevation: 4,
},
VTextField: {
variant: 'outlined',
density: 'comfortable',
color: 'primary',
hideDetails: 'auto',
},
VAutocomplete: {
variant: 'outlined',
color: 'primary',
density: 'comfortable',
hideDetails: 'auto',
menuProps: {
contentClass: 'app-autocomplete__content v-autocomplete__content',
},
VChip: {
label: true,
},
},
VCombobox: {
variant: 'outlined',
density: 'comfortable',
color: 'primary',
hideDetails: 'auto',
VChip: {
label: true,
},
},
VFileInput: {
variant: 'outlined',
density: 'comfortable',
color: 'primary',
hideDetails: 'auto',
},
VTextarea: {
variant: 'outlined',
density: 'comfortable',
color: 'primary',
hideDetails: 'auto',
},
VSnackbar: {
VBtn: {
density: 'comfortable',
},
},
VSwitch: {
// set v-switch default color to primary
inset: true,
color: 'primary',
hideDetails: 'auto',
ripple: false,
},
VNavigationDrawer: {
touchless: true,
},
VVideo: {
VSlider: {
thumbLabel: false,
},
},
}

View File

@@ -0,0 +1,87 @@
import checkboxChecked from '@images/svg/checkbox-checked.svg'
import checkboxIndeterminate from '@images/svg/checkbox-indeterminate.svg'
import checkboxUnchecked from '@images/svg/checkbox-unchecked.svg'
import radioChecked from '@images/svg/radio-checked.svg'
import radioUnchecked from '@images/svg/radio-unchecked.svg'
const customIcons = {
'mdi-checkbox-blank-outline': checkboxUnchecked,
'mdi-checkbox-marked': checkboxChecked,
'mdi-minus-box': checkboxIndeterminate,
'mdi-radiobox-marked': radioChecked,
'mdi-radiobox-blank': radioUnchecked,
}
const aliases = {
calendar: 'tabler-calendar',
collapse: 'tabler-chevron-up',
complete: 'tabler-check',
cancel: 'tabler-x',
close: 'tabler-x',
delete: 'tabler-circle-x-filled',
clear: 'tabler-circle-x',
success: 'tabler-circle-check',
info: 'tabler-info-circle',
warning: 'tabler-alert-triangle',
error: 'tabler-alert-circle',
prev: 'tabler-chevron-left',
ratingEmpty: 'tabler-star',
ratingFull: 'tabler-star-filled',
ratingHalf: 'tabler-star-half-filled',
next: 'tabler-chevron-right',
delimiter: 'tabler-circle',
sort: 'tabler-arrow-up',
expand: 'tabler-chevron-down',
menu: 'tabler-menu-2',
subgroup: 'tabler-caret-down',
dropdown: 'tabler-chevron-down',
edit: 'tabler-pencil',
loading: 'tabler-refresh',
first: 'tabler-player-skip-back',
last: 'tabler-player-skip-forward',
unfold: 'tabler-arrows-move-vertical',
file: 'tabler-paperclip',
plus: 'tabler-plus',
minus: 'tabler-minus',
sortAsc: 'tabler-arrow-up',
sortDesc: 'tabler-arrow-down',
play: 'tabler-player-play',
pause: 'tabler-player-pause',
fullscreen: 'tabler-maximize',
fullscreenExit: 'tabler-minimize',
volumeHigh: 'tabler-volume',
volumeMedium: 'tabler-volume-2',
volumeLow: 'tabler-volume-2',
volumeOff: 'tabler-volume-off',
tableGroupExpand: 'tabler-chevron-right',
tableGroupCollapse: 'tabler-chevron-down',
}
export const iconify = {
component: props => {
// Load custom SVG directly instead of going through icon component
if (typeof props.icon === 'string') {
const iconComponent = customIcons[props.icon]
if (iconComponent)
return h(iconComponent)
}
return h(props.tag, {
...props,
// As we are using class based icons
class: [props.icon],
// Remove used props from DOM rendering
tag: undefined,
icon: undefined,
})
},
}
export const icons = {
defaultSet: 'iconify',
aliases,
sets: {
iconify,
},
}

View File

@@ -0,0 +1,58 @@
import { deepMerge } from '@antfu/utils'
import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components/VBtn'
import { VVideo } from 'vuetify/labs/VVideo'
import { createVueI18nAdapter } from 'vuetify/locale/adapters/vue-i18n'
import defaults from './defaults'
import { icons } from './icons'
import { staticPrimaryColor, staticPrimaryDarkenColor, themes } from './theme'
import { themeConfig } from '@themeConfig'
// Styles
import { cookieRef } from '@/@layouts/stores/config'
import '@core/scss/template/libs/vuetify/index.scss'
import 'vuetify/styles'
export default defineNuxtPlugin(nuxtApp => {
const { $i18n } = useNuxtApp()
const i18n = { global: $i18n }
const cookieThemeValues = {
defaultTheme: resolveVuetifyTheme(themeConfig.app.theme),
themes: {
light: {
colors: {
'primary': cookieRef('lightThemePrimaryColor', staticPrimaryColor).value,
'primary-darken-1': cookieRef('lightThemePrimaryDarkenColor', staticPrimaryDarkenColor).value,
},
},
dark: {
colors: {
'primary': cookieRef('darkThemePrimaryColor', staticPrimaryColor).value,
'primary-darken-1': cookieRef('darkThemePrimaryDarkenColor', staticPrimaryDarkenColor).value,
},
},
},
}
const optionTheme = deepMerge({ themes }, cookieThemeValues)
const vuetify = createVuetify({
ssr: true,
aliases: {
IconBtn: VBtn,
},
components: {
VVideo,
},
defaults,
icons,
theme: optionTheme,
locale: { adapter: createVueI18nAdapter({ i18n, useI18n }),
},
})
nuxtApp.vueApp.use(vuetify)
})

View File

@@ -0,0 +1,150 @@
export const staticPrimaryColor = '#7367F0'
export const staticPrimaryDarkenColor = '#675DD8'
export const themes = {
light: {
dark: false,
colors: {
'primary': staticPrimaryColor,
'on-primary': '#fff',
'primary-darken-1': '#675DD8',
'secondary': '#808390',
'on-secondary': '#fff',
'secondary-darken-1': '#737682',
'success': '#28C76F',
'on-success': '#fff',
'success-darken-1': '#24B364',
'info': '#00BAD1',
'on-info': '#fff',
'info-darken-1': '#00A7BC',
'warning': '#FF9F43',
'on-warning': '#fff',
'warning-darken-1': '#E68F3C',
'error': '#FF4C51',
'on-error': '#fff',
'error-darken-1': '#E64449',
'background': '#F8F7FA',
'on-background': '#2F2B3D',
'surface': '#fff',
'on-surface': '#2F2B3D',
'grey-50': '#FAFAFA',
'grey-100': '#F5F5F5',
'grey-200': '#EEEEEE',
'grey-300': '#E0E0E0',
'grey-400': '#BDBDBD',
'grey-500': '#9E9E9E',
'grey-600': '#757575',
'grey-700': '#616161',
'grey-800': '#424242',
'grey-900': '#212121',
'grey-light': '#FAFAFA',
'perfect-scrollbar-thumb': '#DBDADE',
'skin-bordered-background': '#fff',
'skin-bordered-surface': '#fff',
'expansion-panel-text-custom-bg': '#fafafa',
},
variables: {
'code-color': '#d400ff',
'overlay-scrim-background': '#2F2B3D',
'tooltip-background': '#2F2B3D',
'overlay-scrim-opacity': 0.5,
'hover-opacity': 0.06,
'focus-opacity': 0.1,
'selected-opacity': 0.08,
'activated-opacity': 0.16,
'pressed-opacity': 0.14,
'dragged-opacity': 0.1,
'disabled-opacity': 0.4,
'border-color': '#2F2B3D',
'border-opacity': 0.12,
'table-header-color': '#EAEAEC',
'high-emphasis-opacity': 0.9,
'medium-emphasis-opacity': 0.7,
'switch-opacity': 0.2,
'switch-disabled-track-opacity': 0.3,
'switch-disabled-thumb-opacity': 0.4,
'switch-checked-disabled-opacity': 0.3,
'track-bg': '#F1F0F2',
// Shadows
'shadow-key-umbra-color': '#2F2B3D',
'shadow-xs-opacity': 0.10,
'shadow-sm-opacity': 0.12,
'shadow-md-opacity': 0.14,
'shadow-lg-opacity': 0.16,
'shadow-xl-opacity': 0.18,
},
},
dark: {
dark: true,
colors: {
'primary': staticPrimaryColor,
'on-primary': '#fff',
'primary-darken-1': '#675DD8',
'secondary': '#808390',
'on-secondary': '#fff',
'secondary-darken-1': '#737682',
'success': '#28C76F',
'on-success': '#fff',
'success-darken-1': '#24B364',
'info': '#00BAD1',
'on-info': '#fff',
'info-darken-1': '#00A7BC',
'warning': '#FF9F43',
'on-warning': '#fff',
'warning-darken-1': '#E68F3C',
'error': '#FF4C51',
'on-error': '#fff',
'error-darken-1': '#E64449',
'background': '#25293C',
'on-background': '#E1DEF5',
'surface': '#2F3349',
'on-surface': '#E1DEF5',
'grey-50': '#26293A',
'grey-100': '#2F3349',
'grey-200': '#26293A',
'grey-300': '#4A5072',
'grey-400': '#5E6692',
'grey-500': '#7983BB',
'grey-600': '#AAB3DE',
'grey-700': '#B6BEE3',
'grey-800': '#CFD3EC',
'grey-900': '#E7E9F6',
'grey-light': '#353A52',
'perfect-scrollbar-thumb': '#4A5072',
'skin-bordered-background': '#2F3349',
'skin-bordered-surface': '#2F3349',
},
variables: {
'code-color': '#d400ff',
'overlay-scrim-background': '#171925',
'tooltip-background': '#F7F4FF',
'overlay-scrim-opacity': 0.6,
'hover-opacity': 0.06,
'focus-opacity': 0.1,
'selected-opacity': 0.08,
'activated-opacity': 0.16,
'pressed-opacity': 0.14,
'dragged-opacity': 0.1,
'disabled-opacity': 0.4,
'border-color': '#E1DEF5',
'border-opacity': 0.12,
'table-header-color': '#535876',
'high-emphasis-opacity': 0.9,
'medium-emphasis-opacity': 0.7,
'switch-opacity': 0.4,
'switch-disabled-track-opacity': 0.4,
'switch-disabled-thumb-opacity': 0.8,
'switch-checked-disabled-opacity': 0.3,
'track-bg': '#3A3F57',
// Shadows
'shadow-key-umbra-color': '#131120',
'shadow-xs-opacity': 0.16,
'shadow-sm-opacity': 0.18,
'shadow-md-opacity': 0.2,
'shadow-lg-opacity': 0.22,
'shadow-xl-opacity': 0.24,
},
},
}
export default themes

View File

@@ -0,0 +1,17 @@
/**
* plugins/webfontloader.js
*
* webfontloader documentation: https://github.com/typekit/webfontloader
*/
export async function loadFonts() {
const webFontLoader = await import(/* webpackChunkName: "webfontloader" */ 'webfontloader')
webFontLoader.load({
google: {
families: ['Public+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap'],
},
})
}
export default defineNuxtPlugin(() => {
loadFonts()
})