diff --git a/.dockerignore b/.dockerignore new file mode 100755 index 0000000..056f5cc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +node_modules +.next +npm-debug.log +.git diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..339944c --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# Dependencies and AdonisJS build +node_modules/ +**/node_modules/ +build +dist +tmp + +# Secrets +.env +.env.local +.env.production.local +.env.development.local + +# Frontend assets compiled code +public/assets + +# Build tools specific +npm-debug.log +yarn-error.log + +# Editors specific +.fleet +.idea +.vscode + +# Platform specific +.DS_Store + +*.tsbuildinfo + +/apps/backend/public/ +/apps/backend/storage/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..d0a7784 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 0000000..66150cb --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,3 @@ +# npm run test:admin +# npm run test:backend +# npm run test:web diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..ca5c350 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24.18.0 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..51e1eed --- /dev/null +++ b/.prettierignore @@ -0,0 +1,13 @@ +**/node_modules/** +**/build/** +**/dist/** +**/coverage/** +**/.next/** + +apps/backend/public/** +apps/backend/storage/** +apps/backend/app/templates/** +apps/backend/.adonisjs/** +apps/backend/database/schema.ts + +apps/web/.next/** diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..7434513 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,135 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project +adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +### Changed + +### Fixed + +### Removed + +## [1.3.1] - 2026-08-31 + +### Fixed + +- Fixed Web Studio site settings rejecting empty optional fields. The backend bodyparser converts + empty strings to `null`, so a cleared menu title, footer copyright or legal path failed + validation; those fields are now optional in the vine schema (stored without the key) and the + admin maps them back to empty strings via `SiteSettingsMapper`. +- Backend validation errors on the settings page no longer disappear silently: the shared 422 + handler skips them expecting the caller to map field errors, which the page never did. Structured + field errors are now set on the matching form inputs, the tab holding the first error is opened, + and message-only 422s surface as a toast. +- Fixed renaming or deleting a folder destroying sibling folders whose name shares its prefix + (renaming `aa` overwrote and then deleted `aab`). Drive strips the trailing slash off a listing + prefix, so a directory's contents are now filtered on the real `/` prefix, and the S3 + service deletes the listed keys instead of passing that prefix to `deleteAll`. +- Fixed the web container running against the host's `node_modules`: the `web` service keeps + `apps/web/node_modules` in an anonymous volume, so the bind mount no longer shadows the + dependencies installed in the image. + +## [1.3.0] - 2026-08-28 + +### Added + +- Added an `ApiException` base class whose self-handling renders module exceptions as + `{ message, code }` JSON responses, so exception classes no longer need registration in the + global HTTP exception handler. +- Added `@crux-kit/editor-tiptap`, a free, headless rich-text editor package built on TipTap. The `light` preset covers bold, italic, underline, + strikethrough, headings, lists, blockquote, text alignment, links, and undo/redo, reading and + writing content as plain HTML so it themes with the shared design-system tokens. +- Added the `InputTiptapEditor` composed form field. +- Added `useIntlDate` and `useIntlName` hooks under `apps/admin/src/app/i18n`, each returning a + formatter bound to the active UI language. Reading the language from context is what subscribes a + component to a language switch; components that read the `IntlDate`/`IntlName` singletons directly + +### Changed + +- Moved module generation fully server-side. The admin devtools now sends the raw generator config + (`{ name, table, generate, form, datatable }`) instead of pre-rendered source strings, and the + six frontend source builders were ported verbatim from the admin to + `apps/backend/app/services/module_generator`. +- Refactored `module_controller.ts` (~500 lines) into a thin HTTP controller delegating to focused + `module_generator` service modules: an orchestrator, schema-derived context building, naming and + DB-type helpers, a template renderer, and `builders/` + `writers/` subdirectories. +- Split the root `.env` into per-workspace env files (`apps/backend/.env`, `apps/admin/.env`, + `apps/web/.env`) so each app only ingests the variables it uses. Every `docker-compose.yml` + service now loads its own app's env file, and the admin (Vite) and web (Next.js) apps rely on + their frameworks' native env loading instead of custom root-file merging. +- Renamed cross-app URL env variables: `PAGE_MANAGER_API_URL` → `BACKEND_API_URL` in the web app + and `VITE_PAGE_MANAGER_WEB_URL` → `VITE_WEB_URL` in the admin app. +- File Manager exceptions now extend `ApiException`. +- Extracted the admin i18n context out of `I18nProvider` into `app/i18n/context.ts` and + `app/i18n/useLanguage.ts`, so components reach the active language through a side-effect-free + module instead of importing the provider and executing its module body. +- The selected language is now persisted to local storage as its code rather than as the whole + `Language` object. + +### Fixed + +- Fixed admin menu highlighting, which marked every ancestor entry active at once. +- Fixes the containing section staying collapsed when a sub-route is opened directly. +- Fixed backend functional test discovery: the `tests/**/*.spec.(ts|js)` globs in `adonisrc.ts` + are not valid for the native `fs.glob` used by Japa v5, so the suite silently ran zero tests. +- Fixed the backend `lint` script path (`../scripts` → `../../scripts`), which made + `npm run lint` fail before linting. +- Removed the stale Japa v1-era `@japa/spec-reporter` wiring from `tests/bootstrap.ts`; the + runner's built-in spec reporter is used instead. +- Renamed `app/exceptions/file_manager_exeptions.ts` to `file_manager_exceptions.ts`, fixing the + filename typo, and updated all imports. + +### Removed + +- Removed the root `.env` file. + +## [1.2.0] - 2026-07-17 + +### Changed + +- Moved AdonisJS ESLint and Prettier configuration packages and Japa test dependencies from the + root package manifest to the backend workspace so workspace-specific dependencies are owned by + `apps/backend`. +- Updated the Admin frontend architecture so global providers belong to the `app` composition + layer under `app/providers` instead of being modeled as a separate architectural layer. + +## [1.1.0] - 2026-07-17 + +### Added + +- Added image map editor for creating and editing interactive image map areas in the File Manager. + +### Changed + +- Migrated TypeScript from `5.8.3` to `7.0.2` +- Migrated AdonisJS from `6.x` to `7.3.5` +- Refactored admin module-generator source builders to compose imports and source sections through + shared source-file helpers while preserving the existing generation payload. +- Renamed module-generator builder classes and files from template-builder terminology to + source-builder terminology. +- Updated module-generator frontend documentation to reference the new source-builder names. + +### Fixed + +- Fix prettier one line import break sorting and class order + +### Removed + +- Removed "prettier-plugin-one-line-imports" + +## [1.0.1] - 2026-06-30 + +### Fixed + +- Resolved a circular dependency in language imports that could crash the admin app during language + initialization. +- Exposed the provider `languages` list through `I18nProvider` instead of importing the language + config directly in `UserDropdownMenu`. +- Updated language selection in `UserDropdownMenu` to use the provider-supplied `languages` + collection, preventing inconsistent state during rendering. diff --git a/README.md b/README.md index caa0473..05bc1a1 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,12 @@ Adding new modules, services, tenants, integrations, or developers should not re ### Principles -* Modular architecture -* Low coupling -* Clear interfaces -* Easy onboarding -* Predictable project structure -* Minimal friction when adding new functionality +- Modular architecture +- Low coupling +- Clear interfaces +- Easy onboarding +- Predictable project structure +- Minimal friction when adding new functionality --- @@ -28,25 +28,25 @@ Business-specific logic should sit on top of the foundation instead of contamina ### Core building blocks -* Authentication -* Authorization -* Roles & permissions -* Organizations -* Events -* Workflows -* Storage -* Notifications -* API layer -* Integrations -* Configuration +- Authentication +- Authorization +- Roles & permissions +- Organizations +- Events +- Workflows +- Storage +- Notifications +- API layer +- Integrations +- Configuration ### Principles -* Reusable core -* Configuration-driven behavior -* Extensible modules -* Replaceable infrastructure -* Clear separation between core and business logic +- Reusable core +- Configuration-driven behavior +- Extensible modules +- Replaceable infrastructure +- Clear separation between core and business logic --- @@ -58,14 +58,14 @@ Not only more traffic, but also more customers, data, modules, developers, integ ### Principles -* Horizontal scaling -* Multi-tenancy -* Async processing -* Observability -* Independent modules -* Independent deployment paths where needed -* Efficient data growth -* Clear service boundaries +- Horizontal scaling +- Multi-tenancy +- Async processing +- Observability +- Independent modules +- Independent deployment paths where needed +- Efficient data growth +- Clear service boundaries --- @@ -101,3 +101,177 @@ ZFG Or, internally: > **Zero Fucks Given.** + +## About + +| App | Source | Dev port | What it is | +| --------------- | --------------- | -------- | ------------------------------------------------------ | +| Backend API | `apps/backend/` | 3333 | AdonisJS — data, auth, permissions, public content API | +| Admin panel | `apps/admin/` | 5173 | React + Vite — the internal UI | +| Public website | `apps/web/` | 3000 | Next.js — the site visitors see | +| Shared packages | `packages/` | — | UI, hooks, services, types, utils | + +Full documentation lives in [`docs/`](./docs/Readme.md). + +### Tech Stack + +#### Backend + +- AdonisJS +- TypeScript +- Lucid ORM +- PostgreSQL / MySQL (configurable) +- Redis, S3 / MinIO storage + +#### Admin panel + +- React +- TypeScript +- Vite +- React Query / MobX / Axios +- Radix UI + Tailwind component system +- React Hook Form + Zod + +#### Public website + +- Next.js (App Router, React Server Components) +- TypeScript +- next-intl +- Tailwind CSS + +### Getting Started + +#### Prerequisites + +- Node.js `24.18.0` (see `.nvmrc`; the package manifest requires `>=24.0.0`) +- npm `>=11.6.2` (the repo pins `npm@11.15.0`) +- PostgreSQL + +#### Installation + +```bash +git clone https://git.kossmc.com/coach.one1994/zero-fucks-given.git +``` + +```bash +cd zero-fucks-given && npm install --force +``` + +> `--force` is required. `typescript-eslint` does not yet declare support for the TypeScript +> version this repo uses, so a plain `npm install` fails with `ERESOLVE`. Never substitute +> `--legacy-peer-deps` — it strips nested peer dependencies and breaks the backend at runtime. Use +> `npm ci --force` for a reproducible install, and `npm install --force` when adding one. +> See [troubleshooting.md](./troubleshooting.md). + +### Configuration + +Each workspace defines its own environment variables. Copy the workspace's `.env.example` to `.env` and fill in the values: + +| Env file | Covers | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `apps/backend/.env` | Server (`PORT`, `APP_KEY`), database (`DB_*`), storage (`AWS_*`, `S3_*`), and the public site link (`WEB_APP_URL`, `WEB_REVALIDATE_SECRET`) used to purge its cache | +| `apps/admin/.env` | `VITE_API_URL` (backend), `VITE_WEB_URL` (public site, used for page previews), `VITE_TINYMCE_API_KEY` | +| `apps/web/.env` | `BACKEND_API_URL` (backend base URL for server rendering), `REVALIDATE_SECRET` (must match the backend's `WEB_REVALIDATE_SECRET`), `SITE_URL` (canonical origin) | + +`docker-compose.yml` loads each service's env from the same per-app files. Inside Docker, service +URLs must use compose service names (`http://backend:3333`), not `localhost`. + +### Running + +#### Locally + +| Command | Description | +| ----------------------- | ----------------------------------------------- | +| `npm run dev:backend` | Start the AdonisJS backend in development mode | +| `npm run dev:admin-app` | Start the React admin application | +| `npm run dev:web` | Start the Next.js web application | +| `npm run dev:all` | Start backend, admin, and web apps concurrently | + +#### With Docker + +```bash +docker compose up -d +``` + +Brings up everything: backend (3333), admin (5173), web (3000), PostgreSQL (5432), Redis (6379), +MinIO (9000 / console 9001) and pgAdmin (5050). + +Two quirks worth knowing when a change appears not to take effect: + +- The web container keeps `.next` on an anonymous volume that survives rebuilds. Clear it with + `docker compose up -d --force-recreate --renew-anon-volumes web`. +- Backend HMR does not always pick up edits on macOS (bind-mount file events); restart + `crux_backend_adonis` to load them. + +### Scripts + +#### Build + +| Command | Description | +| ----------------------- | ------------------------------------------ | +| `npm run build:backend` | Build the backend application | +| `npm run build:admin` | Type-check and build the admin application | +| `npm run build:web` | Type-check and build the Next.js web app | + +#### Test + +| Command | Description | +| ---------------------- | ---------------------------------------------- | +| `npm run test:backend` | Backend functional tests (requires a database) | +| `npm run test:admin` | Admin unit tests (Vitest) | +| `npm run test:web` | Web app unit tests (Vitest) | + +#### Lint and format + +| Command | Description | +| ---------------------- | -------------------------- | +| `npm run lint` | ESLint across the monorepo | +| `npm run lint:fix` | ESLint with autofix | +| `npm run format` | Prettier write | +| `npm run format:check` | Prettier check, no writes | + +#### Versions + +| Command | Description | +| ----------------------- | ------------------------------------ | +| `npm run version:patch` | Update patch version of all packages | +| `npm run version:minor` | Update minor version of all packages | +| `npm run version:major` | Update major version of all packages | + +> Versions are updated without creating git tags. + +### Features + +#### Module Generator + +Create full CRUD modules by selecting: + +- Database table +- Fields and types +- Validation rules +- List view configuration + +**Generated output** — Backend: controllers, validators, routes. Frontend: pages, forms, tables, API. + +#### Authentication & Authorization + +- JWT / session-based authentication +- Role & permission system +- Policy-based access control + +#### Content Management + +Web Manager is the built-in CMS: editors build localized pages from prebuilt blocks in the admin +panel, preview them privately, and publish to the Next.js site, which purges only the cache entries +the change affects. See [Web Manager](./docs/core/web-manager/Readme.md). + +### Documentation + +| Topic | Where | +| ------------------------ | ---------------------------------------------------- | +| Documentation home | [docs/Readme.md](./docs/Readme.md) | +| Public website | [apps/web/Readme.md](./apps/web/Readme.md) | +| Architecture | [docs/architecture/](./docs/architecture/Readme.md) | +| Core modules | [docs/core/](./docs/Readme.md#core-modules) | +| Shared packages | [docs/packages/Readme.md](./docs/packages/Readme.md) | +| Install and setup issues | [troubleshooting.md](./troubleshooting.md) | diff --git a/apps/admin/.dockerignore b/apps/admin/.dockerignore new file mode 100755 index 0000000..76add87 --- /dev/null +++ b/apps/admin/.dockerignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/apps/admin/.env.example b/apps/admin/.env.example new file mode 100755 index 0000000..a1aa4c7 --- /dev/null +++ b/apps/admin/.env.example @@ -0,0 +1,3 @@ +VITE_API_URL=http://localhost:3333 +VITE_TINYMCE_API_KEY= +VITE_WEB_URL=http://localhost:3000 \ No newline at end of file diff --git a/apps/admin/.prettierignore b/apps/admin/.prettierignore new file mode 100644 index 0000000..2cf1da4 --- /dev/null +++ b/apps/admin/.prettierignore @@ -0,0 +1,2 @@ +dist +build \ No newline at end of file diff --git a/apps/admin/.prettierrc b/apps/admin/.prettierrc new file mode 100644 index 0000000..6cb0664 --- /dev/null +++ b/apps/admin/.prettierrc @@ -0,0 +1,33 @@ +{ + "printWidth": 100, + "quoteProps": "consistent", + "tabWidth": 2, + "endOfLine": "lf", + "singleQuote": true, + "trailingComma": "none", + "bracketSpacing": true, + "semi": true, + "bracketSameLine": false, + "jsxSingleQuote": false, + "arrowParens": "always", + "importOrder": [ + "", + "", + "^@crux-kit/(.*)$", + "^#app/(.*)$", + "^#infrastructure/(.*)$", + "^#devtools/(.*)$", + "^#core/(.*)$", + "^#modules/(.*)$", + "^#refdata/(.*)$", + "^#shared/(.*)$", + "^#(.*)$", + "^[./]" + ], + "importOrderCaseSensitive": false, + "plugins": [ + "@ianvs/prettier-plugin-sort-imports", + "../../plugins/prettier/one-line-sorted-imports.cjs", + "prettier-plugin-tailwindcss" + ] +} diff --git a/apps/admin/Dockerfile b/apps/admin/Dockerfile new file mode 100755 index 0000000..30c7168 --- /dev/null +++ b/apps/admin/Dockerfile @@ -0,0 +1,20 @@ +FROM node:24-alpine3.22 + +WORKDIR /app + +# Copy all workspaces before installation so npm resolves workspace dependencies. +COPY package.json package-lock.json ./ +COPY apps ./apps +COPY packages ./packages + +RUN npm ci --force + +WORKDIR /app/apps/admin + +ENV CHOKIDAR_USEPOLLING=true +ENV HOST=0.0.0.0 +ENV PORT=5173 + +EXPOSE 5173 + +CMD ["npm", "run", "dev"] diff --git a/apps/admin/eslint.config.js b/apps/admin/eslint.config.js new file mode 100755 index 0000000..f0e8d9f --- /dev/null +++ b/apps/admin/eslint.config.js @@ -0,0 +1,61 @@ +import prettierConfig from 'eslint-config-prettier'; +import reactHooks from 'eslint-plugin-react-hooks'; +import reactRefresh from 'eslint-plugin-react-refresh'; +import globals from 'globals'; +import tseslint from 'typescript-eslint'; + +const cleanGlobals = Object.fromEntries( + Object.entries(globals.browser).map(([key, value]) => [key.trim(), value]) +); + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [...tseslint.configs.recommended, prettierConfig], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: cleanGlobals + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh + }, + rules: { + ...reactHooks.configs.recommended.rules, + '@typescript-eslint/no-unused-vars': [ + 'warn', + { + /* + * Check all function arguments for usage + **/ + args: 'all', + /* + * Ignore function arguments that start with "_" (e.g., `_arg`) + **/ + argsIgnorePattern: '^_', + /* + * Check all caught error variables in try/catch + **/ + caughtErrors: 'all', + /* + *Ignore caught errors that start with "_" (e.g., `catch (_err)`) + **/ + caughtErrorsIgnorePattern: '^_', + /* + * Ignore unused elements in array destructuring if they start with "_" + **/ + destructuredArrayIgnorePattern: '^_', + /* + * Ignore variables declared but not used if they start with "_" + **/ + varsIgnorePattern: '^_', + /* + * Ignore unused variables when using object rest spread (e.g., `const { a, ...rest } = obj;`) + **/ + ignoreRestSiblings: true + } + ] + } + } +); diff --git a/apps/admin/index.html b/apps/admin/index.html new file mode 100755 index 0000000..1f141f2 --- /dev/null +++ b/apps/admin/index.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + +
+ + + diff --git a/apps/admin/package.json b/apps/admin/package.json new file mode 100755 index 0000000..72599ae --- /dev/null +++ b/apps/admin/package.json @@ -0,0 +1,117 @@ +{ + "name": "@crux-kit/admin-app", + "private": true, + "version": "1.3.1", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "test": "vitest run tests --environment=node", + "lint": "eslint src --fix", + "format": "prettier --write .", + "preview": "vite preview" + }, + "dependencies": { + "@crux-kit/editor-tiptap": "*", + "@crux-kit/hooks": "*", + "@crux-kit/intl-date": "*", + "@crux-kit/intl-name": "*", + "@crux-kit/keenicon": "*", + "@crux-kit/local-storage": "*", + "@crux-kit/types": "*", + "@crux-kit/utils": "*", + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@faker-js/faker": "^9.8.0", + "@formatjs/intl-pluralrules": "^5.4.4", + "@formatjs/intl-relativetimeformat": "^11.4.11", + "@hookform/resolvers": "^5.0.1", + "@radix-ui/react-accordion": "^1.2.11", + "@radix-ui/react-alert-dialog": "^1.1.14", + "@radix-ui/react-aspect-ratio": "^1.1.7", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-checkbox": "^1.3.2", + "@radix-ui/react-collapsible": "^1.1.11", + "@radix-ui/react-context-menu": "^2.2.15", + "@radix-ui/react-dialog": "^1.1.14", + "@radix-ui/react-direction": "^1.1.1", + "@radix-ui/react-dropdown-menu": "^2.1.15", + "@radix-ui/react-hover-card": "^1.1.14", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-menubar": "^1.1.15", + "@radix-ui/react-navigation-menu": "^1.2.13", + "@radix-ui/react-popover": "^1.1.14", + "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "^1.3.7", + "@radix-ui/react-scroll-area": "^1.2.9", + "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-slider": "^1.3.5", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-switch": "^1.2.5", + "@radix-ui/react-tabs": "^1.1.12", + "@radix-ui/react-toast": "^1.2.14", + "@radix-ui/react-toggle": "^1.1.9", + "@radix-ui/react-toggle-group": "^1.1.10", + "@radix-ui/react-tooltip": "^1.2.7", + "@react-input/mask": "^2.0.4", + "@tailwindcss/vite": "^4.1.7", + "@tanstack/react-query": "^5.77.2", + "@tanstack/react-query-devtools": "^5.77.0", + "@tanstack/react-table": "^8.21.3", + "@tinymce/tinymce-react": "^6.2.1", + "apexcharts": "4.7.0", + "axios": "^1.12.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk": "^1.1.1", + "date-fns": "^4.1.0", + "date-fns-tz": "^3.2.0", + "input-otp": "^1.4.2", + "leaflet": "^1.9.4", + "lucide-react": "^1.16.0", + "mobx": "^6.15.0", + "mobx-react-lite": "^4.1.1", + "next-themes": "^0.4.6", + "postcss-preset-env": "^10.1.6", + "prismjs": "^1.30.0", + "react": "^19.1.0", + "react-apexcharts": "1.7.0", + "react-day-picker": "^9.7.0", + "react-dom": "^19.1.0", + "react-hook-form": "^7.56.4", + "react-image-crop": "^11.0.10", + "react-inlinesvg": "^4.2.0", + "react-intl": "^7.1.11", + "react-resizable-panels": "^3.0.2", + "react-router": "^7.6.1", + "react-router-dom": "^7.6.1", + "sonner": "^2.0.3", + "tailwind-merge": "^3.3.0", + "tailwindcss-animate": "^1.0.7", + "throttle-debounce": "^5.0.2", + "tinymce": "^7.9.1", + "uuid": "^11.1.0", + "vaul": "^1.1.2", + "vite-plugin-windicss": "^1.9.4", + "zod": "^3.25.32" + }, + "devDependencies": { + "@tailwindcss/typography": "^0.5.19", + "@types/leaflet": "^1.9.18", + "@types/prismjs": "^1.26.5", + "@types/react": "^19.1.6", + "@types/react-dom": "^19.1.5", + "@types/throttle-debounce": "^5.0.2", + "@vitejs/plugin-react": "^4.5.0", + "autoprefixer": "^10.4.21", + "dotenv": "^16.5.0", + "globals": "^16.1.0", + "postcss": "^8.5.3", + "tailwindcss": "^4.1.7", + "tsx": "^4.19.4", + "vite": "^6.3.5", + "vitest": "^4.1.9" + } +} diff --git a/apps/admin/public/media/app/access-control-dark.svg b/apps/admin/public/media/app/access-control-dark.svg new file mode 100644 index 0000000..05dd8be --- /dev/null +++ b/apps/admin/public/media/app/access-control-dark.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/apps/admin/public/media/app/access-control-light.svg b/apps/admin/public/media/app/access-control-light.svg new file mode 100644 index 0000000..6dcefd1 --- /dev/null +++ b/apps/admin/public/media/app/access-control-light.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/apps/admin/public/media/app/auth-bg.png b/apps/admin/public/media/app/auth-bg.png new file mode 100755 index 0000000..d5fe363 Binary files /dev/null and b/apps/admin/public/media/app/auth-bg.png differ diff --git a/apps/admin/public/media/app/brutal-aggressive-rooster-head-icon.svg b/apps/admin/public/media/app/brutal-aggressive-rooster-head-icon.svg new file mode 100644 index 0000000..c97b538 --- /dev/null +++ b/apps/admin/public/media/app/brutal-aggressive-rooster-head-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/admin/public/media/app/devtools-dark.svg b/apps/admin/public/media/app/devtools-dark.svg new file mode 100644 index 0000000..c3a68ba --- /dev/null +++ b/apps/admin/public/media/app/devtools-dark.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/apps/admin/public/media/app/devtools-light.svg b/apps/admin/public/media/app/devtools-light.svg new file mode 100644 index 0000000..2bcd115 --- /dev/null +++ b/apps/admin/public/media/app/devtools-light.svg @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/apps/admin/public/media/app/favicon.ico b/apps/admin/public/media/app/favicon.ico new file mode 100755 index 0000000..48261b2 Binary files /dev/null and b/apps/admin/public/media/app/favicon.ico differ diff --git a/apps/admin/public/media/app/file-manager-dark.svg b/apps/admin/public/media/app/file-manager-dark.svg new file mode 100644 index 0000000..0de5d07 --- /dev/null +++ b/apps/admin/public/media/app/file-manager-dark.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/apps/admin/public/media/app/file-manager-light.svg b/apps/admin/public/media/app/file-manager-light.svg new file mode 100644 index 0000000..34ae081 --- /dev/null +++ b/apps/admin/public/media/app/file-manager-light.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/apps/admin/public/media/app/logo-dark.svg b/apps/admin/public/media/app/logo-dark.svg new file mode 100755 index 0000000..de38452 --- /dev/null +++ b/apps/admin/public/media/app/logo-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/app/logo-light.svg b/apps/admin/public/media/app/logo-light.svg new file mode 100755 index 0000000..5ec6677 --- /dev/null +++ b/apps/admin/public/media/app/logo-light.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/app/web-studio-dark.svg b/apps/admin/public/media/app/web-studio-dark.svg new file mode 100644 index 0000000..73e0edf --- /dev/null +++ b/apps/admin/public/media/app/web-studio-dark.svg @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/apps/admin/public/media/app/web-studio-light.svg b/apps/admin/public/media/app/web-studio-light.svg new file mode 100644 index 0000000..c07b85e --- /dev/null +++ b/apps/admin/public/media/app/web-studio-light.svg @@ -0,0 +1,11 @@ + + + + + diff --git a/apps/admin/public/media/avatars/blank.png b/apps/admin/public/media/avatars/blank.png new file mode 100755 index 0000000..278fe96 Binary files /dev/null and b/apps/admin/public/media/avatars/blank.png differ diff --git a/apps/admin/public/media/file-types/ai.svg b/apps/admin/public/media/file-types/ai.svg new file mode 100755 index 0000000..80970d9 --- /dev/null +++ b/apps/admin/public/media/file-types/ai.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/apk.svg b/apps/admin/public/media/file-types/apk.svg new file mode 100755 index 0000000..4f594fc --- /dev/null +++ b/apps/admin/public/media/file-types/apk.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/css.svg b/apps/admin/public/media/file-types/css.svg new file mode 100755 index 0000000..c3734d8 --- /dev/null +++ b/apps/admin/public/media/file-types/css.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/disc.svg b/apps/admin/public/media/file-types/disc.svg new file mode 100755 index 0000000..d8ca4f0 --- /dev/null +++ b/apps/admin/public/media/file-types/disc.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/doc.svg b/apps/admin/public/media/file-types/doc.svg new file mode 100755 index 0000000..5932718 --- /dev/null +++ b/apps/admin/public/media/file-types/doc.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/excel.svg b/apps/admin/public/media/file-types/excel.svg new file mode 100755 index 0000000..e384c15 --- /dev/null +++ b/apps/admin/public/media/file-types/excel.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/figma.svg b/apps/admin/public/media/file-types/figma.svg new file mode 100755 index 0000000..35e2bb2 --- /dev/null +++ b/apps/admin/public/media/file-types/figma.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/file-types/font.svg b/apps/admin/public/media/file-types/font.svg new file mode 100755 index 0000000..b81a7f1 --- /dev/null +++ b/apps/admin/public/media/file-types/font.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/image.svg b/apps/admin/public/media/file-types/image.svg new file mode 100755 index 0000000..cf2ebdc --- /dev/null +++ b/apps/admin/public/media/file-types/image.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/iso.svg b/apps/admin/public/media/file-types/iso.svg new file mode 100755 index 0000000..009d177 --- /dev/null +++ b/apps/admin/public/media/file-types/iso.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/javascript.svg b/apps/admin/public/media/file-types/javascript.svg new file mode 100755 index 0000000..a327c2c --- /dev/null +++ b/apps/admin/public/media/file-types/javascript.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/js.svg b/apps/admin/public/media/file-types/js.svg new file mode 100755 index 0000000..4d0299d --- /dev/null +++ b/apps/admin/public/media/file-types/js.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/mail-1.svg b/apps/admin/public/media/file-types/mail-1.svg new file mode 100755 index 0000000..4c1d5b3 --- /dev/null +++ b/apps/admin/public/media/file-types/mail-1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/mail.svg b/apps/admin/public/media/file-types/mail.svg new file mode 100755 index 0000000..3aa8aea --- /dev/null +++ b/apps/admin/public/media/file-types/mail.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/mp3.svg b/apps/admin/public/media/file-types/mp3.svg new file mode 100755 index 0000000..b308570 --- /dev/null +++ b/apps/admin/public/media/file-types/mp3.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/music.svg b/apps/admin/public/media/file-types/music.svg new file mode 100755 index 0000000..7e84cba --- /dev/null +++ b/apps/admin/public/media/file-types/music.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/pdf.svg b/apps/admin/public/media/file-types/pdf.svg new file mode 100755 index 0000000..7cf2a0a --- /dev/null +++ b/apps/admin/public/media/file-types/pdf.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/php.svg b/apps/admin/public/media/file-types/php.svg new file mode 100755 index 0000000..d964c6c --- /dev/null +++ b/apps/admin/public/media/file-types/php.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/powerpoint.svg b/apps/admin/public/media/file-types/powerpoint.svg new file mode 100755 index 0000000..9d28795 --- /dev/null +++ b/apps/admin/public/media/file-types/powerpoint.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/ppt.svg b/apps/admin/public/media/file-types/ppt.svg new file mode 100755 index 0000000..082e071 --- /dev/null +++ b/apps/admin/public/media/file-types/ppt.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/psd.svg b/apps/admin/public/media/file-types/psd.svg new file mode 100755 index 0000000..1879431 --- /dev/null +++ b/apps/admin/public/media/file-types/psd.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/record.svg b/apps/admin/public/media/file-types/record.svg new file mode 100755 index 0000000..4593fda --- /dev/null +++ b/apps/admin/public/media/file-types/record.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/sql.svg b/apps/admin/public/media/file-types/sql.svg new file mode 100755 index 0000000..3e46a84 --- /dev/null +++ b/apps/admin/public/media/file-types/sql.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/svg.svg b/apps/admin/public/media/file-types/svg.svg new file mode 100755 index 0000000..5815078 --- /dev/null +++ b/apps/admin/public/media/file-types/svg.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/text.svg b/apps/admin/public/media/file-types/text.svg new file mode 100755 index 0000000..cd9716d --- /dev/null +++ b/apps/admin/public/media/file-types/text.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/ttf.svg b/apps/admin/public/media/file-types/ttf.svg new file mode 100755 index 0000000..c63222b --- /dev/null +++ b/apps/admin/public/media/file-types/ttf.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/txt.svg b/apps/admin/public/media/file-types/txt.svg new file mode 100755 index 0000000..03d0d6b --- /dev/null +++ b/apps/admin/public/media/file-types/txt.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/unknown-file.png b/apps/admin/public/media/file-types/unknown-file.png new file mode 100644 index 0000000..69ae32f Binary files /dev/null and b/apps/admin/public/media/file-types/unknown-file.png differ diff --git a/apps/admin/public/media/file-types/vector.svg b/apps/admin/public/media/file-types/vector.svg new file mode 100755 index 0000000..582cd50 --- /dev/null +++ b/apps/admin/public/media/file-types/vector.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/video-1.svg b/apps/admin/public/media/file-types/video-1.svg new file mode 100755 index 0000000..0c9ad67 --- /dev/null +++ b/apps/admin/public/media/file-types/video-1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/video.svg b/apps/admin/public/media/file-types/video.svg new file mode 100755 index 0000000..4488b9f --- /dev/null +++ b/apps/admin/public/media/file-types/video.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/word.svg b/apps/admin/public/media/file-types/word.svg new file mode 100755 index 0000000..3bc7350 --- /dev/null +++ b/apps/admin/public/media/file-types/word.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/xls.svg b/apps/admin/public/media/file-types/xls.svg new file mode 100755 index 0000000..875462d --- /dev/null +++ b/apps/admin/public/media/file-types/xls.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/file-types/zip.svg b/apps/admin/public/media/file-types/zip.svg new file mode 100755 index 0000000..4bd52f3 --- /dev/null +++ b/apps/admin/public/media/file-types/zip.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/files/7z.svg b/apps/admin/public/media/files/7z.svg new file mode 100644 index 0000000..80e82af --- /dev/null +++ b/apps/admin/public/media/files/7z.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/files/Reference.md b/apps/admin/public/media/files/Reference.md new file mode 100644 index 0000000..5f4d717 --- /dev/null +++ b/apps/admin/public/media/files/Reference.md @@ -0,0 +1 @@ +Icons downloaded from [https://www.untitledui.com/resources/file-icons](https://www.untitledui.com/resources/file-icons) diff --git a/apps/admin/public/media/files/aep.svg b/apps/admin/public/media/files/aep.svg new file mode 100644 index 0000000..20c0b9b --- /dev/null +++ b/apps/admin/public/media/files/aep.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/ai.svg b/apps/admin/public/media/files/ai.svg new file mode 100644 index 0000000..d1f8dbf --- /dev/null +++ b/apps/admin/public/media/files/ai.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/audio.svg b/apps/admin/public/media/files/audio.svg new file mode 100644 index 0000000..1f6fae5 --- /dev/null +++ b/apps/admin/public/media/files/audio.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/apps/admin/public/media/files/avi.svg b/apps/admin/public/media/files/avi.svg new file mode 100644 index 0000000..0e42e9e --- /dev/null +++ b/apps/admin/public/media/files/avi.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/code.svg b/apps/admin/public/media/files/code.svg new file mode 100644 index 0000000..ffe024a --- /dev/null +++ b/apps/admin/public/media/files/code.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/apps/admin/public/media/files/css.svg b/apps/admin/public/media/files/css.svg new file mode 100644 index 0000000..5055279 --- /dev/null +++ b/apps/admin/public/media/files/css.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/csv.svg b/apps/admin/public/media/files/csv.svg new file mode 100644 index 0000000..4cac3c2 --- /dev/null +++ b/apps/admin/public/media/files/csv.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/dmg.svg b/apps/admin/public/media/files/dmg.svg new file mode 100644 index 0000000..ad4d131 --- /dev/null +++ b/apps/admin/public/media/files/dmg.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/doc.svg b/apps/admin/public/media/files/doc.svg new file mode 100644 index 0000000..ae57750 --- /dev/null +++ b/apps/admin/public/media/files/doc.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/document.svg b/apps/admin/public/media/files/document.svg new file mode 100644 index 0000000..61e8afa --- /dev/null +++ b/apps/admin/public/media/files/document.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/apps/admin/public/media/files/docx.svg b/apps/admin/public/media/files/docx.svg new file mode 100644 index 0000000..e87df80 --- /dev/null +++ b/apps/admin/public/media/files/docx.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/empty.svg b/apps/admin/public/media/files/empty.svg new file mode 100644 index 0000000..bf1df8a --- /dev/null +++ b/apps/admin/public/media/files/empty.svg @@ -0,0 +1,8 @@ + + + + diff --git a/apps/admin/public/media/files/eps.svg b/apps/admin/public/media/files/eps.svg new file mode 100644 index 0000000..c1db067 --- /dev/null +++ b/apps/admin/public/media/files/eps.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/exe.svg b/apps/admin/public/media/files/exe.svg new file mode 100644 index 0000000..8d6e2a5 --- /dev/null +++ b/apps/admin/public/media/files/exe.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/fig.svg b/apps/admin/public/media/files/fig.svg new file mode 100644 index 0000000..8a69e82 --- /dev/null +++ b/apps/admin/public/media/files/fig.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/folder.svg b/apps/admin/public/media/files/folder.svg new file mode 100644 index 0000000..c7707c6 --- /dev/null +++ b/apps/admin/public/media/files/folder.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/apps/admin/public/media/files/gif.svg b/apps/admin/public/media/files/gif.svg new file mode 100644 index 0000000..e8cf04f --- /dev/null +++ b/apps/admin/public/media/files/gif.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/go.svg b/apps/admin/public/media/files/go.svg new file mode 100644 index 0000000..baeb3f5 --- /dev/null +++ b/apps/admin/public/media/files/go.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/files/gz.svg b/apps/admin/public/media/files/gz.svg new file mode 100644 index 0000000..d8bbdd8 --- /dev/null +++ b/apps/admin/public/media/files/gz.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/files/html.svg b/apps/admin/public/media/files/html.svg new file mode 100644 index 0000000..f9d94ea --- /dev/null +++ b/apps/admin/public/media/files/html.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/image.svg b/apps/admin/public/media/files/image.svg new file mode 100644 index 0000000..4b2ab6c --- /dev/null +++ b/apps/admin/public/media/files/image.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/apps/admin/public/media/files/img.svg b/apps/admin/public/media/files/img.svg new file mode 100644 index 0000000..911c737 --- /dev/null +++ b/apps/admin/public/media/files/img.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/indd.svg b/apps/admin/public/media/files/indd.svg new file mode 100644 index 0000000..de30f7b --- /dev/null +++ b/apps/admin/public/media/files/indd.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/java.svg b/apps/admin/public/media/files/java.svg new file mode 100644 index 0000000..3523557 --- /dev/null +++ b/apps/admin/public/media/files/java.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/jpeg.svg b/apps/admin/public/media/files/jpeg.svg new file mode 100644 index 0000000..79687fa --- /dev/null +++ b/apps/admin/public/media/files/jpeg.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/jpg.svg b/apps/admin/public/media/files/jpg.svg new file mode 100644 index 0000000..270c49a --- /dev/null +++ b/apps/admin/public/media/files/jpg.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/js.svg b/apps/admin/public/media/files/js.svg new file mode 100644 index 0000000..18e269b --- /dev/null +++ b/apps/admin/public/media/files/js.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/json.svg b/apps/admin/public/media/files/json.svg new file mode 100644 index 0000000..260d009 --- /dev/null +++ b/apps/admin/public/media/files/json.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/md.svg b/apps/admin/public/media/files/md.svg new file mode 100644 index 0000000..2065591 --- /dev/null +++ b/apps/admin/public/media/files/md.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/files/mkv.svg b/apps/admin/public/media/files/mkv.svg new file mode 100644 index 0000000..3b0e831 --- /dev/null +++ b/apps/admin/public/media/files/mkv.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/mp3.svg b/apps/admin/public/media/files/mp3.svg new file mode 100644 index 0000000..39e8e1f --- /dev/null +++ b/apps/admin/public/media/files/mp3.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/mp4.svg b/apps/admin/public/media/files/mp4.svg new file mode 100644 index 0000000..64f0598 --- /dev/null +++ b/apps/admin/public/media/files/mp4.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/mpeg.svg b/apps/admin/public/media/files/mpeg.svg new file mode 100644 index 0000000..4fc451f --- /dev/null +++ b/apps/admin/public/media/files/mpeg.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/pdf-simple.svg b/apps/admin/public/media/files/pdf-simple.svg new file mode 100644 index 0000000..c033185 --- /dev/null +++ b/apps/admin/public/media/files/pdf-simple.svg @@ -0,0 +1,12 @@ + + + + + diff --git a/apps/admin/public/media/files/pdf.svg b/apps/admin/public/media/files/pdf.svg new file mode 100644 index 0000000..17eb46d --- /dev/null +++ b/apps/admin/public/media/files/pdf.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/php.svg b/apps/admin/public/media/files/php.svg new file mode 100644 index 0000000..161f507 --- /dev/null +++ b/apps/admin/public/media/files/php.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/files/png.svg b/apps/admin/public/media/files/png.svg new file mode 100644 index 0000000..1454ac8 --- /dev/null +++ b/apps/admin/public/media/files/png.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/ppt.svg b/apps/admin/public/media/files/ppt.svg new file mode 100644 index 0000000..71f8c71 --- /dev/null +++ b/apps/admin/public/media/files/ppt.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/pptx.svg b/apps/admin/public/media/files/pptx.svg new file mode 100644 index 0000000..dff696b --- /dev/null +++ b/apps/admin/public/media/files/pptx.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/psd.svg b/apps/admin/public/media/files/psd.svg new file mode 100644 index 0000000..34365b4 --- /dev/null +++ b/apps/admin/public/media/files/psd.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/py.svg b/apps/admin/public/media/files/py.svg new file mode 100644 index 0000000..312b395 --- /dev/null +++ b/apps/admin/public/media/files/py.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/files/rar.svg b/apps/admin/public/media/files/rar.svg new file mode 100644 index 0000000..4cb4428 --- /dev/null +++ b/apps/admin/public/media/files/rar.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/rss.svg b/apps/admin/public/media/files/rss.svg new file mode 100644 index 0000000..34f6c40 --- /dev/null +++ b/apps/admin/public/media/files/rss.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/rust.svg b/apps/admin/public/media/files/rust.svg new file mode 100644 index 0000000..eabfdcd --- /dev/null +++ b/apps/admin/public/media/files/rust.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/files/spreadsheet.svg b/apps/admin/public/media/files/spreadsheet.svg new file mode 100644 index 0000000..a5cb1da --- /dev/null +++ b/apps/admin/public/media/files/spreadsheet.svg @@ -0,0 +1,15 @@ + + + + + diff --git a/apps/admin/public/media/files/sql.svg b/apps/admin/public/media/files/sql.svg new file mode 100644 index 0000000..dca7ed7 --- /dev/null +++ b/apps/admin/public/media/files/sql.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/svg.svg b/apps/admin/public/media/files/svg.svg new file mode 100644 index 0000000..b621c24 --- /dev/null +++ b/apps/admin/public/media/files/svg.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/tar.svg b/apps/admin/public/media/files/tar.svg new file mode 100644 index 0000000..39ded86 --- /dev/null +++ b/apps/admin/public/media/files/tar.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/files/tiff.svg b/apps/admin/public/media/files/tiff.svg new file mode 100644 index 0000000..0e45d01 --- /dev/null +++ b/apps/admin/public/media/files/tiff.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/txt.svg b/apps/admin/public/media/files/txt.svg new file mode 100644 index 0000000..4618eb5 --- /dev/null +++ b/apps/admin/public/media/files/txt.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/video-2.svg b/apps/admin/public/media/files/video-2.svg new file mode 100644 index 0000000..a636981 --- /dev/null +++ b/apps/admin/public/media/files/video-2.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + diff --git a/apps/admin/public/media/files/video.svg b/apps/admin/public/media/files/video.svg new file mode 100644 index 0000000..2e9e5f0 --- /dev/null +++ b/apps/admin/public/media/files/video.svg @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/apps/admin/public/media/files/wav.svg b/apps/admin/public/media/files/wav.svg new file mode 100644 index 0000000..3fcb43c --- /dev/null +++ b/apps/admin/public/media/files/wav.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/webp.svg b/apps/admin/public/media/files/webp.svg new file mode 100644 index 0000000..4623465 --- /dev/null +++ b/apps/admin/public/media/files/webp.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/xls.svg b/apps/admin/public/media/files/xls.svg new file mode 100644 index 0000000..1e03716 --- /dev/null +++ b/apps/admin/public/media/files/xls.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/xlsx.svg b/apps/admin/public/media/files/xlsx.svg new file mode 100644 index 0000000..ae85fbc --- /dev/null +++ b/apps/admin/public/media/files/xlsx.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/xml.svg b/apps/admin/public/media/files/xml.svg new file mode 100644 index 0000000..a6859ad --- /dev/null +++ b/apps/admin/public/media/files/xml.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/files/yaml.svg b/apps/admin/public/media/files/yaml.svg new file mode 100644 index 0000000..4c4e8bb --- /dev/null +++ b/apps/admin/public/media/files/yaml.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/files/zip.svg b/apps/admin/public/media/files/zip.svg new file mode 100644 index 0000000..c50e3d8 --- /dev/null +++ b/apps/admin/public/media/files/zip.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/apps/admin/public/media/flags/afghanistan.svg b/apps/admin/public/media/flags/afghanistan.svg new file mode 100755 index 0000000..b3cb5bc --- /dev/null +++ b/apps/admin/public/media/flags/afghanistan.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/aland-islands.svg b/apps/admin/public/media/flags/aland-islands.svg new file mode 100755 index 0000000..71ae0d7 --- /dev/null +++ b/apps/admin/public/media/flags/aland-islands.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/albania.svg b/apps/admin/public/media/flags/albania.svg new file mode 100755 index 0000000..53b8683 --- /dev/null +++ b/apps/admin/public/media/flags/albania.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/algeria.svg b/apps/admin/public/media/flags/algeria.svg new file mode 100755 index 0000000..8692d52 --- /dev/null +++ b/apps/admin/public/media/flags/algeria.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/american-samoa.svg b/apps/admin/public/media/flags/american-samoa.svg new file mode 100755 index 0000000..da124ea --- /dev/null +++ b/apps/admin/public/media/flags/american-samoa.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/andorra.svg b/apps/admin/public/media/flags/andorra.svg new file mode 100755 index 0000000..448f90e --- /dev/null +++ b/apps/admin/public/media/flags/andorra.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/angola.svg b/apps/admin/public/media/flags/angola.svg new file mode 100755 index 0000000..734bbf1 --- /dev/null +++ b/apps/admin/public/media/flags/angola.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/anguilla.svg b/apps/admin/public/media/flags/anguilla.svg new file mode 100755 index 0000000..2255268 --- /dev/null +++ b/apps/admin/public/media/flags/anguilla.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/antigua-and-barbuda.svg b/apps/admin/public/media/flags/antigua-and-barbuda.svg new file mode 100755 index 0000000..b4c7c93 --- /dev/null +++ b/apps/admin/public/media/flags/antigua-and-barbuda.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/argentina.svg b/apps/admin/public/media/flags/argentina.svg new file mode 100755 index 0000000..0cd84ab --- /dev/null +++ b/apps/admin/public/media/flags/argentina.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/armenia.svg b/apps/admin/public/media/flags/armenia.svg new file mode 100755 index 0000000..67a5a53 --- /dev/null +++ b/apps/admin/public/media/flags/armenia.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/aruba.svg b/apps/admin/public/media/flags/aruba.svg new file mode 100755 index 0000000..4f53a45 --- /dev/null +++ b/apps/admin/public/media/flags/aruba.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/australia.svg b/apps/admin/public/media/flags/australia.svg new file mode 100755 index 0000000..8fb8c0a --- /dev/null +++ b/apps/admin/public/media/flags/australia.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/austria.svg b/apps/admin/public/media/flags/austria.svg new file mode 100755 index 0000000..0be23ae --- /dev/null +++ b/apps/admin/public/media/flags/austria.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/azerbaijan.svg b/apps/admin/public/media/flags/azerbaijan.svg new file mode 100755 index 0000000..fa12d8d --- /dev/null +++ b/apps/admin/public/media/flags/azerbaijan.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/azores-islands.svg b/apps/admin/public/media/flags/azores-islands.svg new file mode 100755 index 0000000..40b29de --- /dev/null +++ b/apps/admin/public/media/flags/azores-islands.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/bahamas.svg b/apps/admin/public/media/flags/bahamas.svg new file mode 100755 index 0000000..c84792d --- /dev/null +++ b/apps/admin/public/media/flags/bahamas.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/bahrain.svg b/apps/admin/public/media/flags/bahrain.svg new file mode 100755 index 0000000..374a7db --- /dev/null +++ b/apps/admin/public/media/flags/bahrain.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/balearic-islands.svg b/apps/admin/public/media/flags/balearic-islands.svg new file mode 100755 index 0000000..c134fbf --- /dev/null +++ b/apps/admin/public/media/flags/balearic-islands.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/bangladesh.svg b/apps/admin/public/media/flags/bangladesh.svg new file mode 100755 index 0000000..0c948a0 --- /dev/null +++ b/apps/admin/public/media/flags/bangladesh.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/barbados.svg b/apps/admin/public/media/flags/barbados.svg new file mode 100755 index 0000000..bc5d4c1 --- /dev/null +++ b/apps/admin/public/media/flags/barbados.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/basque-country.svg b/apps/admin/public/media/flags/basque-country.svg new file mode 100755 index 0000000..619592a --- /dev/null +++ b/apps/admin/public/media/flags/basque-country.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/belarus.svg b/apps/admin/public/media/flags/belarus.svg new file mode 100755 index 0000000..02d6a04 --- /dev/null +++ b/apps/admin/public/media/flags/belarus.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/belgium.svg b/apps/admin/public/media/flags/belgium.svg new file mode 100755 index 0000000..5359447 --- /dev/null +++ b/apps/admin/public/media/flags/belgium.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/belize.svg b/apps/admin/public/media/flags/belize.svg new file mode 100755 index 0000000..b89ae5f --- /dev/null +++ b/apps/admin/public/media/flags/belize.svg @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/benin.svg b/apps/admin/public/media/flags/benin.svg new file mode 100755 index 0000000..7599965 --- /dev/null +++ b/apps/admin/public/media/flags/benin.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/bermuda.svg b/apps/admin/public/media/flags/bermuda.svg new file mode 100755 index 0000000..7be8ebd --- /dev/null +++ b/apps/admin/public/media/flags/bermuda.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/bhutan.svg b/apps/admin/public/media/flags/bhutan.svg new file mode 100755 index 0000000..31fdde0 --- /dev/null +++ b/apps/admin/public/media/flags/bhutan.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/bolivia.svg b/apps/admin/public/media/flags/bolivia.svg new file mode 100755 index 0000000..ee7868f --- /dev/null +++ b/apps/admin/public/media/flags/bolivia.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/bonaire.svg b/apps/admin/public/media/flags/bonaire.svg new file mode 100755 index 0000000..b7806da --- /dev/null +++ b/apps/admin/public/media/flags/bonaire.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/bosnia-and-herzegovina.svg b/apps/admin/public/media/flags/bosnia-and-herzegovina.svg new file mode 100755 index 0000000..28e70bc --- /dev/null +++ b/apps/admin/public/media/flags/bosnia-and-herzegovina.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/botswana.svg b/apps/admin/public/media/flags/botswana.svg new file mode 100755 index 0000000..69a6911 --- /dev/null +++ b/apps/admin/public/media/flags/botswana.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/brazil.svg b/apps/admin/public/media/flags/brazil.svg new file mode 100755 index 0000000..6d38a61 --- /dev/null +++ b/apps/admin/public/media/flags/brazil.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/british-columbia.svg b/apps/admin/public/media/flags/british-columbia.svg new file mode 100755 index 0000000..9793c4c --- /dev/null +++ b/apps/admin/public/media/flags/british-columbia.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/british-indian-ocean-territory.svg b/apps/admin/public/media/flags/british-indian-ocean-territory.svg new file mode 100755 index 0000000..6e1fcaf --- /dev/null +++ b/apps/admin/public/media/flags/british-indian-ocean-territory.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/british-virgin-islands.svg b/apps/admin/public/media/flags/british-virgin-islands.svg new file mode 100755 index 0000000..52174ad --- /dev/null +++ b/apps/admin/public/media/flags/british-virgin-islands.svg @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/brunei.svg b/apps/admin/public/media/flags/brunei.svg new file mode 100755 index 0000000..4cca334 --- /dev/null +++ b/apps/admin/public/media/flags/brunei.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/bulgaria.svg b/apps/admin/public/media/flags/bulgaria.svg new file mode 100755 index 0000000..60671ef --- /dev/null +++ b/apps/admin/public/media/flags/bulgaria.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/burkina-faso.svg b/apps/admin/public/media/flags/burkina-faso.svg new file mode 100755 index 0000000..694be06 --- /dev/null +++ b/apps/admin/public/media/flags/burkina-faso.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/burundi.svg b/apps/admin/public/media/flags/burundi.svg new file mode 100755 index 0000000..3ffb8c8 --- /dev/null +++ b/apps/admin/public/media/flags/burundi.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/cambodia.svg b/apps/admin/public/media/flags/cambodia.svg new file mode 100755 index 0000000..cbba946 --- /dev/null +++ b/apps/admin/public/media/flags/cambodia.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/cameroon.svg b/apps/admin/public/media/flags/cameroon.svg new file mode 100755 index 0000000..06a0179 --- /dev/null +++ b/apps/admin/public/media/flags/cameroon.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/canada.svg b/apps/admin/public/media/flags/canada.svg new file mode 100755 index 0000000..aa6531c --- /dev/null +++ b/apps/admin/public/media/flags/canada.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/canary-islands.svg b/apps/admin/public/media/flags/canary-islands.svg new file mode 100755 index 0000000..1b55832 --- /dev/null +++ b/apps/admin/public/media/flags/canary-islands.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/cape-verde.svg b/apps/admin/public/media/flags/cape-verde.svg new file mode 100755 index 0000000..71f38fa --- /dev/null +++ b/apps/admin/public/media/flags/cape-verde.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/cayman-islands.svg b/apps/admin/public/media/flags/cayman-islands.svg new file mode 100755 index 0000000..8756e61 --- /dev/null +++ b/apps/admin/public/media/flags/cayman-islands.svg @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/central-african-republic.svg b/apps/admin/public/media/flags/central-african-republic.svg new file mode 100755 index 0000000..00b434a --- /dev/null +++ b/apps/admin/public/media/flags/central-african-republic.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/ceuta.svg b/apps/admin/public/media/flags/ceuta.svg new file mode 100755 index 0000000..38998e1 --- /dev/null +++ b/apps/admin/public/media/flags/ceuta.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/chad.svg b/apps/admin/public/media/flags/chad.svg new file mode 100755 index 0000000..a1afd0d --- /dev/null +++ b/apps/admin/public/media/flags/chad.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/chile.svg b/apps/admin/public/media/flags/chile.svg new file mode 100755 index 0000000..bea60c7 --- /dev/null +++ b/apps/admin/public/media/flags/chile.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/china.svg b/apps/admin/public/media/flags/china.svg new file mode 100755 index 0000000..c4f7a0c --- /dev/null +++ b/apps/admin/public/media/flags/china.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/christmas-island.svg b/apps/admin/public/media/flags/christmas-island.svg new file mode 100755 index 0000000..0107ea6 --- /dev/null +++ b/apps/admin/public/media/flags/christmas-island.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/cocos-island.svg b/apps/admin/public/media/flags/cocos-island.svg new file mode 100755 index 0000000..5868744 --- /dev/null +++ b/apps/admin/public/media/flags/cocos-island.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/colombia.svg b/apps/admin/public/media/flags/colombia.svg new file mode 100755 index 0000000..3f67537 --- /dev/null +++ b/apps/admin/public/media/flags/colombia.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/comoros.svg b/apps/admin/public/media/flags/comoros.svg new file mode 100755 index 0000000..923141a --- /dev/null +++ b/apps/admin/public/media/flags/comoros.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/cook-islands.svg b/apps/admin/public/media/flags/cook-islands.svg new file mode 100755 index 0000000..671a871 --- /dev/null +++ b/apps/admin/public/media/flags/cook-islands.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/corsica.svg b/apps/admin/public/media/flags/corsica.svg new file mode 100755 index 0000000..528f6b1 --- /dev/null +++ b/apps/admin/public/media/flags/corsica.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/costa-rica.svg b/apps/admin/public/media/flags/costa-rica.svg new file mode 100755 index 0000000..596a10e --- /dev/null +++ b/apps/admin/public/media/flags/costa-rica.svg @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/croatia.svg b/apps/admin/public/media/flags/croatia.svg new file mode 100755 index 0000000..b37f9ba --- /dev/null +++ b/apps/admin/public/media/flags/croatia.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/cuba.svg b/apps/admin/public/media/flags/cuba.svg new file mode 100755 index 0000000..b84b10e --- /dev/null +++ b/apps/admin/public/media/flags/cuba.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/curacao.svg b/apps/admin/public/media/flags/curacao.svg new file mode 100755 index 0000000..286b87d --- /dev/null +++ b/apps/admin/public/media/flags/curacao.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/czech-republic.svg b/apps/admin/public/media/flags/czech-republic.svg new file mode 100755 index 0000000..6e082b4 --- /dev/null +++ b/apps/admin/public/media/flags/czech-republic.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/democratic-republic-of-congo.svg b/apps/admin/public/media/flags/democratic-republic-of-congo.svg new file mode 100755 index 0000000..7fd9cc3 --- /dev/null +++ b/apps/admin/public/media/flags/democratic-republic-of-congo.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/denmark.svg b/apps/admin/public/media/flags/denmark.svg new file mode 100755 index 0000000..d2c9e7f --- /dev/null +++ b/apps/admin/public/media/flags/denmark.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/djibouti.svg b/apps/admin/public/media/flags/djibouti.svg new file mode 100755 index 0000000..852b206 --- /dev/null +++ b/apps/admin/public/media/flags/djibouti.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/dominica.svg b/apps/admin/public/media/flags/dominica.svg new file mode 100755 index 0000000..c1228c6 --- /dev/null +++ b/apps/admin/public/media/flags/dominica.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/dominican-republic.svg b/apps/admin/public/media/flags/dominican-republic.svg new file mode 100755 index 0000000..d96b67e --- /dev/null +++ b/apps/admin/public/media/flags/dominican-republic.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/east-timor.svg b/apps/admin/public/media/flags/east-timor.svg new file mode 100755 index 0000000..c6b2e2d --- /dev/null +++ b/apps/admin/public/media/flags/east-timor.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/ecuador.svg b/apps/admin/public/media/flags/ecuador.svg new file mode 100755 index 0000000..4978a74 --- /dev/null +++ b/apps/admin/public/media/flags/ecuador.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/egypt.svg b/apps/admin/public/media/flags/egypt.svg new file mode 100755 index 0000000..065d536 --- /dev/null +++ b/apps/admin/public/media/flags/egypt.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/el-salvador.svg b/apps/admin/public/media/flags/el-salvador.svg new file mode 100755 index 0000000..b2de291 --- /dev/null +++ b/apps/admin/public/media/flags/el-salvador.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/england.svg b/apps/admin/public/media/flags/england.svg new file mode 100755 index 0000000..574257a --- /dev/null +++ b/apps/admin/public/media/flags/england.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/equatorial-guinea.svg b/apps/admin/public/media/flags/equatorial-guinea.svg new file mode 100755 index 0000000..3cb6f88 --- /dev/null +++ b/apps/admin/public/media/flags/equatorial-guinea.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/eritrea.svg b/apps/admin/public/media/flags/eritrea.svg new file mode 100755 index 0000000..0c737c0 --- /dev/null +++ b/apps/admin/public/media/flags/eritrea.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/estonia.svg b/apps/admin/public/media/flags/estonia.svg new file mode 100755 index 0000000..f44b53a --- /dev/null +++ b/apps/admin/public/media/flags/estonia.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/ethiopia.svg b/apps/admin/public/media/flags/ethiopia.svg new file mode 100755 index 0000000..8990365 --- /dev/null +++ b/apps/admin/public/media/flags/ethiopia.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/european-union.svg b/apps/admin/public/media/flags/european-union.svg new file mode 100755 index 0000000..76377e8 --- /dev/null +++ b/apps/admin/public/media/flags/european-union.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/falkland-islands.svg b/apps/admin/public/media/flags/falkland-islands.svg new file mode 100755 index 0000000..f5f0c22 --- /dev/null +++ b/apps/admin/public/media/flags/falkland-islands.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/fiji.svg b/apps/admin/public/media/flags/fiji.svg new file mode 100755 index 0000000..21b61b7 --- /dev/null +++ b/apps/admin/public/media/flags/fiji.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/finland.svg b/apps/admin/public/media/flags/finland.svg new file mode 100755 index 0000000..bae8824 --- /dev/null +++ b/apps/admin/public/media/flags/finland.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/flag.svg b/apps/admin/public/media/flags/flag.svg new file mode 100755 index 0000000..2f091d5 --- /dev/null +++ b/apps/admin/public/media/flags/flag.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/france.svg b/apps/admin/public/media/flags/france.svg new file mode 100755 index 0000000..d271892 --- /dev/null +++ b/apps/admin/public/media/flags/france.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/french-polynesia.svg b/apps/admin/public/media/flags/french-polynesia.svg new file mode 100755 index 0000000..9eb56ae --- /dev/null +++ b/apps/admin/public/media/flags/french-polynesia.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/gabon.svg b/apps/admin/public/media/flags/gabon.svg new file mode 100755 index 0000000..e7590c7 --- /dev/null +++ b/apps/admin/public/media/flags/gabon.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/galapagos-islands.svg b/apps/admin/public/media/flags/galapagos-islands.svg new file mode 100755 index 0000000..5c9bb4a --- /dev/null +++ b/apps/admin/public/media/flags/galapagos-islands.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/gambia.svg b/apps/admin/public/media/flags/gambia.svg new file mode 100755 index 0000000..db309a4 --- /dev/null +++ b/apps/admin/public/media/flags/gambia.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/georgia.svg b/apps/admin/public/media/flags/georgia.svg new file mode 100755 index 0000000..19aeac1 --- /dev/null +++ b/apps/admin/public/media/flags/georgia.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/germany.svg b/apps/admin/public/media/flags/germany.svg new file mode 100755 index 0000000..4290c77 --- /dev/null +++ b/apps/admin/public/media/flags/germany.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/ghana.svg b/apps/admin/public/media/flags/ghana.svg new file mode 100755 index 0000000..3f83f4d --- /dev/null +++ b/apps/admin/public/media/flags/ghana.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/gibraltar.svg b/apps/admin/public/media/flags/gibraltar.svg new file mode 100755 index 0000000..d7c167e --- /dev/null +++ b/apps/admin/public/media/flags/gibraltar.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/greece.svg b/apps/admin/public/media/flags/greece.svg new file mode 100755 index 0000000..9632b6f --- /dev/null +++ b/apps/admin/public/media/flags/greece.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/greenland.svg b/apps/admin/public/media/flags/greenland.svg new file mode 100755 index 0000000..c2b7355 --- /dev/null +++ b/apps/admin/public/media/flags/greenland.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/grenada.svg b/apps/admin/public/media/flags/grenada.svg new file mode 100755 index 0000000..9ec3356 --- /dev/null +++ b/apps/admin/public/media/flags/grenada.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/guam.svg b/apps/admin/public/media/flags/guam.svg new file mode 100755 index 0000000..64bf9fd --- /dev/null +++ b/apps/admin/public/media/flags/guam.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/guatemala.svg b/apps/admin/public/media/flags/guatemala.svg new file mode 100755 index 0000000..4b4ff32 --- /dev/null +++ b/apps/admin/public/media/flags/guatemala.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/guernsey.svg b/apps/admin/public/media/flags/guernsey.svg new file mode 100755 index 0000000..250079e --- /dev/null +++ b/apps/admin/public/media/flags/guernsey.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/guinea-bissau.svg b/apps/admin/public/media/flags/guinea-bissau.svg new file mode 100755 index 0000000..03c737b --- /dev/null +++ b/apps/admin/public/media/flags/guinea-bissau.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/guinea.svg b/apps/admin/public/media/flags/guinea.svg new file mode 100755 index 0000000..309f35d --- /dev/null +++ b/apps/admin/public/media/flags/guinea.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/haiti.svg b/apps/admin/public/media/flags/haiti.svg new file mode 100755 index 0000000..fd0497d --- /dev/null +++ b/apps/admin/public/media/flags/haiti.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/hawaii.svg b/apps/admin/public/media/flags/hawaii.svg new file mode 100755 index 0000000..4955f12 --- /dev/null +++ b/apps/admin/public/media/flags/hawaii.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/honduras.svg b/apps/admin/public/media/flags/honduras.svg new file mode 100755 index 0000000..08d48d8 --- /dev/null +++ b/apps/admin/public/media/flags/honduras.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/hong-kong.svg b/apps/admin/public/media/flags/hong-kong.svg new file mode 100755 index 0000000..bc23f8a --- /dev/null +++ b/apps/admin/public/media/flags/hong-kong.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/hungary.svg b/apps/admin/public/media/flags/hungary.svg new file mode 100755 index 0000000..62a7816 --- /dev/null +++ b/apps/admin/public/media/flags/hungary.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/iceland.svg b/apps/admin/public/media/flags/iceland.svg new file mode 100755 index 0000000..93a5806 --- /dev/null +++ b/apps/admin/public/media/flags/iceland.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/india.svg b/apps/admin/public/media/flags/india.svg new file mode 100755 index 0000000..a35952d --- /dev/null +++ b/apps/admin/public/media/flags/india.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/indonesia.svg b/apps/admin/public/media/flags/indonesia.svg new file mode 100755 index 0000000..2f61500 --- /dev/null +++ b/apps/admin/public/media/flags/indonesia.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/iran.svg b/apps/admin/public/media/flags/iran.svg new file mode 100755 index 0000000..8f00529 --- /dev/null +++ b/apps/admin/public/media/flags/iran.svg @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/iraq.svg b/apps/admin/public/media/flags/iraq.svg new file mode 100755 index 0000000..a78b6e9 --- /dev/null +++ b/apps/admin/public/media/flags/iraq.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/ireland.svg b/apps/admin/public/media/flags/ireland.svg new file mode 100755 index 0000000..c1f75ba --- /dev/null +++ b/apps/admin/public/media/flags/ireland.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/isle-of-man.svg b/apps/admin/public/media/flags/isle-of-man.svg new file mode 100755 index 0000000..9ff50f6 --- /dev/null +++ b/apps/admin/public/media/flags/isle-of-man.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/israel.svg b/apps/admin/public/media/flags/israel.svg new file mode 100755 index 0000000..0c1f226 --- /dev/null +++ b/apps/admin/public/media/flags/israel.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/italy.svg b/apps/admin/public/media/flags/italy.svg new file mode 100755 index 0000000..2c3a2e3 --- /dev/null +++ b/apps/admin/public/media/flags/italy.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/ivory-coast.svg b/apps/admin/public/media/flags/ivory-coast.svg new file mode 100755 index 0000000..eea20db --- /dev/null +++ b/apps/admin/public/media/flags/ivory-coast.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/jamaica.svg b/apps/admin/public/media/flags/jamaica.svg new file mode 100755 index 0000000..a709601 --- /dev/null +++ b/apps/admin/public/media/flags/jamaica.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/japan.svg b/apps/admin/public/media/flags/japan.svg new file mode 100755 index 0000000..7d0e0cb --- /dev/null +++ b/apps/admin/public/media/flags/japan.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/jersey.svg b/apps/admin/public/media/flags/jersey.svg new file mode 100755 index 0000000..04130bb --- /dev/null +++ b/apps/admin/public/media/flags/jersey.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/jordan.svg b/apps/admin/public/media/flags/jordan.svg new file mode 100755 index 0000000..d05aa3d --- /dev/null +++ b/apps/admin/public/media/flags/jordan.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/kazakhstan.svg b/apps/admin/public/media/flags/kazakhstan.svg new file mode 100755 index 0000000..40975f7 --- /dev/null +++ b/apps/admin/public/media/flags/kazakhstan.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/kenya.svg b/apps/admin/public/media/flags/kenya.svg new file mode 100755 index 0000000..12ef6bc --- /dev/null +++ b/apps/admin/public/media/flags/kenya.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/kiribati.svg b/apps/admin/public/media/flags/kiribati.svg new file mode 100755 index 0000000..700fa69 --- /dev/null +++ b/apps/admin/public/media/flags/kiribati.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/kosovo.svg b/apps/admin/public/media/flags/kosovo.svg new file mode 100755 index 0000000..7a9aea7 --- /dev/null +++ b/apps/admin/public/media/flags/kosovo.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/kuwait.svg b/apps/admin/public/media/flags/kuwait.svg new file mode 100755 index 0000000..5f9514f --- /dev/null +++ b/apps/admin/public/media/flags/kuwait.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/kyrgyzstan.svg b/apps/admin/public/media/flags/kyrgyzstan.svg new file mode 100755 index 0000000..646fd34 --- /dev/null +++ b/apps/admin/public/media/flags/kyrgyzstan.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/laos.svg b/apps/admin/public/media/flags/laos.svg new file mode 100755 index 0000000..d05646e --- /dev/null +++ b/apps/admin/public/media/flags/laos.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/latvia.svg b/apps/admin/public/media/flags/latvia.svg new file mode 100755 index 0000000..a2e0615 --- /dev/null +++ b/apps/admin/public/media/flags/latvia.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/lebanon.svg b/apps/admin/public/media/flags/lebanon.svg new file mode 100755 index 0000000..f41f74f --- /dev/null +++ b/apps/admin/public/media/flags/lebanon.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/lesotho.svg b/apps/admin/public/media/flags/lesotho.svg new file mode 100755 index 0000000..57f22a4 --- /dev/null +++ b/apps/admin/public/media/flags/lesotho.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/liberia.svg b/apps/admin/public/media/flags/liberia.svg new file mode 100755 index 0000000..b0f6ecb --- /dev/null +++ b/apps/admin/public/media/flags/liberia.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/libya.svg b/apps/admin/public/media/flags/libya.svg new file mode 100755 index 0000000..33e2c2f --- /dev/null +++ b/apps/admin/public/media/flags/libya.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/liechtenstein.svg b/apps/admin/public/media/flags/liechtenstein.svg new file mode 100755 index 0000000..b6075b9 --- /dev/null +++ b/apps/admin/public/media/flags/liechtenstein.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/lithuania.svg b/apps/admin/public/media/flags/lithuania.svg new file mode 100755 index 0000000..e2ae265 --- /dev/null +++ b/apps/admin/public/media/flags/lithuania.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/luxembourg.svg b/apps/admin/public/media/flags/luxembourg.svg new file mode 100755 index 0000000..c81d754 --- /dev/null +++ b/apps/admin/public/media/flags/luxembourg.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/macao.svg b/apps/admin/public/media/flags/macao.svg new file mode 100755 index 0000000..25cbedc --- /dev/null +++ b/apps/admin/public/media/flags/macao.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/madagascar.svg b/apps/admin/public/media/flags/madagascar.svg new file mode 100755 index 0000000..7b0360b --- /dev/null +++ b/apps/admin/public/media/flags/madagascar.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/madeira.svg b/apps/admin/public/media/flags/madeira.svg new file mode 100755 index 0000000..202611f --- /dev/null +++ b/apps/admin/public/media/flags/madeira.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/malawi.svg b/apps/admin/public/media/flags/malawi.svg new file mode 100755 index 0000000..dd13a37 --- /dev/null +++ b/apps/admin/public/media/flags/malawi.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/malaysia.svg b/apps/admin/public/media/flags/malaysia.svg new file mode 100755 index 0000000..d54136a --- /dev/null +++ b/apps/admin/public/media/flags/malaysia.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/maldives.svg b/apps/admin/public/media/flags/maldives.svg new file mode 100755 index 0000000..1459140 --- /dev/null +++ b/apps/admin/public/media/flags/maldives.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/mali.svg b/apps/admin/public/media/flags/mali.svg new file mode 100755 index 0000000..9059f81 --- /dev/null +++ b/apps/admin/public/media/flags/mali.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/malta.svg b/apps/admin/public/media/flags/malta.svg new file mode 100755 index 0000000..83bc352 --- /dev/null +++ b/apps/admin/public/media/flags/malta.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/marshall-island.svg b/apps/admin/public/media/flags/marshall-island.svg new file mode 100755 index 0000000..7e51ddc --- /dev/null +++ b/apps/admin/public/media/flags/marshall-island.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/martinique.svg b/apps/admin/public/media/flags/martinique.svg new file mode 100755 index 0000000..e80b49c --- /dev/null +++ b/apps/admin/public/media/flags/martinique.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/mauritania.svg b/apps/admin/public/media/flags/mauritania.svg new file mode 100755 index 0000000..f5dba04 --- /dev/null +++ b/apps/admin/public/media/flags/mauritania.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/mauritius.svg b/apps/admin/public/media/flags/mauritius.svg new file mode 100755 index 0000000..96a7abf --- /dev/null +++ b/apps/admin/public/media/flags/mauritius.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/melilla.svg b/apps/admin/public/media/flags/melilla.svg new file mode 100755 index 0000000..10b20a4 --- /dev/null +++ b/apps/admin/public/media/flags/melilla.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/mexico.svg b/apps/admin/public/media/flags/mexico.svg new file mode 100755 index 0000000..8f5d9b4 --- /dev/null +++ b/apps/admin/public/media/flags/mexico.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/micronesia.svg b/apps/admin/public/media/flags/micronesia.svg new file mode 100755 index 0000000..07f6f94 --- /dev/null +++ b/apps/admin/public/media/flags/micronesia.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/moldova.svg b/apps/admin/public/media/flags/moldova.svg new file mode 100755 index 0000000..5e403f3 --- /dev/null +++ b/apps/admin/public/media/flags/moldova.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/monaco.svg b/apps/admin/public/media/flags/monaco.svg new file mode 100755 index 0000000..565cf5f --- /dev/null +++ b/apps/admin/public/media/flags/monaco.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/mongolia.svg b/apps/admin/public/media/flags/mongolia.svg new file mode 100755 index 0000000..0037448 --- /dev/null +++ b/apps/admin/public/media/flags/mongolia.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/montenegro.svg b/apps/admin/public/media/flags/montenegro.svg new file mode 100755 index 0000000..bf10070 --- /dev/null +++ b/apps/admin/public/media/flags/montenegro.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/montserrat.svg b/apps/admin/public/media/flags/montserrat.svg new file mode 100755 index 0000000..cf1b3ec --- /dev/null +++ b/apps/admin/public/media/flags/montserrat.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/morocco.svg b/apps/admin/public/media/flags/morocco.svg new file mode 100755 index 0000000..5acea60 --- /dev/null +++ b/apps/admin/public/media/flags/morocco.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/mozambique.svg b/apps/admin/public/media/flags/mozambique.svg new file mode 100755 index 0000000..63f579e --- /dev/null +++ b/apps/admin/public/media/flags/mozambique.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/myanmar.svg b/apps/admin/public/media/flags/myanmar.svg new file mode 100755 index 0000000..6bcce7d --- /dev/null +++ b/apps/admin/public/media/flags/myanmar.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/namibia.svg b/apps/admin/public/media/flags/namibia.svg new file mode 100755 index 0000000..dd6fb2c --- /dev/null +++ b/apps/admin/public/media/flags/namibia.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/nato.svg b/apps/admin/public/media/flags/nato.svg new file mode 100755 index 0000000..f8603fe --- /dev/null +++ b/apps/admin/public/media/flags/nato.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/nauru.svg b/apps/admin/public/media/flags/nauru.svg new file mode 100755 index 0000000..e922d0e --- /dev/null +++ b/apps/admin/public/media/flags/nauru.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/nepal.svg b/apps/admin/public/media/flags/nepal.svg new file mode 100755 index 0000000..8009e9e --- /dev/null +++ b/apps/admin/public/media/flags/nepal.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/netherlands.svg b/apps/admin/public/media/flags/netherlands.svg new file mode 100755 index 0000000..2f71030 --- /dev/null +++ b/apps/admin/public/media/flags/netherlands.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/new-zealand.svg b/apps/admin/public/media/flags/new-zealand.svg new file mode 100755 index 0000000..cc0ee7f --- /dev/null +++ b/apps/admin/public/media/flags/new-zealand.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/nicaragua.svg b/apps/admin/public/media/flags/nicaragua.svg new file mode 100755 index 0000000..27b6cca --- /dev/null +++ b/apps/admin/public/media/flags/nicaragua.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/niger.svg b/apps/admin/public/media/flags/niger.svg new file mode 100755 index 0000000..60a73a2 --- /dev/null +++ b/apps/admin/public/media/flags/niger.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/nigeria.svg b/apps/admin/public/media/flags/nigeria.svg new file mode 100755 index 0000000..41da495 --- /dev/null +++ b/apps/admin/public/media/flags/nigeria.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/niue.svg b/apps/admin/public/media/flags/niue.svg new file mode 100755 index 0000000..0c3b6d0 --- /dev/null +++ b/apps/admin/public/media/flags/niue.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/norfolk-island.svg b/apps/admin/public/media/flags/norfolk-island.svg new file mode 100755 index 0000000..2082bdf --- /dev/null +++ b/apps/admin/public/media/flags/norfolk-island.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/north-korea.svg b/apps/admin/public/media/flags/north-korea.svg new file mode 100755 index 0000000..31d1463 --- /dev/null +++ b/apps/admin/public/media/flags/north-korea.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/northern-cyprus.svg b/apps/admin/public/media/flags/northern-cyprus.svg new file mode 100755 index 0000000..0587fe0 --- /dev/null +++ b/apps/admin/public/media/flags/northern-cyprus.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/northern-mariana-islands.svg b/apps/admin/public/media/flags/northern-mariana-islands.svg new file mode 100755 index 0000000..4029970 --- /dev/null +++ b/apps/admin/public/media/flags/northern-mariana-islands.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/norway.svg b/apps/admin/public/media/flags/norway.svg new file mode 100755 index 0000000..46ab6bf --- /dev/null +++ b/apps/admin/public/media/flags/norway.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/oman.svg b/apps/admin/public/media/flags/oman.svg new file mode 100755 index 0000000..5030fca --- /dev/null +++ b/apps/admin/public/media/flags/oman.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/ossetia.svg b/apps/admin/public/media/flags/ossetia.svg new file mode 100755 index 0000000..7d8cdd0 --- /dev/null +++ b/apps/admin/public/media/flags/ossetia.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/pakistan.svg b/apps/admin/public/media/flags/pakistan.svg new file mode 100755 index 0000000..f792bfe --- /dev/null +++ b/apps/admin/public/media/flags/pakistan.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/palau.svg b/apps/admin/public/media/flags/palau.svg new file mode 100755 index 0000000..19623a2 --- /dev/null +++ b/apps/admin/public/media/flags/palau.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/palestine.svg b/apps/admin/public/media/flags/palestine.svg new file mode 100755 index 0000000..0072a44 --- /dev/null +++ b/apps/admin/public/media/flags/palestine.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/panama.svg b/apps/admin/public/media/flags/panama.svg new file mode 100755 index 0000000..e89f18c --- /dev/null +++ b/apps/admin/public/media/flags/panama.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/papua-new-guinea.svg b/apps/admin/public/media/flags/papua-new-guinea.svg new file mode 100755 index 0000000..05a76f9 --- /dev/null +++ b/apps/admin/public/media/flags/papua-new-guinea.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/paraguay.svg b/apps/admin/public/media/flags/paraguay.svg new file mode 100755 index 0000000..8f2e962 --- /dev/null +++ b/apps/admin/public/media/flags/paraguay.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/peru.svg b/apps/admin/public/media/flags/peru.svg new file mode 100755 index 0000000..cd23022 --- /dev/null +++ b/apps/admin/public/media/flags/peru.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/philippines.svg b/apps/admin/public/media/flags/philippines.svg new file mode 100755 index 0000000..a6772d6 --- /dev/null +++ b/apps/admin/public/media/flags/philippines.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/pitcairn-islands.svg b/apps/admin/public/media/flags/pitcairn-islands.svg new file mode 100755 index 0000000..ccd508d --- /dev/null +++ b/apps/admin/public/media/flags/pitcairn-islands.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/poland.svg b/apps/admin/public/media/flags/poland.svg new file mode 100755 index 0000000..f4cd957 --- /dev/null +++ b/apps/admin/public/media/flags/poland.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/portugal.svg b/apps/admin/public/media/flags/portugal.svg new file mode 100755 index 0000000..91a14e6 --- /dev/null +++ b/apps/admin/public/media/flags/portugal.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/puerto-rico.svg b/apps/admin/public/media/flags/puerto-rico.svg new file mode 100755 index 0000000..6622b48 --- /dev/null +++ b/apps/admin/public/media/flags/puerto-rico.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/qatar.svg b/apps/admin/public/media/flags/qatar.svg new file mode 100755 index 0000000..718a769 --- /dev/null +++ b/apps/admin/public/media/flags/qatar.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/rapa-nui.svg b/apps/admin/public/media/flags/rapa-nui.svg new file mode 100755 index 0000000..0cb703e --- /dev/null +++ b/apps/admin/public/media/flags/rapa-nui.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/republic-of-macedonia.svg b/apps/admin/public/media/flags/republic-of-macedonia.svg new file mode 100755 index 0000000..5966f94 --- /dev/null +++ b/apps/admin/public/media/flags/republic-of-macedonia.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/republic-of-the-congo.svg b/apps/admin/public/media/flags/republic-of-the-congo.svg new file mode 100755 index 0000000..1d96ea7 --- /dev/null +++ b/apps/admin/public/media/flags/republic-of-the-congo.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/romania.svg b/apps/admin/public/media/flags/romania.svg new file mode 100755 index 0000000..f274915 --- /dev/null +++ b/apps/admin/public/media/flags/romania.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/russia.svg b/apps/admin/public/media/flags/russia.svg new file mode 100755 index 0000000..17299e2 --- /dev/null +++ b/apps/admin/public/media/flags/russia.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/rwanda.svg b/apps/admin/public/media/flags/rwanda.svg new file mode 100755 index 0000000..18810be --- /dev/null +++ b/apps/admin/public/media/flags/rwanda.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/saba-island.svg b/apps/admin/public/media/flags/saba-island.svg new file mode 100755 index 0000000..fbd7ffc --- /dev/null +++ b/apps/admin/public/media/flags/saba-island.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sahrawi-arab-democratic-republic.svg b/apps/admin/public/media/flags/sahrawi-arab-democratic-republic.svg new file mode 100755 index 0000000..29e3d7f --- /dev/null +++ b/apps/admin/public/media/flags/sahrawi-arab-democratic-republic.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/saint-kitts-and-nevis.svg b/apps/admin/public/media/flags/saint-kitts-and-nevis.svg new file mode 100755 index 0000000..d503337 --- /dev/null +++ b/apps/admin/public/media/flags/saint-kitts-and-nevis.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/samoa.svg b/apps/admin/public/media/flags/samoa.svg new file mode 100755 index 0000000..1327d3f --- /dev/null +++ b/apps/admin/public/media/flags/samoa.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/san-marino.svg b/apps/admin/public/media/flags/san-marino.svg new file mode 100755 index 0000000..3334f79 --- /dev/null +++ b/apps/admin/public/media/flags/san-marino.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sao-tome-and-prince.svg b/apps/admin/public/media/flags/sao-tome-and-prince.svg new file mode 100755 index 0000000..2be137a --- /dev/null +++ b/apps/admin/public/media/flags/sao-tome-and-prince.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sardinia.svg b/apps/admin/public/media/flags/sardinia.svg new file mode 100755 index 0000000..9c122f5 --- /dev/null +++ b/apps/admin/public/media/flags/sardinia.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/saudi-arabia.svg b/apps/admin/public/media/flags/saudi-arabia.svg new file mode 100755 index 0000000..fffb816 --- /dev/null +++ b/apps/admin/public/media/flags/saudi-arabia.svg @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/scotland.svg b/apps/admin/public/media/flags/scotland.svg new file mode 100755 index 0000000..995b18b --- /dev/null +++ b/apps/admin/public/media/flags/scotland.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/senegal.svg b/apps/admin/public/media/flags/senegal.svg new file mode 100755 index 0000000..43aeda2 --- /dev/null +++ b/apps/admin/public/media/flags/senegal.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/serbia.svg b/apps/admin/public/media/flags/serbia.svg new file mode 100755 index 0000000..f2d47b2 --- /dev/null +++ b/apps/admin/public/media/flags/serbia.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/seychelles.svg b/apps/admin/public/media/flags/seychelles.svg new file mode 100755 index 0000000..9c48b97 --- /dev/null +++ b/apps/admin/public/media/flags/seychelles.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sicily.svg b/apps/admin/public/media/flags/sicily.svg new file mode 100755 index 0000000..6b382a4 --- /dev/null +++ b/apps/admin/public/media/flags/sicily.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sierra-leone.svg b/apps/admin/public/media/flags/sierra-leone.svg new file mode 100755 index 0000000..3ef894d --- /dev/null +++ b/apps/admin/public/media/flags/sierra-leone.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/singapore.svg b/apps/admin/public/media/flags/singapore.svg new file mode 100755 index 0000000..c1bbe0d --- /dev/null +++ b/apps/admin/public/media/flags/singapore.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sint-eustatius.svg b/apps/admin/public/media/flags/sint-eustatius.svg new file mode 100755 index 0000000..317526e --- /dev/null +++ b/apps/admin/public/media/flags/sint-eustatius.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sint-maarten.svg b/apps/admin/public/media/flags/sint-maarten.svg new file mode 100755 index 0000000..bf2c035 --- /dev/null +++ b/apps/admin/public/media/flags/sint-maarten.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/slovakia.svg b/apps/admin/public/media/flags/slovakia.svg new file mode 100755 index 0000000..8ca0933 --- /dev/null +++ b/apps/admin/public/media/flags/slovakia.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/slovenia.svg b/apps/admin/public/media/flags/slovenia.svg new file mode 100755 index 0000000..8b63232 --- /dev/null +++ b/apps/admin/public/media/flags/slovenia.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/solomon-islands.svg b/apps/admin/public/media/flags/solomon-islands.svg new file mode 100755 index 0000000..7203b62 --- /dev/null +++ b/apps/admin/public/media/flags/solomon-islands.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/somalia.svg b/apps/admin/public/media/flags/somalia.svg new file mode 100755 index 0000000..3b72d5c --- /dev/null +++ b/apps/admin/public/media/flags/somalia.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/somaliland.svg b/apps/admin/public/media/flags/somaliland.svg new file mode 100755 index 0000000..deb11fe --- /dev/null +++ b/apps/admin/public/media/flags/somaliland.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/south-africa.svg b/apps/admin/public/media/flags/south-africa.svg new file mode 100755 index 0000000..2e657ba --- /dev/null +++ b/apps/admin/public/media/flags/south-africa.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/south-korea.svg b/apps/admin/public/media/flags/south-korea.svg new file mode 100755 index 0000000..acd5c90 --- /dev/null +++ b/apps/admin/public/media/flags/south-korea.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/south-sudan.svg b/apps/admin/public/media/flags/south-sudan.svg new file mode 100755 index 0000000..ac0a21e --- /dev/null +++ b/apps/admin/public/media/flags/south-sudan.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/spain.svg b/apps/admin/public/media/flags/spain.svg new file mode 100755 index 0000000..5f67162 --- /dev/null +++ b/apps/admin/public/media/flags/spain.svg @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sri-lanka.svg b/apps/admin/public/media/flags/sri-lanka.svg new file mode 100755 index 0000000..eaf58c3 --- /dev/null +++ b/apps/admin/public/media/flags/sri-lanka.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/st-barts.svg b/apps/admin/public/media/flags/st-barts.svg new file mode 100755 index 0000000..5205637 --- /dev/null +++ b/apps/admin/public/media/flags/st-barts.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/st-lucia.svg b/apps/admin/public/media/flags/st-lucia.svg new file mode 100755 index 0000000..3d32682 --- /dev/null +++ b/apps/admin/public/media/flags/st-lucia.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/st-vincent-and-the-grenadines.svg b/apps/admin/public/media/flags/st-vincent-and-the-grenadines.svg new file mode 100755 index 0000000..ffe6fee --- /dev/null +++ b/apps/admin/public/media/flags/st-vincent-and-the-grenadines.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sudan.svg b/apps/admin/public/media/flags/sudan.svg new file mode 100755 index 0000000..6df8c2d --- /dev/null +++ b/apps/admin/public/media/flags/sudan.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/suriname.svg b/apps/admin/public/media/flags/suriname.svg new file mode 100755 index 0000000..16f6fa7 --- /dev/null +++ b/apps/admin/public/media/flags/suriname.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/swaziland.svg b/apps/admin/public/media/flags/swaziland.svg new file mode 100755 index 0000000..718aab5 --- /dev/null +++ b/apps/admin/public/media/flags/swaziland.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/sweden.svg b/apps/admin/public/media/flags/sweden.svg new file mode 100755 index 0000000..e27a5f7 --- /dev/null +++ b/apps/admin/public/media/flags/sweden.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/switzerland.svg b/apps/admin/public/media/flags/switzerland.svg new file mode 100755 index 0000000..61e4e81 --- /dev/null +++ b/apps/admin/public/media/flags/switzerland.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/syria.svg b/apps/admin/public/media/flags/syria.svg new file mode 100755 index 0000000..3e98f58 --- /dev/null +++ b/apps/admin/public/media/flags/syria.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/taiwan.svg b/apps/admin/public/media/flags/taiwan.svg new file mode 100755 index 0000000..d1f3671 --- /dev/null +++ b/apps/admin/public/media/flags/taiwan.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/tajikistan.svg b/apps/admin/public/media/flags/tajikistan.svg new file mode 100755 index 0000000..4c1f795 --- /dev/null +++ b/apps/admin/public/media/flags/tajikistan.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/tanzania.svg b/apps/admin/public/media/flags/tanzania.svg new file mode 100755 index 0000000..55f7129 --- /dev/null +++ b/apps/admin/public/media/flags/tanzania.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/thailand.svg b/apps/admin/public/media/flags/thailand.svg new file mode 100755 index 0000000..e5dae5c --- /dev/null +++ b/apps/admin/public/media/flags/thailand.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/tibet.svg b/apps/admin/public/media/flags/tibet.svg new file mode 100755 index 0000000..cc24bc2 --- /dev/null +++ b/apps/admin/public/media/flags/tibet.svg @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/togo.svg b/apps/admin/public/media/flags/togo.svg new file mode 100755 index 0000000..66100af --- /dev/null +++ b/apps/admin/public/media/flags/togo.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/tokelau.svg b/apps/admin/public/media/flags/tokelau.svg new file mode 100755 index 0000000..c48108d --- /dev/null +++ b/apps/admin/public/media/flags/tokelau.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/tonga.svg b/apps/admin/public/media/flags/tonga.svg new file mode 100755 index 0000000..7116131 --- /dev/null +++ b/apps/admin/public/media/flags/tonga.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/transnistria.svg b/apps/admin/public/media/flags/transnistria.svg new file mode 100755 index 0000000..e0439ab --- /dev/null +++ b/apps/admin/public/media/flags/transnistria.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/trinidad-and-tobago.svg b/apps/admin/public/media/flags/trinidad-and-tobago.svg new file mode 100755 index 0000000..72e026f --- /dev/null +++ b/apps/admin/public/media/flags/trinidad-and-tobago.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/tunisia.svg b/apps/admin/public/media/flags/tunisia.svg new file mode 100755 index 0000000..08e4379 --- /dev/null +++ b/apps/admin/public/media/flags/tunisia.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/turkey.svg b/apps/admin/public/media/flags/turkey.svg new file mode 100755 index 0000000..0a5cb9c --- /dev/null +++ b/apps/admin/public/media/flags/turkey.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/turkmenistan.svg b/apps/admin/public/media/flags/turkmenistan.svg new file mode 100755 index 0000000..c130cd7 --- /dev/null +++ b/apps/admin/public/media/flags/turkmenistan.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/turks-and-caicos.svg b/apps/admin/public/media/flags/turks-and-caicos.svg new file mode 100755 index 0000000..17bfea2 --- /dev/null +++ b/apps/admin/public/media/flags/turks-and-caicos.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/tuvalu-1.svg b/apps/admin/public/media/flags/tuvalu-1.svg new file mode 100755 index 0000000..d49cabb --- /dev/null +++ b/apps/admin/public/media/flags/tuvalu-1.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/tuvalu.svg b/apps/admin/public/media/flags/tuvalu.svg new file mode 100755 index 0000000..871d1de --- /dev/null +++ b/apps/admin/public/media/flags/tuvalu.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/uganda.svg b/apps/admin/public/media/flags/uganda.svg new file mode 100755 index 0000000..926bc9d --- /dev/null +++ b/apps/admin/public/media/flags/uganda.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/uk.svg b/apps/admin/public/media/flags/uk.svg new file mode 100755 index 0000000..383c9e8 --- /dev/null +++ b/apps/admin/public/media/flags/uk.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/ukraine.svg b/apps/admin/public/media/flags/ukraine.svg new file mode 100755 index 0000000..04b8a32 --- /dev/null +++ b/apps/admin/public/media/flags/ukraine.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/united-arab-emirates.svg b/apps/admin/public/media/flags/united-arab-emirates.svg new file mode 100755 index 0000000..c507b8f --- /dev/null +++ b/apps/admin/public/media/flags/united-arab-emirates.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/united-kingdom.svg b/apps/admin/public/media/flags/united-kingdom.svg new file mode 100755 index 0000000..bab1dbd --- /dev/null +++ b/apps/admin/public/media/flags/united-kingdom.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/united-nations.svg b/apps/admin/public/media/flags/united-nations.svg new file mode 100755 index 0000000..c4db01a --- /dev/null +++ b/apps/admin/public/media/flags/united-nations.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/united-states.svg b/apps/admin/public/media/flags/united-states.svg new file mode 100755 index 0000000..37ff08d --- /dev/null +++ b/apps/admin/public/media/flags/united-states.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/uruguay.svg b/apps/admin/public/media/flags/uruguay.svg new file mode 100755 index 0000000..9d5ea42 --- /dev/null +++ b/apps/admin/public/media/flags/uruguay.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/uzbekistan.svg b/apps/admin/public/media/flags/uzbekistan.svg new file mode 100755 index 0000000..265704a --- /dev/null +++ b/apps/admin/public/media/flags/uzbekistan.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/vanuatu.svg b/apps/admin/public/media/flags/vanuatu.svg new file mode 100755 index 0000000..fcbd354 --- /dev/null +++ b/apps/admin/public/media/flags/vanuatu.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/vatican-city.svg b/apps/admin/public/media/flags/vatican-city.svg new file mode 100755 index 0000000..62464e7 --- /dev/null +++ b/apps/admin/public/media/flags/vatican-city.svg @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/venezuela.svg b/apps/admin/public/media/flags/venezuela.svg new file mode 100755 index 0000000..e35b132 --- /dev/null +++ b/apps/admin/public/media/flags/venezuela.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/vietnam.svg b/apps/admin/public/media/flags/vietnam.svg new file mode 100755 index 0000000..08f02fb --- /dev/null +++ b/apps/admin/public/media/flags/vietnam.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/virgin-islands.svg b/apps/admin/public/media/flags/virgin-islands.svg new file mode 100755 index 0000000..bcb036f --- /dev/null +++ b/apps/admin/public/media/flags/virgin-islands.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/wales.svg b/apps/admin/public/media/flags/wales.svg new file mode 100755 index 0000000..3130bca --- /dev/null +++ b/apps/admin/public/media/flags/wales.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/yemen.svg b/apps/admin/public/media/flags/yemen.svg new file mode 100755 index 0000000..dbe7eb0 --- /dev/null +++ b/apps/admin/public/media/flags/yemen.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/zambia.svg b/apps/admin/public/media/flags/zambia.svg new file mode 100755 index 0000000..50a5fbc --- /dev/null +++ b/apps/admin/public/media/flags/zambia.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/flags/zimbabwe.svg b/apps/admin/public/media/flags/zimbabwe.svg new file mode 100755 index 0000000..cd3c0b3 --- /dev/null +++ b/apps/admin/public/media/flags/zimbabwe.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/1-dark.svg b/apps/admin/public/media/illustrations/1-dark.svg new file mode 100755 index 0000000..454708b --- /dev/null +++ b/apps/admin/public/media/illustrations/1-dark.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/1.svg b/apps/admin/public/media/illustrations/1.svg new file mode 100755 index 0000000..a3562f6 --- /dev/null +++ b/apps/admin/public/media/illustrations/1.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/10-dark.svg b/apps/admin/public/media/illustrations/10-dark.svg new file mode 100755 index 0000000..94e2da7 --- /dev/null +++ b/apps/admin/public/media/illustrations/10-dark.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/10.svg b/apps/admin/public/media/illustrations/10.svg new file mode 100755 index 0000000..0eb8330 --- /dev/null +++ b/apps/admin/public/media/illustrations/10.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/11-dark.svg b/apps/admin/public/media/illustrations/11-dark.svg new file mode 100755 index 0000000..8845d6e --- /dev/null +++ b/apps/admin/public/media/illustrations/11-dark.svg @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/11.svg b/apps/admin/public/media/illustrations/11.svg new file mode 100755 index 0000000..e87c588 --- /dev/null +++ b/apps/admin/public/media/illustrations/11.svg @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/12.svg b/apps/admin/public/media/illustrations/12.svg new file mode 100755 index 0000000..07b097d --- /dev/null +++ b/apps/admin/public/media/illustrations/12.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/13.svg b/apps/admin/public/media/illustrations/13.svg new file mode 100755 index 0000000..4a83ad1 --- /dev/null +++ b/apps/admin/public/media/illustrations/13.svg @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/14.svg b/apps/admin/public/media/illustrations/14.svg new file mode 100755 index 0000000..4720b49 --- /dev/null +++ b/apps/admin/public/media/illustrations/14.svg @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/15.svg b/apps/admin/public/media/illustrations/15.svg new file mode 100755 index 0000000..5d68a9e --- /dev/null +++ b/apps/admin/public/media/illustrations/15.svg @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/16.svg b/apps/admin/public/media/illustrations/16.svg new file mode 100755 index 0000000..54b8ac2 --- /dev/null +++ b/apps/admin/public/media/illustrations/16.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/17.svg b/apps/admin/public/media/illustrations/17.svg new file mode 100755 index 0000000..ecf87b2 --- /dev/null +++ b/apps/admin/public/media/illustrations/17.svg @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/18-dark.svg b/apps/admin/public/media/illustrations/18-dark.svg new file mode 100755 index 0000000..d2fc6cd --- /dev/null +++ b/apps/admin/public/media/illustrations/18-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/illustrations/18.svg b/apps/admin/public/media/illustrations/18.svg new file mode 100755 index 0000000..4edf911 --- /dev/null +++ b/apps/admin/public/media/illustrations/18.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/illustrations/19-dark.svg b/apps/admin/public/media/illustrations/19-dark.svg new file mode 100755 index 0000000..ec21a49 --- /dev/null +++ b/apps/admin/public/media/illustrations/19-dark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/admin/public/media/illustrations/19.svg b/apps/admin/public/media/illustrations/19.svg new file mode 100755 index 0000000..736ade2 --- /dev/null +++ b/apps/admin/public/media/illustrations/19.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/admin/public/media/illustrations/2-dark.svg b/apps/admin/public/media/illustrations/2-dark.svg new file mode 100755 index 0000000..ec25b88 --- /dev/null +++ b/apps/admin/public/media/illustrations/2-dark.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/2.svg b/apps/admin/public/media/illustrations/2.svg new file mode 100755 index 0000000..c8fb6c5 --- /dev/null +++ b/apps/admin/public/media/illustrations/2.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/20-dark.svg b/apps/admin/public/media/illustrations/20-dark.svg new file mode 100755 index 0000000..5c57507 --- /dev/null +++ b/apps/admin/public/media/illustrations/20-dark.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/20.svg b/apps/admin/public/media/illustrations/20.svg new file mode 100755 index 0000000..2c3308d --- /dev/null +++ b/apps/admin/public/media/illustrations/20.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/21-dark.svg b/apps/admin/public/media/illustrations/21-dark.svg new file mode 100755 index 0000000..c22b539 --- /dev/null +++ b/apps/admin/public/media/illustrations/21-dark.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/21.svg b/apps/admin/public/media/illustrations/21.svg new file mode 100755 index 0000000..f8e1a2b --- /dev/null +++ b/apps/admin/public/media/illustrations/21.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/22-dark.svg b/apps/admin/public/media/illustrations/22-dark.svg new file mode 100755 index 0000000..776b83e --- /dev/null +++ b/apps/admin/public/media/illustrations/22-dark.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/22.svg b/apps/admin/public/media/illustrations/22.svg new file mode 100755 index 0000000..722a3ca --- /dev/null +++ b/apps/admin/public/media/illustrations/22.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/23-dark.svg b/apps/admin/public/media/illustrations/23-dark.svg new file mode 100755 index 0000000..754852c --- /dev/null +++ b/apps/admin/public/media/illustrations/23-dark.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/23.svg b/apps/admin/public/media/illustrations/23.svg new file mode 100755 index 0000000..317cc18 --- /dev/null +++ b/apps/admin/public/media/illustrations/23.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/24.svg b/apps/admin/public/media/illustrations/24.svg new file mode 100755 index 0000000..e883157 --- /dev/null +++ b/apps/admin/public/media/illustrations/24.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/illustrations/25.svg b/apps/admin/public/media/illustrations/25.svg new file mode 100755 index 0000000..131cf0a --- /dev/null +++ b/apps/admin/public/media/illustrations/25.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/admin/public/media/illustrations/26.svg b/apps/admin/public/media/illustrations/26.svg new file mode 100755 index 0000000..580be2d --- /dev/null +++ b/apps/admin/public/media/illustrations/26.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/admin/public/media/illustrations/27.svg b/apps/admin/public/media/illustrations/27.svg new file mode 100755 index 0000000..ae4a6dd --- /dev/null +++ b/apps/admin/public/media/illustrations/27.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/illustrations/28-dark.svg b/apps/admin/public/media/illustrations/28-dark.svg new file mode 100755 index 0000000..fbb8089 --- /dev/null +++ b/apps/admin/public/media/illustrations/28-dark.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/28.svg b/apps/admin/public/media/illustrations/28.svg new file mode 100755 index 0000000..90a831f --- /dev/null +++ b/apps/admin/public/media/illustrations/28.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/29-dark.svg b/apps/admin/public/media/illustrations/29-dark.svg new file mode 100755 index 0000000..a362576 --- /dev/null +++ b/apps/admin/public/media/illustrations/29-dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/illustrations/29.svg b/apps/admin/public/media/illustrations/29.svg new file mode 100755 index 0000000..2e52329 --- /dev/null +++ b/apps/admin/public/media/illustrations/29.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/admin/public/media/illustrations/3-dark.svg b/apps/admin/public/media/illustrations/3-dark.svg new file mode 100755 index 0000000..cc76dac --- /dev/null +++ b/apps/admin/public/media/illustrations/3-dark.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/3.svg b/apps/admin/public/media/illustrations/3.svg new file mode 100755 index 0000000..ec9a574 --- /dev/null +++ b/apps/admin/public/media/illustrations/3.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/30-dark.svg b/apps/admin/public/media/illustrations/30-dark.svg new file mode 100755 index 0000000..6345789 --- /dev/null +++ b/apps/admin/public/media/illustrations/30-dark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/admin/public/media/illustrations/30.svg b/apps/admin/public/media/illustrations/30.svg new file mode 100755 index 0000000..d1a493d --- /dev/null +++ b/apps/admin/public/media/illustrations/30.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/apps/admin/public/media/illustrations/31-dark.svg b/apps/admin/public/media/illustrations/31-dark.svg new file mode 100755 index 0000000..cc051d3 --- /dev/null +++ b/apps/admin/public/media/illustrations/31-dark.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/31.svg b/apps/admin/public/media/illustrations/31.svg new file mode 100755 index 0000000..f3d20a3 --- /dev/null +++ b/apps/admin/public/media/illustrations/31.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/32-dark.svg b/apps/admin/public/media/illustrations/32-dark.svg new file mode 100755 index 0000000..18ae088 --- /dev/null +++ b/apps/admin/public/media/illustrations/32-dark.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/32.svg b/apps/admin/public/media/illustrations/32.svg new file mode 100755 index 0000000..6e8e0b6 --- /dev/null +++ b/apps/admin/public/media/illustrations/32.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/33-dark.svg b/apps/admin/public/media/illustrations/33-dark.svg new file mode 100755 index 0000000..10d45ef --- /dev/null +++ b/apps/admin/public/media/illustrations/33-dark.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/33.svg b/apps/admin/public/media/illustrations/33.svg new file mode 100755 index 0000000..1333f4a --- /dev/null +++ b/apps/admin/public/media/illustrations/33.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/34-dark.svg b/apps/admin/public/media/illustrations/34-dark.svg new file mode 100755 index 0000000..47df883 --- /dev/null +++ b/apps/admin/public/media/illustrations/34-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/illustrations/34.svg b/apps/admin/public/media/illustrations/34.svg new file mode 100755 index 0000000..6ab8850 --- /dev/null +++ b/apps/admin/public/media/illustrations/34.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/apps/admin/public/media/illustrations/35-dark.svg b/apps/admin/public/media/illustrations/35-dark.svg new file mode 100755 index 0000000..4604e10 --- /dev/null +++ b/apps/admin/public/media/illustrations/35-dark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/35.svg b/apps/admin/public/media/illustrations/35.svg new file mode 100755 index 0000000..736dc00 --- /dev/null +++ b/apps/admin/public/media/illustrations/35.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/admin/public/media/illustrations/4-dark.svg b/apps/admin/public/media/illustrations/4-dark.svg new file mode 100755 index 0000000..1c8eabf --- /dev/null +++ b/apps/admin/public/media/illustrations/4-dark.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/4.svg b/apps/admin/public/media/illustrations/4.svg new file mode 100755 index 0000000..ba22a72 --- /dev/null +++ b/apps/admin/public/media/illustrations/4.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/5-dark.svg b/apps/admin/public/media/illustrations/5-dark.svg new file mode 100755 index 0000000..7c2704a --- /dev/null +++ b/apps/admin/public/media/illustrations/5-dark.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/5.svg b/apps/admin/public/media/illustrations/5.svg new file mode 100755 index 0000000..08c0c00 --- /dev/null +++ b/apps/admin/public/media/illustrations/5.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/6.svg b/apps/admin/public/media/illustrations/6.svg new file mode 100755 index 0000000..753efaa --- /dev/null +++ b/apps/admin/public/media/illustrations/6.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/7.svg b/apps/admin/public/media/illustrations/7.svg new file mode 100755 index 0000000..fa171cb --- /dev/null +++ b/apps/admin/public/media/illustrations/7.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/8.svg b/apps/admin/public/media/illustrations/8.svg new file mode 100755 index 0000000..05f5a27 --- /dev/null +++ b/apps/admin/public/media/illustrations/8.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/illustrations/9.svg b/apps/admin/public/media/illustrations/9.svg new file mode 100755 index 0000000..27d6fe4 --- /dev/null +++ b/apps/admin/public/media/illustrations/9.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/images/2600x1200/2-dark.png b/apps/admin/public/media/images/2600x1200/2-dark.png new file mode 100755 index 0000000..a5ae71d Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/2-dark.png differ diff --git a/apps/admin/public/media/images/2600x1200/2.png b/apps/admin/public/media/images/2600x1200/2.png new file mode 100755 index 0000000..9bb5773 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/2.png differ diff --git a/apps/admin/public/media/images/2600x1200/3-dark.png b/apps/admin/public/media/images/2600x1200/3-dark.png new file mode 100755 index 0000000..3410e53 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/3-dark.png differ diff --git a/apps/admin/public/media/images/2600x1200/3.png b/apps/admin/public/media/images/2600x1200/3.png new file mode 100755 index 0000000..31eafa3 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/3.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-1-dark.png b/apps/admin/public/media/images/2600x1200/bg-1-dark.png new file mode 100755 index 0000000..8abd291 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-1-dark.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-1.png b/apps/admin/public/media/images/2600x1200/bg-1.png new file mode 100755 index 0000000..9e1a77d Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-1.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-10-dark.png b/apps/admin/public/media/images/2600x1200/bg-10-dark.png new file mode 100755 index 0000000..bfaac51 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-10-dark.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-10.png b/apps/admin/public/media/images/2600x1200/bg-10.png new file mode 100755 index 0000000..4864081 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-10.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-11.png b/apps/admin/public/media/images/2600x1200/bg-11.png new file mode 100755 index 0000000..e9f0f70 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-11.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-12.png b/apps/admin/public/media/images/2600x1200/bg-12.png new file mode 100755 index 0000000..adced1a Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-12.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-13.png b/apps/admin/public/media/images/2600x1200/bg-13.png new file mode 100755 index 0000000..7b73ae2 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-13.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-14-dark.png b/apps/admin/public/media/images/2600x1200/bg-14-dark.png new file mode 100755 index 0000000..017a13d Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-14-dark.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-14.png b/apps/admin/public/media/images/2600x1200/bg-14.png new file mode 100755 index 0000000..ee5d8c5 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-14.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-2-dark.png b/apps/admin/public/media/images/2600x1200/bg-2-dark.png new file mode 100755 index 0000000..3053342 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-2-dark.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-2.png b/apps/admin/public/media/images/2600x1200/bg-2.png new file mode 100755 index 0000000..34410a4 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-2.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-3-dark.png b/apps/admin/public/media/images/2600x1200/bg-3-dark.png new file mode 100755 index 0000000..23d1b47 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-3-dark.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-3.png b/apps/admin/public/media/images/2600x1200/bg-3.png new file mode 100755 index 0000000..bb1e075 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-3.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-4-dark.png b/apps/admin/public/media/images/2600x1200/bg-4-dark.png new file mode 100755 index 0000000..361f302 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-4-dark.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-4.png b/apps/admin/public/media/images/2600x1200/bg-4.png new file mode 100755 index 0000000..2ec2d99 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-4.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-5-dark.png b/apps/admin/public/media/images/2600x1200/bg-5-dark.png new file mode 100755 index 0000000..40b3fe7 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-5-dark.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-5.png b/apps/admin/public/media/images/2600x1200/bg-5.png new file mode 100755 index 0000000..4f8ea96 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-5.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-6.png b/apps/admin/public/media/images/2600x1200/bg-6.png new file mode 100755 index 0000000..a4971e3 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-6.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-7.png b/apps/admin/public/media/images/2600x1200/bg-7.png new file mode 100755 index 0000000..5c55e66 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-7.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-8.png b/apps/admin/public/media/images/2600x1200/bg-8.png new file mode 100755 index 0000000..a80a9f3 Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-8.png differ diff --git a/apps/admin/public/media/images/2600x1200/bg-9.png b/apps/admin/public/media/images/2600x1200/bg-9.png new file mode 100755 index 0000000..14a257e Binary files /dev/null and b/apps/admin/public/media/images/2600x1200/bg-9.png differ diff --git a/apps/admin/public/media/images/2600x1600/1-dark.png b/apps/admin/public/media/images/2600x1600/1-dark.png new file mode 100755 index 0000000..678eb7f Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/1-dark.png differ diff --git a/apps/admin/public/media/images/2600x1600/1.png b/apps/admin/public/media/images/2600x1600/1.png new file mode 100755 index 0000000..792cd90 Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/1.png differ diff --git a/apps/admin/public/media/images/2600x1600/2-dark.png b/apps/admin/public/media/images/2600x1600/2-dark.png new file mode 100755 index 0000000..31ef8a3 Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/2-dark.png differ diff --git a/apps/admin/public/media/images/2600x1600/2.png b/apps/admin/public/media/images/2600x1600/2.png new file mode 100755 index 0000000..5fceb42 Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/2.png differ diff --git a/apps/admin/public/media/images/2600x1600/bg-1-dark.png b/apps/admin/public/media/images/2600x1600/bg-1-dark.png new file mode 100755 index 0000000..c5c4c95 Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/bg-1-dark.png differ diff --git a/apps/admin/public/media/images/2600x1600/bg-1.png b/apps/admin/public/media/images/2600x1600/bg-1.png new file mode 100755 index 0000000..e941beb Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/bg-1.png differ diff --git a/apps/admin/public/media/images/2600x1600/bg-2-dark.png b/apps/admin/public/media/images/2600x1600/bg-2-dark.png new file mode 100755 index 0000000..9ab1cf8 Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/bg-2-dark.png differ diff --git a/apps/admin/public/media/images/2600x1600/bg-2.png b/apps/admin/public/media/images/2600x1600/bg-2.png new file mode 100755 index 0000000..bb0ec32 Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/bg-2.png differ diff --git a/apps/admin/public/media/images/2600x1600/bg-3-dark.png b/apps/admin/public/media/images/2600x1600/bg-3-dark.png new file mode 100755 index 0000000..3f0e0d3 Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/bg-3-dark.png differ diff --git a/apps/admin/public/media/images/2600x1600/bg-3.png b/apps/admin/public/media/images/2600x1600/bg-3.png new file mode 100755 index 0000000..bc7931f Binary files /dev/null and b/apps/admin/public/media/images/2600x1600/bg-3.png differ diff --git a/apps/admin/public/media/images/600x400/28.jpg b/apps/admin/public/media/images/600x400/28.jpg new file mode 100755 index 0000000..69907cc Binary files /dev/null and b/apps/admin/public/media/images/600x400/28.jpg differ diff --git a/apps/admin/public/media/images/600x400/29.jpg b/apps/admin/public/media/images/600x400/29.jpg new file mode 100755 index 0000000..454644b Binary files /dev/null and b/apps/admin/public/media/images/600x400/29.jpg differ diff --git a/apps/admin/public/media/images/600x400/30.jpg b/apps/admin/public/media/images/600x400/30.jpg new file mode 100755 index 0000000..52b4d36 Binary files /dev/null and b/apps/admin/public/media/images/600x400/30.jpg differ diff --git a/apps/admin/public/media/images/600x400/31.jpg b/apps/admin/public/media/images/600x400/31.jpg new file mode 100755 index 0000000..e3f58ad Binary files /dev/null and b/apps/admin/public/media/images/600x400/31.jpg differ diff --git a/apps/admin/public/media/images/600x400/32.jpg b/apps/admin/public/media/images/600x400/32.jpg new file mode 100755 index 0000000..25a9178 Binary files /dev/null and b/apps/admin/public/media/images/600x400/32.jpg differ diff --git a/apps/admin/public/media/web-studio/blocks/articles.svg b/apps/admin/public/media/web-studio/blocks/articles.svg new file mode 100644 index 0000000..d33dcdf --- /dev/null +++ b/apps/admin/public/media/web-studio/blocks/articles.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/web-studio/blocks/banner.svg b/apps/admin/public/media/web-studio/blocks/banner.svg new file mode 100644 index 0000000..f90a075 --- /dev/null +++ b/apps/admin/public/media/web-studio/blocks/banner.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/admin/public/media/web-studio/blocks/content.svg b/apps/admin/public/media/web-studio/blocks/content.svg new file mode 100644 index 0000000..23a4516 --- /dev/null +++ b/apps/admin/public/media/web-studio/blocks/content.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/web-studio/blocks/faq.svg b/apps/admin/public/media/web-studio/blocks/faq.svg new file mode 100644 index 0000000..1c023ad --- /dev/null +++ b/apps/admin/public/media/web-studio/blocks/faq.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/web-studio/blocks/media-content.svg b/apps/admin/public/media/web-studio/blocks/media-content.svg new file mode 100644 index 0000000..0e2cec0 --- /dev/null +++ b/apps/admin/public/media/web-studio/blocks/media-content.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/apps/admin/public/media/web-studio/blocks/media.svg b/apps/admin/public/media/web-studio/blocks/media.svg new file mode 100644 index 0000000..3ccb2b4 --- /dev/null +++ b/apps/admin/public/media/web-studio/blocks/media.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/admin/src/app/config/app.ts b/apps/admin/src/app/config/app.ts new file mode 100755 index 0000000..f8b7ae5 --- /dev/null +++ b/apps/admin/src/app/config/app.ts @@ -0,0 +1,17 @@ +import { name, version } from '../../../package.json'; + +export const TINYMCE_API_KEY = import.meta.env['VITE_TINYMCE_API_KEY']; + +export const API_URL = import.meta.env['VITE_API_URL']; + +export const IS_DEV_MODE = import.meta.env.MODE === 'development'; + +export const IS_PROD_MODE = import.meta.env.MODE === 'production'; + +export const BASE_URL = import.meta.env.BASE_URL; + +export const MODE = import.meta.env.MODE; + +export const APP_NAME = name; + +export const APP_VERSION = version; diff --git a/apps/admin/src/app/config/general.ts b/apps/admin/src/app/config/general.ts new file mode 100755 index 0000000..23cd196 --- /dev/null +++ b/apps/admin/src/app/config/general.ts @@ -0,0 +1,8 @@ +export const generalSettings = { + purchaseLink: '', + docsLink: '', + licenseLink: '', + devsLink: '', + faqLink: '', + aboutLink: '' +}; diff --git a/apps/admin/src/app/config/settings.ts b/apps/admin/src/app/config/settings.ts new file mode 100755 index 0000000..2850248 --- /dev/null +++ b/apps/admin/src/app/config/settings.ts @@ -0,0 +1,28 @@ +import { LayoutNames, Settings } from './types'; + +export const APP_SETTINGS: Settings = { + layout: '', + container: 'fixed', + layouts: { + [LayoutNames.DEFAULT]: { + sidebarCollapse: false, + sidebarTheme: 'light' + }, + [LayoutNames.HORIZONTAL_MENU]: { + headerSticky: true, + headerStickyOffset: 200 + }, + [LayoutNames.DUAL_ROW_HEADER]: { + headerSticky: true, + headerStickyOffset: 200 + }, + [LayoutNames.ADVANCE_MEGA_MENU]: { + headerSticky: true, + headerStickyOffset: 200 + }, + [LayoutNames.EXTENDED_HEADER]: { + headerSticky: true, + headerStickyOffset: 200 + } + } +}; diff --git a/apps/admin/src/app/config/types.ts b/apps/admin/src/app/config/types.ts new file mode 100755 index 0000000..39509c9 --- /dev/null +++ b/apps/admin/src/app/config/types.ts @@ -0,0 +1,61 @@ +import { type LucideIcon } from 'lucide-react'; + +export interface MenuItem { + title?: string; + icon?: LucideIcon; + path?: string; + rootPath?: string; + childrenIndex?: number; + heading?: string; + children?: MenuConfig; + disabled?: boolean; + collapse?: boolean; + collapseTitle?: string; + expandTitle?: string; + badge?: string; + separator?: boolean; + permissions?: string[]; +} + +export type MenuConfig = MenuItem[]; + +// prettier-ignore +export enum LayoutNames { + DEFAULT = 'default-layout', // demo1 + HORIZONTAL_MENU = 'horizontal-menu-layout', // demo2 + COMPACT_SIDEBAR = 'compact-sidebar-layout', // demo3 + TWO_COLUMN_SIDEBAR = 'two-column-sidebar-layout', // demo4 + DUAL_ROW_HEADER = 'dual-rows-header-layout', // demo5 + MULTIPLE_MENUS = 'multiple-menus-layout', // demo6 + ADVANCE_MEGA_MENU = 'advanced-mega-menu-layout', // demo7 + DROPDOWN_MENU = 'dropdown-menu-layout', // demo8 + EXTENDED_HEADER = 'extended-header-layout', // demo9 + DARK_SIDEBAR = 'dark-sidebar-layout', // demo10 +} + +export interface Settings { + container: 'fixed' | 'fluid'; + layout: string; + layouts: { + [LayoutNames.DEFAULT]: { + sidebarCollapse: boolean; + sidebarTheme: 'light' | 'dark'; + }; + [LayoutNames.HORIZONTAL_MENU]: { + headerSticky: boolean; + headerStickyOffset: number; + }; + [LayoutNames.DUAL_ROW_HEADER]: { + headerSticky: boolean; + headerStickyOffset: number; + }; + [LayoutNames.ADVANCE_MEGA_MENU]: { + headerSticky: boolean; + headerStickyOffset: number; + }; + [LayoutNames.EXTENDED_HEADER]: { + headerSticky: boolean; + headerStickyOffset: number; + }; + }; +} diff --git a/apps/admin/src/app/css/components/apexcharts.css b/apps/admin/src/app/css/components/apexcharts.css new file mode 100755 index 0000000..93c5631 --- /dev/null +++ b/apps/admin/src/app/css/components/apexcharts.css @@ -0,0 +1,101 @@ +@layer components { + .apexcharts-text, + .apexcharts-title-text, + .apexcharts-legend-text { + font-family: inherit !important; + } + + .apexcharts-title-text { + font-weight: var(--font-weight-normal); + } + + .apexcharts-pie-label { + @apply text-xs; + } + + .apexcharts-toolbar { + text-align: start !important; + } + + .apexcharts-menu { + border: 1px solid var(--color-border) !important; + box-shadow: var(--box-shadow-sm) !important; + background-color: var(--color-background) !important; + border-radius: 0.625rem !important; + padding: 0.5rem 0 !important; + overflow: hidden; + min-width: 10rem !important; + } + + .apexcharts-menu .apexcharts-menu-item { + padding: 0.5rem 0.5rem !important; + } + + .apexcharts-menu .apexcharts-menu-item:hover { + background-color: var(--gray-100) !important; + } + + .apexcharts-tooltip { + border: 1px solid var(--color-border) !important; + box-shadow: var(--box-shadow-sm) !important; + background-color: var(--color-background) !important; + border-radius: 0.625rem !important; + color: var(--color-secondary-foreground) !important; + } + + .apexcharts-tooltip .apexcharts-tooltip-title { + @apply text-foreground text-sm font-medium; + padding: 0.25rem 0.5rem !important; + background-color: transparent !important; + border-bottom: 1px solid var(--color-border) !important; + } + + .apexcharts-xaxistooltip { + border: 1px solid var(--color-border) !important; + box-shadow: var(--box-shadow-sm) !important; + background-color: var(--color-background) !important; + border-radius: 0.625rem; + color: var(--color-mono); + } + + .apexcharts-xaxistooltip:before { + border-bottom: 0 !important; + } + + .apexcharts-legend { + display: flex; + flex-direction: column; + @apply gap-2; + } + + .apexcharts-legend .apexcharts-legend-series { + @apply gap-1; + display: flex; + align-items: center; + } + + .apexcharts-legend .apexcharts-legend-series .apexcharts-legend-text { + @apply text-muted-foreground text-sm font-medium; + } + + .apexcharts-card-rounded .apexcharts-canvas svg { + border-bottom-left-radius: var(--radius-xl); + border-bottom-right-radius: var(--radius-xl); + } + + .apexcharts-rounded-sm .apexcharts-canvas svg { + border-radius: var(--radius-sm); + } + + .apexcharts-rounded .apexcharts-canvas svg { + border-radius: var(--radius-md); + } + + .apexcharts-rounded-lg .apexcharts-canvas svg { + border-radius: var(--radius-lg); + } + + .apexcharts-rounded-xl .apexcharts-canvas svg { + border-radius: var(--radius-xl); + } +} diff --git a/apps/admin/src/app/css/components/editor.css b/apps/admin/src/app/css/components/editor.css new file mode 100755 index 0000000..7960301 --- /dev/null +++ b/apps/admin/src/app/css/components/editor.css @@ -0,0 +1,10 @@ +@layer components { + .tox.tox-tinymce { + @apply !border-input !border !border-solid; + } + + .tox-pop { + /* HIDE SELECTED TABLE TOOLBAR */ + @apply !hidden; + } +} diff --git a/apps/admin/src/app/css/components/image-input.css b/apps/admin/src/app/css/components/image-input.css new file mode 100755 index 0000000..fa5d8be --- /dev/null +++ b/apps/admin/src/app/css/components/image-input.css @@ -0,0 +1,51 @@ +@layer components { + .kt-image-input { + @apply relative inline-flex size-20 cursor-pointer items-center justify-center; + + input[type='file'] { + @apply absolute size-0 appearance-none opacity-0; + } + } + + .kt-image-input-remove { + @apply bg-background border-border absolute end-0.25 top-0.25 z-[1] flex size-5 cursor-pointer items-center justify-center rounded-full border shadow-sm; + + i { + @apply text-muted-foreground text-[11px]; + } + + svg { + @apply text-muted-foreground size-3.25; + } + + &:hover { + i { + @apply text-foreground; + } + + svg { + @apply text-foreground; + } + } + } + + .kt-image-input-placeholder { + @apply border-border kt-image-input-empty:border-border relative size-full overflow-hidden rounded-full border bg-cover bg-no-repeat; + } + + .kt-image-input-preview { + @apply relative size-full overflow-hidden rounded-full bg-cover bg-no-repeat; + } +} + +@custom-variant kt-image-input-empty { + [data-kt-image-input-initialized].empty & { + @slot; + } +} + +@custom-variant image-input-changed { + [data-kt-image-input-initialized].changed & { + @slot; + } +} diff --git a/apps/admin/src/app/css/components/leaflet.css b/apps/admin/src/app/css/components/leaflet.css new file mode 100755 index 0000000..27e5d2b --- /dev/null +++ b/apps/admin/src/app/css/components/leaflet.css @@ -0,0 +1,25 @@ +@layer components { + /* Base Leaflet container styles */ + .leaflet-container { + /* Leaflet pane and control styles */ + & .leaflet-pane, + & .leaflet-top, + & .leaflet-bottom, + & .leaflet-control { + z-index: 1 !important; + } + + /* Leaflet popup content wrapper styles */ + & .leaflet-popup-content-wrapper { + border-radius: var(--radius-md); + text-align: center; + background-color: var(--color-popover); + + /* Leaflet popup content styles */ + & .leaflet-popup-content { + font-family: inherit; + @apply text-xs; + } + } + } +} diff --git a/apps/admin/src/app/css/components/rating.css b/apps/admin/src/app/css/components/rating.css new file mode 100755 index 0000000..fe09749 --- /dev/null +++ b/apps/admin/src/app/css/components/rating.css @@ -0,0 +1,89 @@ +@layer components { + /* Base kt-rating styles */ + .kt-rating { + display: inline-flex; + align-items: stretch; + + & input { + appearance: none; + position: absolute; + inset-inline-start: 9999px; + + &[disabled] { + display: none; + } + } + } + + /* kt-rating on state */ + .kt-rating-on { + @apply text-yellow-400; + } + + /* kt-rating off state */ + .kt-rating-off { + @apply text-muted-foreground; + } + + /* kt-rating label base styles */ + .kt-rating-label { + display: inline-flex !important; + align-items: center; + + & .kt-rating-on { + display: none !important; + } + + & .kt-rating-off { + display: inline-flex !important; + } + } + + /* Hover and checked states for kt-rating label */ + .kt-rating:hover label.kt-rating-label, + label.kt-rating-label, + label.kt-rating-label.checked, + div.kt-rating-label.checked { + & .kt-rating-on { + display: inline-flex !important; + } + + & .kt-rating-off { + display: none !important; + } + } + + /* Sibling hover and checked states */ + label.kt-rating-label:hover ~ label.kt-rating-label, + .kt-rating-input:checked ~ .kt-rating-label { + & .kt-rating-on { + display: none !important; + } + + & .kt-rating-off { + display: inline-flex !important; + } + } + + /* Indeterminate kt-rating label state */ + .kt-rating-label.indeterminate { + position: relative; + + & .kt-rating-on { + display: inline-flex !important; + position: absolute; + z-index: 1; + overflow: hidden; + inset-inline-start: 0; + } + + & .kt-rating-off { + display: inline-flex !important; + } + } + + /* Cursor for label */ + label.kt-rating-label { + cursor: pointer; + } +} diff --git a/apps/admin/src/app/css/components/scrollable.css b/apps/admin/src/app/css/components/scrollable.css new file mode 100755 index 0000000..9505c1f --- /dev/null +++ b/apps/admin/src/app/css/components/scrollable.css @@ -0,0 +1,118 @@ +@layer components { + /* Base scrollable styles */ + .kt-scrollable, + .kt-scrollable-y, + .kt-scrollable-x, + .kt-scrollable-hover, + .kt-scrollable-y-hover, + .kt-scrollable-x-hover, + .kt-scrollable-auto, + .kt-scrollable-y-auto, + .kt-scrollable-x-auto { + scrollbar-width: thin; + scrollbar-color: transparent transparent; + position: relative; + + &::-webkit-scrollbar { + width: 0.35rem; + height: 0.35rem; + } + + &::-webkit-scrollbar-track { + background-color: transparent; + } + + &::-webkit-scrollbar-thumb { + border-radius: 1.25rem; + } + + &::-webkit-scrollbar-corner { + background-color: transparent; + } + } + + /* Overflow styles for scrollable variants */ + .kt-scrollable, + .kt-scrollable-hover { + overflow: scroll; + } + + .kt-scrollable-y, + .kt-scrollable-y-hover { + overflow-y: scroll; + } + + .kt-scrollable-x, + .kt-scrollable-x-hover { + overflow-x: scroll; + } + + .kt-scrollable-auto { + overflow: auto; + } + + .kt-scrollable-y-auto { + overflow-y: auto; + } + + .kt-scrollable-x-auto { + overflow-x: auto; + } + + /* Scrollbar visibility and color */ + .kt-scrollable, + .kt-scrollable-y, + .kt-scrollable-x, + .kt-scrollable-auto, + .kt-scrollable-y-auto, + .kt-scrollable-x-auto, + .kt-scrollable-hover:hover, + .kt-scrollable-y-hover:hover, + .kt-scrollable-x-hover:hover { + scrollbar-color: var(--scrollbar-thumb-color, var(--color-input)) transparent; + + &::-webkit-scrollbar-thumb { + background-color: var(--scrollbar-thumb-color, var(--color-input)); + } + + &::-webkit-scrollbar-corner { + background-color: transparent; + } + } + + /* Target safari browser only */ + @supports (-webkit-hyphens: none) { + .kt-scrollable, + .kt-scrollable-hover { + overflow: auto; + } + + .kt-scrollable-y, + .kt-scrollable-y-hover { + overflow-y: auto; + } + + .kt-scrollable-x, + .kt-scrollable-x-hover { + overflow-x: auto; + } + } + + /* Responsive adjustments for smaller screens */ + /* @media (max-width: var(--screen-lg)) { + .kt-scrollable, + .kt-scrollable-hover { + overflow: auto; + } + + .kt-scrollable-y, + .kt-scrollable-y-hover { + overflow-y: auto; + } + + .kt-scrollable-x, + .kt-scrollable-x-hover { + overflow-x: auto; + } + } */ +} diff --git a/apps/admin/src/app/css/config.reui.css b/apps/admin/src/app/css/config.reui.css new file mode 100755 index 0000000..8a41d56 --- /dev/null +++ b/apps/admin/src/app/css/config.reui.css @@ -0,0 +1,187 @@ +@plugin 'tailwindcss-animate'; + +/** Colors **/ +:root { + /** Base Colors **/ + --background: oklch(1 0 0); /* --color-white */ + --foreground: oklch(27.4% 0.006 286.033); /* --color-zinc-800 */ + --card: oklch(1 0 0); /* --color-white */ + --card-foreground: oklch(27.4% 0.006 286.033); /* --color-zinc-800 */ + --popover: oklch(1 0 0); /* --color-white */ + --popover-foreground: oklch(27.4% 0.006 286.033); /* --color-zinc-800 */ + --primary: #1379f0; /* custom color */ + --primary-foreground: oklch(1 0 0); /* --color-white */ + --secondary: oklch(96.7% 0.003 264.542); /* --color-zinc-100 */ + --secondary-foreground: oklch(44.6% 0.03 256.802); /* --color-zinc-600 */ + --muted: oklch(96.7% 0.003 264.542); /* --color-zinc-100 */ + --muted-foreground: oklch(70.5% 0.015 286.067); /* --color-zinc-400 */ + --accent: oklch(96.7% 0.003 264.542); /* --color-zinc-100 */ + --accent-foreground: oklch(21% 0.006 285.885); /* --color-zinc-900 */ + --destructive: oklch(57.7% 0.245 27.325); /* --color-red-600 */ + --destructive-foreground: oklch(1 0 0); /* --color-white */ + --mono: oklch(14.1% 0.005 285.823); /* --color-zinc-950 */ + --mono-foreground: oklch(1 0 0); /* --color-white */ + + /** Base Styles **/ + --border: oklch(94% 0.004 286.32); /* between --color-zinc-100 and --color-zinc-200 */ + --input: oklch(92% 0.004 286.32); /* --color-zinc-200 */ + --ring: oklch(87.1% 0.006 286.286); /* --color-zinc-400 */ + --radius: 0.5rem; +} + +.dark { + /** Base Colors **/ + --background: oklch(14.1% 0.005 285.823); /* --color-zinc-950 */ + --foreground: oklch(98.5% 0 0); /* --color-zinc-50 */ + --card: oklch(14.1% 0.005 285.823); /* --color-zinc-950 */ + --card-foreground: oklch(98.5% 0 0); /* --color-zinc-50 */ + --popover: oklch(14.1% 0.005 285.823); /* --color-zinc-950 */ + --popover-foreground: oklch(98.5% 0 0); /* --color-zinc-50 */ + --primary: #1379f0; /* custom color */ + --primary-foreground: oklch(1 0 0); /* --color-white */ + --secondary: oklch(27.4% 0.006 286.033); /* --color-zinc-800 */ + --secondary-foreground: oklch(70.5% 0.015 286.067); /* --color-zinc-400 */ + --muted: oklch(21% 0.006 285.885); /* --color-zinc-900 */ + --muted-foreground: oklch(55.2% 0.016 285.938); /* --color-zinc-500 */ + --accent: oklch(21% 0.006 285.885); /* --color-zinc-900 */ + --accent-foreground: oklch(98.5% 0 0); /* --color-zinc-50 */ + --destructive: oklch(57.7% 0.245 27.325); /* --color-red-600 */ + --destructive-foreground: oklch(1 0 0); /* --color-white */ + --mono: oklch(87.1% 0.006 286.286); /* --color-zinc-300 */ + --mono-foreground: oklch(0 0 0); /* --color-black */ + + /** Base Styles **/ + --border: oklch(27.4% 0.006 286.033); /* --color-zinc-800 */ + --input: oklch(27.4% 0.006 286.033); /* --color-zinc-800 */ + --ring: oklch(27.4% 0.006 286.033); /* --color-zinc-600 */ +} + +/** Theme Setup **/ +@theme inline { + /** Base Colors **/ + --color-background: var(--background); + --color-foreground: var(--foreground); + + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + + --color-mono: var(--mono); + --color-mono-foreground: var(--mono-foreground); + + /** Base Styles **/ + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + + --radius-xl: calc(var(--radius) + 4px); + --radius-lg: var(--radius); + --radius-md: calc(var(--radius) - 2px); + --radius-sm: calc(var(--radius) - 4px); + + --animate-accordion-down: accordion-down 0.2s ease-out; + --animate-accordion-up: accordion-up 0.2s ease-out; + --animate-collapsible-down: collapsible-down 0.2s ease-out; + --animate-collapsible-up: collapsible-up 0.2s ease-out; + --animate-caret-blink: caret-blink 1.25s ease-out infinite; + --animate-strike: strike 0.3s ease-out forwards; + --animate-marquee: marquee var(--duration) linear infinite; + --animate-marquee-vertical: marquee-vertical var(--duration) linear infinite; + + @keyframes accordion-down { + from { + height: 0; + } + to { + height: var(--radix-accordion-content-height); + } + } + @keyframes accordion-up { + from { + height: var(--radix-accordion-content-height); + } + to { + height: 0; + } + } + @keyframes collapsible-down { + from { + height: 0; + } + to { + height: var(--radix-collapsible-content-height); + } + } + @keyframes collapsible-up { + from { + height: var(--radix-collapsible-content-height); + } + to { + height: 0; + } + } + @keyframes caret-blink { + 0%, + 70%, + 100% { + opacity: 1; + } + 20%, + 50% { + opacity: 0; + } + } + + @keyframes strike { + from { + width: 0; + } + to { + width: 100%; + } + } + + @keyframes marquee { + from { + transform: translateX(0); + } + to { + transform: translateX(calc(-100% - var(--gap))); + } + } + + @keyframes marquee-vertical { + from { + transform: translateY(0); + } + to { + transform: translateY(calc(-100% - var(--gap))); + } + } +} + +/** Custom Font Size **/ +@theme { + --text-2sm: 0.8125rem; + --text-2sm--line-height: calc(1.075 / 0.8125); + + --text-2xs: 0.6875rem; + --text-2xs--line-height: calc(0.825 / 0.6875); +} diff --git a/apps/admin/src/app/css/layouts/default-layout.css b/apps/admin/src/app/css/layouts/default-layout.css new file mode 100755 index 0000000..a742d25 --- /dev/null +++ b/apps/admin/src/app/css/layouts/default-layout.css @@ -0,0 +1,135 @@ +@layer components { + /* Variables */ + .default-layout { + --sidebar-transition-duration: 0.3s; + --sidebar-transition-timing: ease; + --sidebar-width: 280px; + --sidebar-width-collapse: 80px; + --sidebar-default-width: 280px; + --header-height: 70px; + } + + @media (max-width: theme(--breakpoint-lg)) { + .default-layout { + --sidebar-width: 280px; + --header-height: 60px; + } + } + + /* Base */ + .default-layout .header { + height: var(--header-height); + } + + .default-layout .sidebar { + width: var(--sidebar-width); + } + + .default-layout.header-fixed .wrapper { + padding-top: var(--header-height); + } + + /* Desktop mode */ + @media (min-width: theme(--breakpoint-lg)) { + .default-layout .sidebar { + width: var(--sidebar-width); + transition: width var(--sidebar-transition-duration) var(--sidebar-transition-timing); + } + + .default-layout .sidebar .sidebar-header { + height: var(--header-height); + } + + .default-layout .sidebar .sidebar-wrapper { + width: var(--sidebar-default-width); + } + + .default-layout .sidebar .sidebar-logo { + width: var(--sidebar-default-width); + } + + .default-layout .sidebar .small-logo { + display: none; + } + + .default-layout.sidebar-fixed .wrapper { + padding-inline-start: var(--sidebar-width) !important; + } + + .default-layout.sidebar-fixed.header-fixed .header { + inset-inline-start: var(--sidebar-width) !important; + } + + .default-layout.sidebar-fixed.header-fixed .wrapper { + padding-top: var(--header-height); + } + + .default-layout.sidebar-collapse { + --sidebar-width: var(--sidebar-width-collapse); + } + + .default-layout.sidebar-collapse .sidebar { + transition: width var(--sidebar-transition-duration) var(--sidebar-transition-timing); + } + + .default-layout.sidebar-collapse .sidebar:hover { + width: var(--sidebar-default-width); + } + + .default-layout.sidebar-collapse .sidebar:not(:hover) .default-logo { + display: none; + } + + .default-layout.sidebar-collapse .sidebar:not(:hover) .small-logo { + display: flex; + } + + .default-layout.sidebar-collapse .sidebar:not(:hover) [data-slot='accordion-menu-title'], + .default-layout.sidebar-collapse .sidebar:not(:hover) [data-slot='badge'], + .default-layout.sidebar-collapse + .sidebar:not(:hover) + [data-slot='accordion-menu-sub-indicator'] { + display: none !important; + transition: none !important; + animation: none !important; + } + + .default-layout.sidebar-collapse .sidebar:not(:hover) [data-slot='accordion-menu-sub-content'] { + visibility: hidden; + position: absolute; + height: 0; + width: 0; + } + + .default-layout.sidebar-collapse .sidebar:not(:hover) [data-slot='accordion-menu-label'] { + visibility: hidden; + position: relative; + } + + .default-layout.sidebar-collapse + .sidebar:not(:hover) + [data-slot='accordion-menu-label']::before { + content: '...'; + color: currentColor; + font-size: inherit; + position: absolute; + visibility: visible; + display: inline-block; + bottom: 50%; + inset-inline-start: 0; + margin-inline-start: -0.15rem; + top: 0.25rem; + transform: translateX(100%); + } + } + + .default-layout.layout-initialized .wrapper { + transition: padding-inline-start var(--sidebar-transition-duration) + var(--sidebar-transition-timing); + } + + .default-layout.layout-initialized .header { + transition: inset-inline-start var(--sidebar-transition-duration) + var(--sidebar-transition-timing); + } +} diff --git a/apps/admin/src/app/css/styles.css b/apps/admin/src/app/css/styles.css new file mode 100755 index 0000000..b993031 --- /dev/null +++ b/apps/admin/src/app/css/styles.css @@ -0,0 +1,49 @@ +/* Tailwind Core */ +@import 'tailwindcss'; +@plugin "@tailwindcss/typography"; +@plugin "@tailwindcss/typography"; + +/* @crux-kit/editor-tiptap — Tailwind class scanning + editor content styles */ +@source '../../../../../packages/design-system/editor-tiptap/src'; +@import '@crux-kit/editor-tiptap/styles.css'; + +/* ReUI Configs */ +@import './config.reui.css'; + +/** Global Styles **/ +@layer base { + * { + @apply border-border; + } + + *:focus-visible { + @apply outline-ring rounded-xs shadow-none outline-2 outline-offset-3 transition-none!; + } +} + +/* Components */ +@import './components/image-input.css'; +@import './components/apexcharts.css'; +@import './components/leaflet.css'; +@import './components/rating.css'; +@import './components/image-input.css'; +@import './components/scrollable.css'; +@import './components/editor.css'; + +/* Demos */ +@import './layouts/default-layout.css'; + +/** Dark/Light Theme Variant **/ +@custom-variant dark (&:is(.dark *)); +@custom-variant light (&:not(.dark *)); + +input[type='number']::-webkit-inner-spin-button, +input[type='number']::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + +/* Firefox */ +input[type='number'] { + -moz-appearance: textfield; +} diff --git a/apps/admin/src/app/i18n/config.ts b/apps/admin/src/app/i18n/config.ts new file mode 100755 index 0000000..c23229f --- /dev/null +++ b/apps/admin/src/app/i18n/config.ts @@ -0,0 +1,53 @@ +import { detectUserTimeMode } from '@crux-kit/utils'; +import { collectModuleMessages } from '#app/services/modules'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import arMessages from './messages/ar.json'; +import enMessages from './messages/en.json'; +import ukMessages from './messages/uk.json'; +import { type Language } from './types'; + +const I18N_MESSAGES = collectModuleMessages({ + en: enMessages, + ar: arMessages, + uk: ukMessages +}); + +const I18N_PHONE_MASK = { + en: '+1 (___) ___-____', + ar: '+966 __ ___ ____', + uk: '+38 (___) ___-__-__' +}; + +const I18N_LANGUAGES: Language[] = [ + { + label: 'English', + code: 'en', + direction: 'ltr', + flag: toAbsoluteUrl('/media/flags/united-states.svg'), + messages: I18N_MESSAGES.en, + phoneMask: I18N_PHONE_MASK.en, + timeMode: detectUserTimeMode() + }, + { + label: 'Arabic (Saudi)', + code: 'ar', + direction: 'rtl', + flag: toAbsoluteUrl('/media/flags/saudi-arabia.svg'), + messages: I18N_MESSAGES.ar, + phoneMask: I18N_PHONE_MASK.ar, + timeMode: detectUserTimeMode() + }, + { + label: 'Ukraine', + code: 'uk', + direction: 'ltr', + flag: toAbsoluteUrl('/media/flags/ukraine.svg'), + messages: I18N_MESSAGES.uk, + phoneMask: I18N_PHONE_MASK.uk, + timeMode: detectUserTimeMode() + } +]; + +const I18N_DEFAULT_LANGUAGE: Language = I18N_LANGUAGES[0]; + +export { I18N_DEFAULT_LANGUAGE, I18N_LANGUAGES, I18N_MESSAGES, I18N_PHONE_MASK }; diff --git a/apps/admin/src/app/i18n/context.ts b/apps/admin/src/app/i18n/context.ts new file mode 100644 index 0000000..4b79daf --- /dev/null +++ b/apps/admin/src/app/i18n/context.ts @@ -0,0 +1,4 @@ +import { createContext } from 'react'; +import { type I18nProviderProps } from '#app/i18n/types'; + +export default createContext(null); diff --git a/apps/admin/src/app/i18n/messages/ar.json b/apps/admin/src/app/i18n/messages/ar.json new file mode 100755 index 0000000..61ae882 --- /dev/null +++ b/apps/admin/src/app/i18n/messages/ar.json @@ -0,0 +1,105 @@ +{ + "ACTION.BACK": "رجوع", + "ACTION.SAVE": "حفظ", + "ACTION.CREATE": "إنشاء", + "ACTION.INCLUDE": "تضمين", + "ACTION.GENERATE": "توليد", + "ACTION.REMOVE": "إزالة", + "ACTION.CANCEL": "إلغاء", + "ACTION.CONFIRM": "تأكيد", + "ACTION.SUBMIT": "إرسال", + "ACTION.SEARCH": "بحث", + "ACTION.SWAP": "تبديل", + "ACTION.MERGE": "دمج", + "ACTION.SPLIT": "تقسيم", + "ACTION.RESET": "إعادة تعيين", + "ACTION.PREVIEW": "معاينة", + "ACTION.UPLOAD": "رفع", + "ACTION.DELETE": "حذف", + "ACTION.CLOSE": "إغلاق", + "ACTION.CLEAR": "مسح", + "ACTION.CLEAR_FILTERS": "مسح عوامل التصفية", + "ACTION.EDIT": "تعديل", + "STATE.CREATING": "جارٍ الإنشاء", + "STATE.GENERATING": "جارٍ التوليد", + "STATE.SAVING": "جارٍ الحفظ", + "STATE.REMOVING": "جارٍ الإزالة", + "STATE.LOADING": "جارٍ التحميل", + "STATE.UPDATING": "جارٍ التحديث", + "ERROR": "خطأ", + "PERMISSION": "صلاحية", + "PERMISSION.PERMISSIONS": "الصلاحيات", + "PERMISSION.PERMISSION_NAME": "اسم الصلاحية", + "PERMISSION.SLUG": "Slug", + "PERMISSION.EDIT_PERMISSION": "تعديل الصلاحية", + "ROLE": "دور", + "ROLE.ROLES": "الأدوار", + "ROLE.ROLE_NAME": "اسم الدور", + "ROLE.SLUG": "Slug", + "ROLE.EDIT_ROLE": "تعديل الدور", + "USER": "مستخدم", + "USER.EDIT_USER": "تعديل المستخدم", + "USER.STATUS.ACTIVE": "نشط", + "USER.STATUS.INACTIVE": "غير نشط", + "USER.MENU.MY_PROFILE": "الملف الشخصي الخاص بي", + "USER.MENU.MY_ACCOUNT": "حسابي", + "USER.MENU.LANGUAGE": "لغة", + "USER.MENU.DARK_MODE": "الوضع المظلم", + "USER.MENU.LOGOUT": "تسجيل الخروج", + "SUCCESS": "تم بنجاح", + "ACTIONS": "الإجراءات", + "FILTER": "تصفية", + "SELECTED": "محدد", + "NAME": "الاسم", + "FIRST_NAME": "الاسم الأول", + "LAST_NAME": "اسم العائلة", + "EMAIL": "البريد الإلكتروني", + "SELECT": "اختر", + "SELECT_OPTION": "اختر خياراً", + "SELECT_ALL": "تحديد الكل", + "SELECT_ALL_WITH_OPTS_LENGTH": "تحديد الكل ({length} خيارات)", + "STATUS": "الحالة", + "PASSWORD": "كلمة المرور", + "NEW_PASSWORD": "كلمة المرور الجديدة", + "PASSWORD_CONFIRM": "تأكيد كلمة المرور", + "MODULE_NAME": "اسم الوحدة", + "RETURN_HOME": "العودة إلى الرئيسية", + "NO_ITEMS_FOUND": "لم يتم العثور على عناصر", + "NO_RESULTS_FOUND": "لم يتم العثور على نتائج", + "PLUS_MORE_WITH_NUMBER": "+ {number} أخرى", + "ADMIN.ADMIN_MANAGEMENT": "إدارة المشرفين", + "ADMIN.ADMINS": "المشرفون", + "DASHBOARD": "لوحة التحكم", + "FORM.ERROR.REQUIRED": "مطلوب", + "FORM.ERROR.INVALID_EMAIL_ADDRESS": "عنوان بريد إلكتروني غير صالح", + "FORM.ERROR.PASSWORDS_MUST_MATCH": "يجب أن تتطابق كلمتا المرور", + "FORM.ERROR.MIN_PASSWORD_LENGTH_DESC": "الحد الأدنى لطول كلمة المرور - 8 أحرف.", + "FORM.ERROR.SOMETHING_WENT_WRONG": "حدث خطأ ما", + "TABLE.COMMON.COLUMNS": "الأعمدة", + "TABLE.COMMON.NO_DATA_AVAILABLE": "لا توجد بيانات متاحة", + "TABLE.COMMON.ROWS_PER_PAGE": "عدد الصفوف في الصفحة", + "TABLE.COMMON.GO_TO_PREVIOUS_PAGE": "الانتقال إلى الصفحة السابقة", + "TABLE.COMMON.GO_TO_NEXT_PAGE": "الانتقال إلى الصفحة التالية", + "PROFILE.PROFILE_SETTINGS": "إعدادات الملف الشخصي", + "PROFILE.AVATAR_DESCRIPTION": "نوصي باستخدام صور لا تقل أبعادها عن 98 × 98 بكسل (بحجم يصل إلى 4 ميغابايت) بصيغة PNG أو JPG أو JPEG.", + "PROFILE.AVATAR_ALT": "الصورة الرمزية", + "PROFILE.AVATAR_SETTINGS": "إعدادات الصورة الرمزية", + "PROFILE.AVATAR_CROP_ME": "قص الصورة", + "PROFILE.EDIT_PROFILE_IMAGE": "تعديل صورة الملف الشخصي", + "MODULE.COMMON.REMOVE_ITEM_QUESTION": "هل أنت متأكد من رغبتك في إزالة {target}؟", + "MODULE.COMMON.ARE_YOU_SURE?": "هل أنت متأكد؟", + "MODULE.COMMON.REMOVE_ITEM_QUESTION_DESC": "لا يمكن التراجع عن هذا الإجراء.", + "MODULE.COMMON.CREATE_NEW_ENTITY": "إنشاء {entity} جديد", + "MODULE.COMMON.CREATE_NEW_USER": "إنشاء مستخدم جديد", + "MESSAGE.PLEASE_WAIT": "يرجى الانتظار", + "MESSAGE.PLEASE_WAIT_THIS_MAY_TAKE_FEW_MOMENTS": "يرجى الانتظار، قد يستغرق هذا بعض الوقت", + "COMMON.SELECT_FILE_TO_VIEW_ITS_CONTENT": "اختر ملفاً لعرض محتوياته", + "COMPONENT.FILE_INPUT.SELECTED_NUM_OF_FILES": "تم اختيار {num} ملف", + "COMPONENT.FILE_INPUT.SELECT_FILE_NO_FILE_SELECTED": "اختر ملفاً، لم يتم اختيار أي ملف", + "COMPONENT.FILE_INPUT.OPTION.FROM_CLOUD_STORAGE": "من التخزين السحابي", + "COMPONENT.FILE_INPUT.OPTION.FROM_LOCAL_MACHINE": "من الجهاز المحلي", + "COMPONENT.FILE_INPUT.OPTION.CLEAR": "مسح", + "COMPONENT.FILE_INPUT.SHOW_SELECTED_FILES": "عرض الملفات المختارة", + "COMPONENT.FILE_INPUT.SELECTED_FILES": "الملفات المختارة", + "COMPONENT.FILE_INPUT.REMOVE_NAME": "إزالة {name}" +} diff --git a/apps/admin/src/app/i18n/messages/en.json b/apps/admin/src/app/i18n/messages/en.json new file mode 100755 index 0000000..5ba984d --- /dev/null +++ b/apps/admin/src/app/i18n/messages/en.json @@ -0,0 +1,105 @@ +{ + "ACTION.BACK": "Back", + "ACTION.SAVE": "Save", + "ACTION.CREATE": "Create", + "ACTION.INCLUDE": "Include", + "ACTION.GENERATE": "Generate", + "ACTION.REMOVE": "Remove", + "ACTION.CANCEL": "Cancel", + "ACTION.CONFIRM": "Confirm", + "ACTION.SUBMIT": "Submit", + "ACTION.SEARCH": "Search", + "ACTION.SWAP": "Swap", + "ACTION.MERGE": "Merge", + "ACTION.SPLIT": "Split", + "ACTION.RESET": "Reset", + "ACTION.PREVIEW": "Preview", + "ACTION.UPLOAD": "Upload", + "ACTION.DELETE": "Delete", + "ACTION.CLOSE": "Close", + "ACTION.CLEAR": "Clear", + "ACTION.CLEAR_FILTERS": "Clear filters", + "ACTION.EDIT": "Edit", + "STATE.CREATING": "Creating", + "STATE.GENERATING": "Generating", + "STATE.SAVING": "Saving", + "STATE.REMOVING": "Removing", + "STATE.LOADING": "Loading", + "STATE.UPDATING": "Updating", + "ERROR": "Error", + "PERMISSION": "Permission", + "PERMISSION.PERMISSIONS": "Permissions", + "PERMISSION.PERMISSION_NAME": "Permission name", + "PERMISSION.SLUG": "Slug", + "PERMISSION.EDIT_PERMISSION": "Edit permission", + "ROLE": "Role", + "ROLE.ROLES": "Roles", + "ROLE.ROLE_NAME": "Role name", + "ROLE.SLUG": "Slug", + "ROLE.EDIT_ROLE": "Edit role", + "USER": "User", + "USER.EDIT_USER": "Edit user", + "USER.STATUS.ACTIVE": "Active", + "USER.STATUS.INACTIVE": "Inactive", + "USER.MENU.MY_PROFILE": "My Profile", + "USER.MENU.MY_ACCOUNT": "My Account", + "USER.MENU.LANGUAGE": "Language", + "USER.MENU.DARK_MODE": "Dark Mode", + "USER.MENU.LOGOUT": "Logout", + "SUCCESS": "Success", + "ACTIONS": "Actions", + "FILTER": "Filter", + "SELECTED": "Selected", + "NAME": "Name", + "FIRST_NAME": "First name", + "LAST_NAME": "Last name", + "EMAIL": "Email", + "SELECT": "Select", + "SELECT_OPTION": "Select Option", + "SELECT_ALL": "Select All", + "SELECT_ALL_WITH_OPTS_LENGTH": "Select All ({length} options)", + "STATUS": "Status", + "PASSWORD": "Password", + "NEW_PASSWORD": "New password", + "PASSWORD_CONFIRM": "Password confirm", + "MODULE_NAME": "Module Name", + "RETURN_HOME": "Return Home", + "NO_ITEMS_FOUND": "No items found", + "NO_RESULTS_FOUND": "No results found", + "PLUS_MORE_WITH_NUMBER": "+ {number} more", + "ADMIN.ADMIN_MANAGEMENT": "Admin Management", + "ADMIN.ADMINS": "Admins", + "DASHBOARD": "Dashboard", + "FORM.ERROR.REQUIRED": "Required", + "FORM.ERROR.INVALID_EMAIL_ADDRESS": "Invalid email address", + "FORM.ERROR.PASSWORDS_MUST_MATCH": "Passwords must match", + "FORM.ERROR.MIN_PASSWORD_LENGTH_DESC": "Min. password length - 8 chars.", + "FORM.ERROR.SOMETHING_WENT_WRONG": "Something went wrong", + "TABLE.COMMON.COLUMNS": "Columns", + "TABLE.COMMON.NO_DATA_AVAILABLE": "No data available", + "TABLE.COMMON.ROWS_PER_PAGE": "Rows per page", + "TABLE.COMMON.GO_TO_PREVIOUS_PAGE": "Go to previous page", + "TABLE.COMMON.GO_TO_NEXT_PAGE": "Go to next page", + "PROFILE.PROFILE_SETTINGS": "Profile Settings", + "PROFILE.AVATAR_DESCRIPTION": "We recommend using images that are at least 98 x 98 pixels in size (file size up to 4 MB) in PNG, JPG, JPEG format.", + "PROFILE.AVATAR_ALT": "Avatar", + "PROFILE.AVATAR_SETTINGS": "Avatar Settings", + "PROFILE.AVATAR_CROP_ME": "Crop me", + "PROFILE.EDIT_PROFILE_IMAGE": "Edit profile image", + "MODULE.COMMON.REMOVE_ITEM_QUESTION": "Are you sure you want to remove {target}?", + "MODULE.COMMON.ARE_YOU_SURE?": "Are you sure?", + "MODULE.COMMON.REMOVE_ITEM_QUESTION_DESC": "This action cannot be undone.", + "MODULE.COMMON.CREATE_NEW_ENTITY": "Create new {entity}", + "MODULE.COMMON.CREATE_NEW_USER": "Create new user", + "MESSAGE.PLEASE_WAIT": "Please wait", + "MESSAGE.PLEASE_WAIT_THIS_MAY_TAKE_FEW_MOMENTS": "Please wait, this may take few moments", + "COMMON.SELECT_FILE_TO_VIEW_ITS_CONTENT": "Select a file to view its contents", + "COMPONENT.FILE_INPUT.SELECTED_NUM_OF_FILES": "{num} file(s) selected", + "COMPONENT.FILE_INPUT.SELECT_FILE_NO_FILE_SELECTED": "Select file, no file selected", + "COMPONENT.FILE_INPUT.OPTION.FROM_CLOUD_STORAGE": "From cloud storage", + "COMPONENT.FILE_INPUT.OPTION.FROM_LOCAL_MACHINE": "From local machine", + "COMPONENT.FILE_INPUT.OPTION.CLEAR": "Clear", + "COMPONENT.FILE_INPUT.SHOW_SELECTED_FILES": "Show selected files", + "COMPONENT.FILE_INPUT.SELECTED_FILES": "Selected files", + "COMPONENT.FILE_INPUT.REMOVE_NAME": "Remove {name}" +} diff --git a/apps/admin/src/app/i18n/messages/uk.json b/apps/admin/src/app/i18n/messages/uk.json new file mode 100755 index 0000000..a62db50 --- /dev/null +++ b/apps/admin/src/app/i18n/messages/uk.json @@ -0,0 +1,105 @@ +{ + "ACTION.BACK": "Назад", + "ACTION.SAVE": "Зберегти", + "ACTION.CREATE": "Створити", + "ACTION.INCLUDE": "Включити", + "ACTION.GENERATE": "Згенерувати", + "ACTION.REMOVE": "Видалити", + "ACTION.CANCEL": "Відмінити", + "ACTION.CONFIRM": "Підтвердити", + "ACTION.SUBMIT": "Надіслати", + "ACTION.SEARCH": "Пошук", + "ACTION.SWAP": "Обміняти", + "ACTION.MERGE": "Об'єднати", + "ACTION.SPLIT": "Розділити", + "ACTION.RESET": "Скинути", + "ACTION.PREVIEW": "Попередній перегляд", + "ACTION.UPLOAD": "Завантажити", + "ACTION.DELETE": "Видалити", + "ACTION.CLOSE": "Закрити", + "ACTION.CLEAR": "Очистити", + "ACTION.CLEAR_FILTERS": "Очистити фільтри", + "ACTION.EDIT": "Редагувати", + "STATE.CREATING": "Створення", + "STATE.GENERATING": "Генерування", + "STATE.SAVING": "Збереження", + "STATE.REMOVING": "Видалення", + "STATE.LOADING": "Завантаження", + "STATE.UPDATING": "Оновлюється", + "ERROR": "Помилка", + "PERMISSION": "Дозвіл", + "PERMISSION.PERMISSIONS": "Дозволи", + "PERMISSION.PERMISSION_NAME": "Назва дозволу", + "PERMISSION.SLUG": "Slug", + "PERMISSION.EDIT_PERMISSION": "Редагувати дозвіл", + "ROLE": "Роль", + "ROLE.ROLES": "Ролі", + "ROLE.ROLE_NAME": "Назва ролі", + "ROLE.SLUG": "Slug", + "ROLE.EDIT_ROLE": "Редагувати роль", + "USER": "Користувач", + "USER.EDIT_USER": "Редагувати користувача", + "USER.STATUS.ACTIVE": "Активний", + "USER.STATUS.INACTIVE": "Неактивний", + "USER.MENU.MY_PROFILE": "Мій профіль", + "USER.MENU.MY_ACCOUNT": "Мій обліковий запис", + "USER.MENU.LANGUAGE": "Мова", + "USER.MENU.DARK_MODE": "Темний режим", + "USER.MENU.LOGOUT": "Вийти", + "SUCCESS": "Успіх", + "ACTIONS": "Дії", + "FILTER": "Фільтр", + "SELECTED": "Вибрано", + "NAME": "Ім'я", + "FIRST_NAME": "Ім'я", + "LAST_NAME": "Прізвище", + "EMAIL": "Електронна пошта", + "SELECT": "Виберіть", + "SELECT_OPTION": "Виберіть Опцію", + "SELECT_ALL": "Вибрати Всі", + "SELECT_ALL_WITH_OPTS_LENGTH": "Вибрати Всі ({length} опцій)", + "STATUS": "Статус", + "PASSWORD": "Пароль", + "NEW_PASSWORD": "Новий пароль", + "PASSWORD_CONFIRM": "Підтвердження пароля", + "MODULE_NAME": "Назва модуля", + "RETURN_HOME": "Повернутись додому", + "NO_ITEMS_FOUND": "Не знайдено жодного елемента", + "NO_RESULTS_FOUND": "Результатів не знайдено", + "PLUS_MORE_WITH_NUMBER": "+ {number} ще", + "ADMIN.ADMIN_MANAGEMENT": "Адмін Управління", + "ADMIN.ADMINS": "Адміністратори", + "DASHBOARD": "Дашборд", + "FORM.ERROR.REQUIRED": "Обов'язково", + "FORM.ERROR.INVALID_EMAIL_ADDRESS": "Недійсна адреса електронної пошти", + "FORM.ERROR.PASSWORDS_MUST_MATCH": "Паролі мають збігатися", + "FORM.ERROR.MIN_PASSWORD_LENGTH_DESC": "Мінімальна довжина пароля - 8 символів.", + "FORM.ERROR.SOMETHING_WENT_WRONG": "Щось пішло не так", + "TABLE.COMMON.COLUMNS": "Колонки", + "TABLE.COMMON.NO_DATA_AVAILABLE": "Немає доступних даних", + "TABLE.COMMON.ROWS_PER_PAGE": "Рядків на сторінці", + "TABLE.COMMON.GO_TO_PREVIOUS_PAGE": "Перейти на попередню сторінку", + "TABLE.COMMON.GO_TO_NEXT_PAGE": "Перейти на наступну сторінку", + "PROFILE.PROFILE_SETTINGS": "Налаштування профілю", + "PROFILE.AVATAR_DESCRIPTION": "Радимо використовувати зображення розміром принаймні 98 x 98 пікселів (розмір файлу - до 4 МБ) у форматі PNG, JPG , JPEG.", + "PROFILE.AVATAR_ALT": "Аватар", + "PROFILE.AVATAR_SETTINGS": "Налаштування аватара", + "PROFILE.AVATAR_CROP_ME": "Обріж мене", + "PROFILE.EDIT_PROFILE_IMAGE": "Редагувати зображення профілю", + "MODULE.COMMON.REMOVE_ITEM_QUESTION": "Ви впевнені, що хочете видалити {target}?", + "MODULE.COMMON.ARE_YOU_SURE?": "Ви впевнені?", + "MODULE.COMMON.REMOVE_ITEM_QUESTION_DESC": "Цю дію не можна скасувати.", + "MODULE.COMMON.CREATE_NEW_ENTITY": "Створити новий {entity}", + "MODULE.COMMON.CREATE_NEW_USER": "Створити нового користувача", + "MESSAGE.PLEASE_WAIT": "Будь ласка, зачекайте", + "MESSAGE.PLEASE_WAIT_THIS_MAY_TAKE_FEW_MOMENTS": "Зачекайте хвилинку, це може зайняти деякий час", + "COMMON.SELECT_FILE_TO_VIEW_ITS_CONTENT": "Виберіть файл, щоб переглянути його вміст", + "COMPONENT.FILE_INPUT.SELECTED_NUM_OF_FILES": "Вибрано {num} файл(и)", + "COMPONENT.FILE_INPUT.SELECT_FILE_NO_FILE_SELECTED": "Виберіть файл, файл не вибрано", + "COMPONENT.FILE_INPUT.OPTION.FROM_CLOUD_STORAGE": "З хмарного сховища", + "COMPONENT.FILE_INPUT.OPTION.FROM_LOCAL_MACHINE": "З локального комп'ютера", + "COMPONENT.FILE_INPUT.OPTION.CLEAR": "Очистити", + "COMPONENT.FILE_INPUT.SHOW_SELECTED_FILES": "Показати вибрані файли", + "COMPONENT.FILE_INPUT.SELECTED_FILES": "Вибрані файли", + "COMPONENT.FILE_INPUT.REMOVE_NAME": "Видалити {name}" +} diff --git a/apps/admin/src/app/i18n/types.ts b/apps/admin/src/app/i18n/types.ts new file mode 100755 index 0000000..5900e70 --- /dev/null +++ b/apps/admin/src/app/i18n/types.ts @@ -0,0 +1,23 @@ +import { type MessageFormatElement } from 'react-intl'; +import { TimeMode } from '@crux-kit/types'; + +export type LanguageCode = 'en' | 'ar' | 'uk'; + +export type LanguageDirection = 'ltr' | 'rtl'; + +export interface Language { + label: string; + code: LanguageCode; + direction: LanguageDirection; + flag: string; + messages: Record | Record; + phoneMask?: string; + timeMode: TimeMode; +} + +export interface I18nProviderProps { + languages: Language[]; + currenLanguage: Language; + isRTL: () => boolean; + changeLanguage: (lang: Language) => void; +} diff --git a/apps/admin/src/app/i18n/useIntlDate.ts b/apps/admin/src/app/i18n/useIntlDate.ts new file mode 100644 index 0000000..12797b5 --- /dev/null +++ b/apps/admin/src/app/i18n/useIntlDate.ts @@ -0,0 +1,20 @@ +import { useMemo } from 'react'; +import useLanguage from '#app/i18n/useLanguage'; +import { IntlDate } from '#infrastructure/IntlDate'; + +type DisplayFormat = Parameters[0]; +type SourceFormat = Parameters[1]; + +const useIntlDate = () => { + const { currenLanguage } = useLanguage(); + + return useMemo( + () => + (value: string, format: DisplayFormat, sourceFormat: SourceFormat = 'UNIVERSAL_ISO') => + IntlDate.parseSource(value, sourceFormat).formatToDisplay(format), + // eslint-disable-next-line react-hooks/exhaustive-deps + [currenLanguage.code] + ); +}; + +export default useIntlDate; diff --git a/apps/admin/src/app/i18n/useIntlName.ts b/apps/admin/src/app/i18n/useIntlName.ts new file mode 100644 index 0000000..6bb9718 --- /dev/null +++ b/apps/admin/src/app/i18n/useIntlName.ts @@ -0,0 +1,18 @@ +import { useMemo } from 'react'; +import useLanguage from '#app/i18n/useLanguage'; +import { IntlName } from '#infrastructure/IntlName'; + +type NameInput = Parameters[0]; +type NameFormat = Parameters[1]; + +const useIntlName = () => { + const { currenLanguage } = useLanguage(); + + return useMemo( + () => (input: NameInput, format: NameFormat) => IntlName.formatToDisplay(input, format), + // eslint-disable-next-line react-hooks/exhaustive-deps + [currenLanguage.code] + ); +}; + +export default useIntlName; diff --git a/apps/admin/src/app/i18n/useLanguage.ts b/apps/admin/src/app/i18n/useLanguage.ts new file mode 100644 index 0000000..4352a3e --- /dev/null +++ b/apps/admin/src/app/i18n/useLanguage.ts @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import TranslationsContext from '#app/i18n/context'; + +const useLanguage = () => { + const context = useContext(TranslationsContext); + + if (!context) throw new Error('useLanguage must be used within I18nProvider'); + + return context; +}; + +export default useLanguage; diff --git a/apps/admin/src/app/layouts/01__Default/components/Breadcrumb.tsx b/apps/admin/src/app/layouts/01__Default/components/Breadcrumb.tsx new file mode 100755 index 0000000..c210121 --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/Breadcrumb.tsx @@ -0,0 +1,41 @@ +import { ChevronRight } from 'lucide-react'; +import { Fragment } from 'react'; +import { useLocation } from 'react-router'; +import { cn } from '@crux-kit/utils'; +import { MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; + +export function Breadcrumb() { + const { pathname } = useLocation(); + const { getBreadcrumb, isActive } = useMenu(pathname); + const menuConfig = useMenuConfig(); + const items: MenuItem[] = getBreadcrumb(menuConfig); + + if (items.length === 0) { + return null; + } + + return ( +
+ {items.map((item, index) => { + const last = index === items.length - 1; + const active = item.path ? isActive(item.path) : false; + + return ( + + + {item.title} + + {!last && ( + + )} + + ); + })} +
+ ); +} diff --git a/apps/admin/src/app/layouts/01__Default/components/Content.tsx b/apps/admin/src/app/layouts/01__Default/components/Content.tsx new file mode 100755 index 0000000..1142bec --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/Content.tsx @@ -0,0 +1,19 @@ +import { Outlet } from 'react-router'; +import { useIsMobile } from '@crux-kit/hooks'; +import { Container } from '#shared/widgets/common/Container'; +import { Breadcrumb } from './Breadcrumb'; + +export function Content() { + const mobile = useIsMobile(); + + return ( +
+ {mobile && ( + + + + )} + +
+ ); +} diff --git a/apps/admin/src/app/layouts/01__Default/components/Footer.tsx b/apps/admin/src/app/layouts/01__Default/components/Footer.tsx new file mode 100755 index 0000000..39d24e5 --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/Footer.tsx @@ -0,0 +1,42 @@ +import { generalSettings } from '#app/config/general'; +import { Container } from '#shared/widgets/common/Container'; + +export function Footer() { + const currentYear = new Date().getFullYear(); + + return ( + + ); +} diff --git a/apps/admin/src/app/layouts/01__Default/components/Header.tsx b/apps/admin/src/app/layouts/01__Default/components/Header.tsx new file mode 100755 index 0000000..0014ab7 --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/Header.tsx @@ -0,0 +1,101 @@ +import { Menu, SquareChevronRight } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { useLocation } from 'react-router'; +import { Link } from 'react-router-dom'; +import { useIsMobile, useScrollPosition } from '@crux-kit/hooks'; +import { cn } from '@crux-kit/utils'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import { Button } from '#shared/ui/Button'; +import { Sheet, SheetBody, SheetContent, SheetHeader, SheetTrigger } from '#shared/ui/Sheet'; +import { Container } from '#shared/widgets/common/Container'; +import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu'; +import { MegaMenu } from './MegaMenu'; +import { MegaMenuMobile } from './MegaMenuMobile'; +import { SidebarMenu } from './SidebarMenu'; + +export function Header() { + const [isSidebarSheetOpen, setIsSidebarSheetOpen] = useState(false); + const [isMegaMenuSheetOpen, setIsMegaMenuSheetOpen] = useState(false); + + const { pathname } = useLocation(); + const mobileMode = useIsMobile(); + + const scrollPosition = useScrollPosition(); + const headerSticky: boolean = scrollPosition > 0; + + // Close sheet when route changes + useEffect(() => { + setIsSidebarSheetOpen(false); + setIsMegaMenuSheetOpen(false); + }, [pathname]); + + return ( +
+ + {/* HeaderLogo */} +
+ + mini-logo + +
+ {mobileMode && ( + + + + + + + + + + + + )} + {mobileMode && ( + + + + + + + + + + + + )} +
+
+ + {/* Main Content (MegaMenu) */} + {!mobileMode && } + + {/* HeaderTopbar */} +
+ + } + /> +
+
+
+ ); +} diff --git a/apps/admin/src/app/layouts/01__Default/components/MegaMenu.tsx b/apps/admin/src/app/layouts/01__Default/components/MegaMenu.tsx new file mode 100755 index 0000000..5df9b1d --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/MegaMenu.tsx @@ -0,0 +1,119 @@ +import { + NavigationMenu, + // NavigationMenuContent, + // NavigationMenuItem, + // NavigationMenuLink, + NavigationMenuList + // NavigationMenuTrigger, +} from '#shared/ui/NavigationMenu'; + +// import { useMenu } from '#shared/hooks/use_menu'; +// import { cn } from '@crux-kit/utils'; +// import { MegaMenuSubAccount } from '#shared/widgets/mega_menu/mega_menu_sub_account'; +// import { MegaMenuSubAuth } from '#shared/widgets/mega_menu/mega_menu_sub_auth'; +// import { MegaMenuSubNetwork } from '#shared/widgets/mega_menu/mega_menu_sub_network'; +// import { MegaMenuSubProfiles } from '#shared/widgets/mega_menu/mega_menu_sub_profiles'; +// import { MegaMenuSubStore } from '#shared/widgets/mega_menu/mega_menu_sub_store'; + +export function MegaMenu() { + // const { pathname } = useLocation(); + // const { isActive, hasActiveChild } = useMenu(pathname); + // const homeItem = MENU_MEGA[0]; + // const publicProfilesItem = MENU_MEGA[1]; + // const myAccountItem = MENU_MEGA[2]; + // const networkItem = MENU_MEGA[3]; + // const authItem = MENU_MEGA[4]; + // const storeItem = MENU_MEGA[5]; + + // const linkClass = ` + // text-sm text-secondary-foreground font-medium + // hover:text-primary hover:bg-transparent + // focus:text-primary focus:bg-transparent + // data-[active=true]:text-primary data-[active=true]:bg-transparent + // data-[state=open]:text-primary data-[state=open]:bg-transparent + // `; + + return ( + + + {/* Home Item */} + {/* + + + {homeItem.title} + + + */} + + {/* Public Profiles Item */} + {/* + + {publicProfilesItem.title} + + + + + */} + + {/* My Account Item */} + {/* + + {myAccountItem.title} + + + + + */} + + {/* Network Item */} + {/* + + {networkItem.title} + + + + + */} + + {/* Store Item */} + {/* + + {storeItem.title} + + + + + */} + + {/* Authentication Item */} + {/* + + {authItem.title} + + + + + */} + + + ); +} diff --git a/apps/admin/src/app/layouts/01__Default/components/MegaMenuMobile.tsx b/apps/admin/src/app/layouts/01__Default/components/MegaMenuMobile.tsx new file mode 100755 index 0000000..eca44f3 --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/MegaMenuMobile.tsx @@ -0,0 +1,197 @@ +'use client'; + +import { LucideIcon } from 'lucide-react'; +import { JSX, useCallback } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +// import { MENU_MEGA_MOBILE } from '#app/menu'; +import { + AccordionMenu, + AccordionMenuClassNames, + AccordionMenuGroup, + AccordionMenuItem, + // AccordionMenuLabel, + AccordionMenuSub, + AccordionMenuSubContent, + AccordionMenuSubTrigger +} from '#shared/ui/AccordionMenu'; +import { Badge } from '#shared/ui/Badge'; + +export interface MenuItem { + title?: string; + icon?: LucideIcon; + path?: string; + rootPath?: string; + childrenIndex?: number; + heading?: string; + children?: MenuItem[]; + disabled?: boolean; + collapse?: boolean; + collapseTitle?: string; + expandTitle?: string; + badge?: string; + separator?: boolean; +} + +export type MenuConfig = MenuItem[]; + +export function MegaMenuMobile() { + const { pathname } = useLocation(); + + // Memoize matchPath to prevent unnecessary re-renders + const matchPath = useCallback( + (path: string): boolean => path === pathname || (path.length > 1 && pathname.startsWith(path)), + [pathname] + ); + + // Global classNames for consistent styling + const classNames: AccordionMenuClassNames = { + root: 'space-y-1', + group: 'gap-px', + label: 'uppercase text-xs font-medium text-muted-foreground/70 pt-2.25 pb-px', + separator: '', + item: 'h-8 hover:bg-transparent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-muted data-[selected=true]:font-medium', + sub: '', + subTrigger: + 'h-8 hover:bg-transparent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-muted data-[selected=true]:font-medium', + subContent: 'py-0', + indicator: '' + }; + + // const buildMenu = (items: MenuConfig): JSX.Element[] => { + // return items.map((item: MenuItem, index: number) => { + // if (item.heading) { + // return buildMenuHeading(item, index); + // } else if (!item.disabled) { + // return buildMenuItemRoot(item, index); + // } else { + // return <>; + // } + // }); + // }; + + // const buildMenuItemRoot = (item: MenuItem, index: number): JSX.Element => { + // if (item.children) { + // return ( + // + // + // {item.icon && } + //
+ // {item.title} + // {item.badge && ( + // + // {item.badge} + // + // )} + //
+ //
+ // + // {buildMenuItemChildren(item.children, 1)} + // + //
+ // ); + // } else { + // return ( + // + // + // {item.icon && } + //
+ // {item.title} + // {item.badge && ( + // + // {item.badge} + // + // )} + //
+ // + //
+ // ); + // } + // }; + + const buildMenuItemChildren = (items: MenuConfig, level: number = 0): JSX.Element[] => { + return items.map((item: MenuItem, index: number) => { + if (!item.disabled) { + return buildMenuItemChild(item, index, level); + } else { + return <>; + } + }); + }; + + const buildMenuItemChild = (item: MenuItem, index: number, level: number = 0): JSX.Element => { + if (item.children) { + return ( + + + {item.icon && } + {item.collapse ? ( + + + {item.collapseTitle} + + {item.expandTitle} + + ) : ( + item.title + )} + {item.badge && ( + + {item.badge} + + )} + + + + {buildMenuItemChildren(item.children, item.collapse ? level : level + 1)} + + + + ); + } else { + return ( + + + {item.icon && } +
+ {item.title} + {item.badge && ( + + {item.badge} + + )} +
+ +
+ ); + } + }; + + // const buildMenuHeading = (item: MenuItem, index: number): JSX.Element => { + // return {item.heading}; + // }; + + return ( +
+ + {/* {buildMenu(MENU_MEGA_MOBILE)} */} + +
+ ); +} diff --git a/apps/admin/src/app/layouts/01__Default/components/Sidebar.tsx b/apps/admin/src/app/layouts/01__Default/components/Sidebar.tsx new file mode 100755 index 0000000..d7d1e0b --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/Sidebar.tsx @@ -0,0 +1,29 @@ +import { useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { SidebarHeader } from './SidebarHeader'; +import { SidebarMenu } from './SidebarMenu'; + +export function Sidebar() { + const { settings } = useSettings(); + const { pathname } = useLocation(); + + return ( +
+ +
+
+ +
+
+
+ ); +} diff --git a/apps/admin/src/app/layouts/01__Default/components/SidebarHeader.tsx b/apps/admin/src/app/layouts/01__Default/components/SidebarHeader.tsx new file mode 100755 index 0000000..e1ef1a1 --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/SidebarHeader.tsx @@ -0,0 +1,63 @@ +import { ChevronFirst } from 'lucide-react'; +import { Link } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import { Button } from '#shared/ui/Button'; + +export function SidebarHeader() { + const { settings, storeOption } = useSettings(); + + const handleToggleClick = () => { + storeOption( + `layouts.${LayoutNames.DEFAULT}.sidebarCollapse`, + !settings.layouts[LayoutNames.DEFAULT].sidebarCollapse + ); + }; + + return ( +
+ +
+ {/* Default Logo + Mini Logo */} +
+
+ {/* Default Dark Logo */} + Mini Logo +
+ + +
+ ); +} diff --git a/apps/admin/src/app/layouts/01__Default/components/SidebarMenu.tsx b/apps/admin/src/app/layouts/01__Default/components/SidebarMenu.tsx new file mode 100755 index 0000000..65be97e --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/SidebarMenu.tsx @@ -0,0 +1,181 @@ +'use client'; + +import { JSX, useMemo } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuConfig, MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { createMenuPathMatcher } from '#shared/lib/menuPath'; +import { AccordionMenu, AccordionMenuClassNames, AccordionMenuGroup, AccordionMenuItem, AccordionMenuLabel, AccordionMenuSub, AccordionMenuSubContent, AccordionMenuSubTrigger } from '#shared/ui/AccordionMenu'; +import { Badge } from '#shared/ui/Badge'; + +export function SidebarMenu() { + const { pathname } = useLocation(); + const menuConfig = useMenuConfig(); + + // Memoize matchPath to prevent unnecessary re-renders + const matchPath = useMemo( + () => createMenuPathMatcher(menuConfig, pathname), + [menuConfig, pathname] + ); + + // Global classNames for consistent styling + const classNames: AccordionMenuClassNames = { + root: 'lg:ps-1 space-y-3', + group: 'gap-px', + label: 'uppercase text-xs font-medium text-muted-foreground/70 pt-2.25 pb-px', + separator: '', + item: 'h-8 hover:bg-transparent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-muted data-[selected=true]:font-medium', + sub: '', + subTrigger: + 'h-8 hover:bg-transparent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-muted data-[selected=true]:font-medium', + subContent: 'py-0', + indicator: '' + }; + + const buildMenu = (items: MenuConfig): JSX.Element[] => { + return items.map((item: MenuItem, index: number) => { + if (item.heading) { + return buildMenuHeading(item, index); + } else if (item.disabled) { + return buildMenuItemRootDisabled(item, index); + } else { + return buildMenuItemRoot(item, index); + } + }); + }; + + const buildMenuItemRoot = (item: MenuItem, index: number): JSX.Element => { + if (item.children) { + return ( + + + {item.icon && } + {item.title} + + + {buildMenuItemChildren(item.children, 1)} + + + ); + } else { + return ( + + + {item.icon && } + {item.title} + + + ); + } + }; + + const buildMenuItemRootDisabled = (item: MenuItem, index: number): JSX.Element => { + return ( + + {item.icon && } + {item.title} + {item.disabled && ( + + Soon + + )} + + ); + }; + + const buildMenuItemChildren = (items: MenuConfig, level: number = 0): JSX.Element[] => { + return items.map((item: MenuItem, index: number) => { + if (item.disabled) { + return buildMenuItemChildDisabled(item, index, level); + } else { + return buildMenuItemChild(item, index, level); + } + }); + }; + + const buildMenuItemChild = (item: MenuItem, index: number, level: number = 0): JSX.Element => { + if (item.children) { + return ( + + + {item.collapse ? ( + + + {item.collapseTitle} + + {item.expandTitle} + + ) : ( + item.title + )} + + 0 ? '' : '') + )} + > + + {buildMenuItemChildren(item.children, item.collapse ? level : level + 1)} + + + + ); + } else { + return ( + + {item.title} + + ); + } + }; + + const buildMenuItemChildDisabled = ( + item: MenuItem, + index: number, + level: number = 0 + ): JSX.Element => { + return ( + + {item.title} + {item.disabled && ( + + Soon + + )} + + ); + }; + + const buildMenuHeading = (item: MenuItem, index: number): JSX.Element => { + return {item.heading}; + }; + + return ( +
+ + {buildMenu(menuConfig)} + +
+ ); +} diff --git a/apps/admin/src/app/layouts/01__Default/components/Toolbar.tsx b/apps/admin/src/app/layouts/01__Default/components/Toolbar.tsx new file mode 100755 index 0000000..f594b2f --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/components/Toolbar.tsx @@ -0,0 +1,86 @@ +import { ChevronRight } from 'lucide-react'; +import { Fragment, ReactNode } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; + +export interface ToolbarHeadingProps { + title?: string | ReactNode; + description?: string | ReactNode; +} + +function Toolbar({ children }: { children?: ReactNode }) { + return
{children}
; +} + +function ToolbarActions({ children }: { children?: ReactNode }) { + return
{children}
; +} + +function ToolbarBreadcrumbs() { + const config = useMenuConfig(); + const { pathname } = useLocation(); + const { getBreadcrumb, isActive } = useMenu(pathname); + const items: MenuItem[] = getBreadcrumb(config); + + if (items.length === 0) { + return null; + } + + return ( +
+
+ {items.map((item, index) => { + const isLast = index === items.length - 1; + const active = item.path ? isActive(item.path) : false; + + return ( + + {item.path ? ( + + {item.title} + + ) : ( + + {item.title} + + )} + {!isLast && } + + ); + })} +
+
+ ); +} + +function ToolbarHeading({ title = '', description }: ToolbarHeadingProps) { + const { pathname } = useLocation(); + const { getCurrentItem } = useMenu(pathname); + const config = useMenuConfig(); + + const item = getCurrentItem(config); + + return ( +
+

+ {title || item?.title || 'Untitled'} +

+ {description && ( +
+ {description} +
+ )} +
+ ); +} + +export { Toolbar, ToolbarActions, ToolbarBreadcrumbs, ToolbarHeading }; diff --git a/apps/admin/src/app/layouts/01__Default/layout.tsx b/apps/admin/src/app/layouts/01__Default/layout.tsx new file mode 100755 index 0000000..428016e --- /dev/null +++ b/apps/admin/src/app/layouts/01__Default/layout.tsx @@ -0,0 +1,70 @@ +// DEMO 1 +// https://keenthemes.com/metronic/tailwind/react/demo1 + +import { useEffect } from 'react'; +import { Outlet } from 'react-router-dom'; +import { useIsMobile } from '@crux-kit/hooks'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { Footer } from './components/Footer'; +import { Header } from './components/Header'; +import { Sidebar } from './components/Sidebar'; + +export function DefaultLayout() { + const isMobile = useIsMobile(); + const { settings, setOption } = useSettings(); + + useEffect(() => { + const bodyClass = document.body.classList; + + if (settings.layouts[LayoutNames.DEFAULT].sidebarCollapse) { + bodyClass.add('sidebar-collapse'); + } else { + bodyClass.remove('sidebar-collapse'); + } + }, [settings]); // Runs only on settings update + + useEffect(() => { + // Set current layout + setOption('layout', LayoutNames.DEFAULT); + }, [setOption]); + + useEffect(() => { + const bodyClass = document.body.classList; + + // Add a class to the body element + bodyClass.add(LayoutNames.DEFAULT); + bodyClass.add('sidebar-fixed'); + bodyClass.add('header-fixed'); + + const timer = setTimeout(() => { + bodyClass.add('layout-initialized'); + }, 1000); // 1000 milliseconds + + // Remove the class when the component is unmounted + return () => { + bodyClass.remove(LayoutNames.DEFAULT); + bodyClass.remove('sidebar-fixed'); + bodyClass.remove('sidebar-collapse'); + bodyClass.remove('header-fixed'); + bodyClass.remove('layout-initialized'); + clearTimeout(timer); + }; + }, []); // Runs only once on mount + + return ( + <> + {!isMobile && } + +
+
+ +
+ +
+ +
+
+ + ); +} diff --git a/apps/admin/src/app/layouts/02__HorizontalMenu/components/Footer.tsx b/apps/admin/src/app/layouts/02__HorizontalMenu/components/Footer.tsx new file mode 100755 index 0000000..39d24e5 --- /dev/null +++ b/apps/admin/src/app/layouts/02__HorizontalMenu/components/Footer.tsx @@ -0,0 +1,42 @@ +import { generalSettings } from '#app/config/general'; +import { Container } from '#shared/widgets/common/Container'; + +export function Footer() { + const currentYear = new Date().getFullYear(); + + return ( + + ); +} diff --git a/apps/admin/src/app/layouts/02__HorizontalMenu/components/Header.tsx b/apps/admin/src/app/layouts/02__HorizontalMenu/components/Header.tsx new file mode 100755 index 0000000..0a78112 --- /dev/null +++ b/apps/admin/src/app/layouts/02__HorizontalMenu/components/Header.tsx @@ -0,0 +1,45 @@ +import { useEffect, useState } from 'react'; // Add useState to the imports + +import { useScrollPosition } from '@crux-kit/hooks'; +import { cn } from '@crux-kit/utils'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { Container } from '#shared/widgets/common/Container'; +import { HeaderLogo } from './HeaderLogo'; +import { HeaderTopbar } from './HeaderTopbar'; + +export function Header() { + const { settings } = useSettings(); + const scrollPosition = useScrollPosition(); + const [headerStickyOn, setHeaderStickyOn] = useState(false); + + useEffect(() => { + const isSticky = + scrollPosition > settings.layouts[LayoutNames.HORIZONTAL_MENU].headerStickyOffset; + setHeaderStickyOn(isSticky); + }, [scrollPosition, settings]); + + useEffect(() => { + if (headerStickyOn === true) { + document.body.setAttribute('data-sticky-header', 'on'); + } else { + document.body.removeAttribute('data-sticky-header'); + } + }, [headerStickyOn]); + + return ( +
+ + + + +
+ ); +} diff --git a/apps/admin/src/app/layouts/02__HorizontalMenu/components/HeaderLogo.tsx b/apps/admin/src/app/layouts/02__HorizontalMenu/components/HeaderLogo.tsx new file mode 100755 index 0000000..19dc848 --- /dev/null +++ b/apps/admin/src/app/layouts/02__HorizontalMenu/components/HeaderLogo.tsx @@ -0,0 +1,71 @@ +// import { useEffect, useState } from 'react'; +// import { ChevronDown } from 'lucide-react'; +import { Link } from 'react-router-dom'; +// import { MENU_ROOT } from '#app/menu'; +// import { +// DropdownMenu, +// DropdownMenuContent, +// DropdownMenuItem, +// DropdownMenuTrigger, +// } from '#shared/ui/dropdown_menu'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; + +// import { cn } from '@crux-kit/utils'; + +export function HeaderLogo() { + // const { pathname } = useLocation(); + // const [selectedMenuItem, setSelectedMenuItem] = useState(MENU_ROOT[1]); + + // useEffect(() => { + // MENU_ROOT.forEach((item) => { + // if (item.rootPath && pathname.includes(item.rootPath)) { + // setSelectedMenuItem(item); + // } + // }); + // }, [pathname]); + + return ( +
+ {/* Logo Section */} + + logo + logo + + + {/* Menu Section */} +
+

Metronic Team

+ / + + {/* + + {selectedMenuItem.title} + + + + {MENU_ROOT.map((item, index) => ( + + + {item.icon && } + {item.title} + + + ))} + + */} +
+
+ ); +} diff --git a/apps/admin/src/app/layouts/02__HorizontalMenu/components/HeaderTopbar.tsx b/apps/admin/src/app/layouts/02__HorizontalMenu/components/HeaderTopbar.tsx new file mode 100755 index 0000000..1779a68 --- /dev/null +++ b/apps/admin/src/app/layouts/02__HorizontalMenu/components/HeaderTopbar.tsx @@ -0,0 +1,46 @@ +// import { MessageCircleMore, MessageSquareDot, Search } from 'lucide-react'; +// import { Button } from '#shared/ui/button'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog'; +// import { ChatSheet } from '#shared/partials/topbar/chat-sheet'; +// import { NotificationsSheet } from '#shared/partials/topbar/notifications-sheet'; +import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu'; + +export function HeaderTopbar() { + return ( +
+
+ {/* + + + } + /> + + + + } + /> + + + + } + /> */} +
+ + } + /> +
+ ); +} diff --git a/apps/admin/src/app/layouts/02__HorizontalMenu/components/Navbar.tsx b/apps/admin/src/app/layouts/02__HorizontalMenu/components/Navbar.tsx new file mode 100755 index 0000000..36cca9e --- /dev/null +++ b/apps/admin/src/app/layouts/02__HorizontalMenu/components/Navbar.tsx @@ -0,0 +1,14 @@ +import { Container } from '#shared/widgets/common/Container'; +import { NavbarLinks } from './NavbarLinks'; +import { NavbarMenu } from './NavbarMenu'; + +export function Navbar() { + return ( +
+ + + + +
+ ); +} diff --git a/apps/admin/src/app/layouts/02__HorizontalMenu/components/NavbarLinks.tsx b/apps/admin/src/app/layouts/02__HorizontalMenu/components/NavbarLinks.tsx new file mode 100755 index 0000000..765416b --- /dev/null +++ b/apps/admin/src/app/layouts/02__HorizontalMenu/components/NavbarLinks.tsx @@ -0,0 +1,15 @@ +export function NavbarLinks() { + return ( + + ); +} diff --git a/apps/admin/src/app/layouts/02__HorizontalMenu/components/NavbarMenu.tsx b/apps/admin/src/app/layouts/02__HorizontalMenu/components/NavbarMenu.tsx new file mode 100755 index 0000000..162a07d --- /dev/null +++ b/apps/admin/src/app/layouts/02__HorizontalMenu/components/NavbarMenu.tsx @@ -0,0 +1,128 @@ +import { ChevronDown } from 'lucide-react'; +import { useMemo } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuConfig } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; +import { createMenuPathMatcher } from '#shared/lib/menuPath'; +import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from '#shared/ui/MenuBar'; + +export function NavbarMenu() { + const { pathname } = useLocation(); + const menuConfig = useMenuConfig(); + + let navbarMenu; + + if (pathname.includes('/public-profile/')) { + navbarMenu = menuConfig?.[2]; + } else if (pathname.includes('/network/')) { + navbarMenu = menuConfig?.[4]; + } else if (pathname.includes('/store-client/')) { + navbarMenu = menuConfig?.[0]; + } else if (pathname.includes('/authentication/')) { + navbarMenu = menuConfig?.[5]; + } else { + navbarMenu = menuConfig?.[3]; + } + + const { hasActiveChild } = useMenu(pathname); + // A leaf highlights only when nothing deeper in the menu matches the route more closely. + const isActive = useMemo( + () => createMenuPathMatcher((navbarMenu?.children ?? []) as MenuConfig, pathname), + [navbarMenu, pathname] + ); + + const buildMenu = (items: MenuConfig) => { + return items.map((item, index) => { + if (item.children) { + return ( + + + {item.title} + + + + {buildSubMenu(item.children)} + + + ); + } else { + return ( + + + + {item.title} + + + + ); + } + }); + }; + + const buildSubMenu = (items: MenuConfig) => { + return items.map((item, index) => { + if (item.children) { + return ( + + + {item.title} + + + {buildSubMenu(item.children)} + + + ); + } else { + return ( + + {item.title} + + ); + } + }); + }; + + return ( +
+
+ + {buildMenu(navbarMenu.children as MenuConfig)} + +
+
+ ); +} diff --git a/apps/admin/src/app/layouts/02__HorizontalMenu/components/Toolbar.tsx b/apps/admin/src/app/layouts/02__HorizontalMenu/components/Toolbar.tsx new file mode 100755 index 0000000..95cbf35 --- /dev/null +++ b/apps/admin/src/app/layouts/02__HorizontalMenu/components/Toolbar.tsx @@ -0,0 +1,86 @@ +import { ChevronRight } from 'lucide-react'; +import { Fragment, ReactNode } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; +import { Container } from '#shared/widgets/common/Container'; + +export interface ToolbarHeadingProps { + title?: string | ReactNode; + description?: string | ReactNode; +} + +function Toolbar({ children }: { children?: ReactNode }) { + return ( +
+ + {children} + +
+ ); +} + +function ToolbarActions({ children }: { children?: ReactNode }) { + return
{children}
; +} + +function ToolbarBreadcrumbs() { + const menuConfig = useMenuConfig(); + const { pathname } = useLocation(); + const { getBreadcrumb, isActive } = useMenu(pathname); + const items: MenuItem[] = getBreadcrumb(menuConfig); + + if (items.length === 0) { + return null; + } + + return ( +
+
+ {items.map((item, index) => { + const isLast = index === items.length - 1; + const active = item.path ? isActive(item.path) : false; + + return ( + + {item.path ? ( + + {item.title} + + ) : ( + + {item.title} + + )} + {!isLast && } + + ); + })} +
+
+ ); +} + +const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => { + const { pathname } = useLocation(); + const { getCurrentItem } = useMenu(pathname); + const menuConfig = useMenuConfig(); + const item = getCurrentItem(menuConfig); + + return ( +
+

{title || item?.title}

+ +
+ ); +}; + +export { Toolbar, ToolbarActions, ToolbarBreadcrumbs, ToolbarHeading }; diff --git a/apps/admin/src/app/layouts/02__HorizontalMenu/layout.tsx b/apps/admin/src/app/layouts/02__HorizontalMenu/layout.tsx new file mode 100755 index 0000000..aa6701e --- /dev/null +++ b/apps/admin/src/app/layouts/02__HorizontalMenu/layout.tsx @@ -0,0 +1,90 @@ +// DEMO 2 +// https://keenthemes.com/metronic/tailwind/react/demo2 + +import { addDays, format } from 'date-fns'; +import { CalendarDays } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { DateRange } from 'react-day-picker'; +import { Outlet, useLocation } from 'react-router-dom'; +import { useBodyClass } from '@crux-kit/hooks'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { Button } from '#shared/ui/Button'; +import { Calendar } from '#shared/ui/Calendar'; +import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover'; +import { Footer } from './components/Footer'; +import { Header } from './components/Header'; +import { Navbar } from './components/Navbar'; +import { Toolbar, ToolbarActions, ToolbarHeading } from './components/Toolbar'; + +export function HorizontalMenuLayout() { + const { pathname } = useLocation(); + const { setOption } = useSettings(); + + useEffect(() => { + // Set current layout + setOption('layout', LayoutNames.HORIZONTAL_MENU); + }, [setOption]); + + useBodyClass(` + [--header-height-default:100px] + data-[sticky-header=on]:[--header-height:60px] + [--header-height:var(--header-height-default)] + `); + + const [date, setDate] = useState({ + from: new Date(2025, 0, 20), + to: addDays(new Date(2025, 0, 20), 20) + }); + + return ( + <> +
+
+ + + +
+ {!pathname.includes('/public-profile/') && ( + + + + + + + + + + + + + + )} + +
+ +
+
+ + ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/Footer.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/Footer.tsx new file mode 100755 index 0000000..39d24e5 --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/Footer.tsx @@ -0,0 +1,42 @@ +import { generalSettings } from '#app/config/general'; +import { Container } from '#shared/widgets/common/Container'; + +export function Footer() { + const currentYear = new Date().getFullYear(); + + return ( + + ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/Header.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/Header.tsx new file mode 100755 index 0000000..685d266 --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/Header.tsx @@ -0,0 +1,14 @@ +import { Container } from '#shared/widgets/common/Container'; +import { HeaderLogo } from './HeaderLogo'; +import { HeaderTopbar } from './HeaderTopbar'; + +export function Header() { + return ( +
+ + + + +
+ ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/HeaderLogo.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/HeaderLogo.tsx new file mode 100755 index 0000000..4088a69 --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/HeaderLogo.tsx @@ -0,0 +1,87 @@ +import { Menu } from 'lucide-react'; +import { Link } from 'react-router-dom'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +// import { cn } from '@crux-kit/utils'; +import { Button } from '#shared/ui/Button'; +// import { +// DropdownMenu, +// DropdownMenuContent, +// DropdownMenuItem, +// DropdownMenuTrigger, +// } from '#shared/ui/dropdown_menu'; +import { Sheet, SheetBody, SheetContent, SheetHeader, SheetTrigger } from '#shared/ui/Sheet'; +import { SidebarMenu } from './SidebarMenu'; + +export function HeaderLogo() { + // const { pathname } = useLocation(); + // const [selectedMenuItem, setSelectedMenuItem] = useState(MENU_ROOT[1]); + + // useEffect(() => { + // MENU_ROOT.forEach((item) => { + // if (item.rootPath && pathname.includes(item.rootPath)) { + // setSelectedMenuItem(item); + // } + // }); + // }, [pathname]); + + return ( +
+ {/* Logo */} +
+ + + + + + + + + + + + + + logo + logo + +
+ + {/* Menu Section */} +
+

Metronic Team

+ / + + {/* + + {selectedMenuItem.title} + + + + {MENU_ROOT.map((item, index) => ( + + + {item.icon && } + {item.title} + + + ))} + + */} +
+
+ ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/HeaderTopbar.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/HeaderTopbar.tsx new file mode 100755 index 0000000..293aed2 --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/HeaderTopbar.tsx @@ -0,0 +1,56 @@ +// import { LayoutGrid, MessageCircleMore, MessageSquareDot, Search } from 'lucide-react'; +import { Link } from 'react-router-dom'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import { Button } from '#shared/ui/Button'; +// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog'; +// import { AppsDropdownMenu } from '#shared/partials/topbar/apps-dropdown-menu'; +// import { ChatSheet } from '#shared/partials/topbar/chat-sheet'; +// import { NotificationsSheet } from '#shared/partials/topbar/notifications-sheet'; +import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu'; + +export function HeaderTopbar() { + return ( +
+ + {/* + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> */} + + } + /> +
+ ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/Navbar.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/Navbar.tsx new file mode 100755 index 0000000..966ce6c --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/Navbar.tsx @@ -0,0 +1,16 @@ +import { Container } from '#shared/widgets/common/Container'; +import { NavbarLinks } from './NavbarLinks'; +import { NavbarMenu } from './NavbarMenu'; + +export function Navbar() { + return ( +
+
+ + + + +
+
+ ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/NavbarLinks.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/NavbarLinks.tsx new file mode 100755 index 0000000..f4c86f9 --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/NavbarLinks.tsx @@ -0,0 +1,46 @@ +import { addDays, format } from 'date-fns'; +import { CalendarDays } from 'lucide-react'; +import { useState } from 'react'; +import { DateRange } from 'react-day-picker'; +import { Button } from '#shared/ui/Button'; +import { Calendar } from '#shared/ui/Calendar'; +import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover'; + +export function NavbarLinks() { + const [date, setDate] = useState({ + from: new Date(2025, 0, 20), + to: addDays(new Date(2025, 0, 20), 20) + }); + + return ( +
+ + + + + + + + +
+ ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/NavbarMenu.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/NavbarMenu.tsx new file mode 100755 index 0000000..99fefa8 --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/NavbarMenu.tsx @@ -0,0 +1,121 @@ +import { ChevronDown } from 'lucide-react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuConfig } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; +import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from '#shared/ui/MenuBar'; + +export function NavbarMenu() { + const { pathname } = useLocation(); + const menuConfig = useMenuConfig(); + + let navbarMenu; + + if (pathname.includes('/public-profile/')) { + navbarMenu = menuConfig?.[2]; + } else if (pathname.includes('/network/')) { + navbarMenu = menuConfig?.[4]; + } else if (pathname.includes('/store-client/')) { + navbarMenu = menuConfig?.[0]; + } else if (pathname.includes('/authentication/')) { + navbarMenu = menuConfig?.[5]; + } else { + navbarMenu = menuConfig?.[3]; + } + + const { isActive, hasActiveChild } = useMenu(pathname); + + const buildMenu = (items: MenuConfig) => { + return items.map((item, index) => { + if (item.children) { + return ( + + + {item.title} + + + + {buildSubMenu(item.children)} + + + ); + } else { + return ( + + + + {item.title} + + + + ); + } + }); + }; + + const buildSubMenu = (items: MenuConfig) => { + return items.map((item, index) => { + if (item.children) { + return ( + + + {item.title} + + + {buildSubMenu(item.children)} + + + ); + } else { + return ( + + {item.title} + + ); + } + }); + }; + + return ( +
+
+ + {buildMenu(navbarMenu.children as MenuConfig)} + +
+
+ ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/Sidebar.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/Sidebar.tsx new file mode 100755 index 0000000..116123b --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/Sidebar.tsx @@ -0,0 +1,13 @@ +import { SidebarMenu } from './SidebarMenu'; + +export function Sidebar() { + return ( +
+
+
+ +
+
+
+ ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/SidebarMenu.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/SidebarMenu.tsx new file mode 100755 index 0000000..9fc9023 --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/SidebarMenu.tsx @@ -0,0 +1,100 @@ +import { BarChart3, Bell, CheckSquare, Code, HelpCircle, MessageSquare, Settings, Shield, UserCircle, Users } from 'lucide-react'; +import { Link } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { Button } from '#shared/ui/Button'; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '#shared/ui/Tooltip'; + +export interface Item { + icon: React.ComponentType<{ className?: string }>; + path: string; + title: string; + newTab?: boolean; + active?: boolean; +} + +export function SidebarMenu() { + const items: Item[] = [ + { + icon: BarChart3, + path: '/', + title: 'Dashboard' + }, + { + icon: UserCircle, + path: '/public-profile/profiles/default', + title: 'Profile' + }, + { + icon: Settings, + path: '/account/home/get-started', + title: 'Account' + }, + { + icon: Users, + path: '/network/get-started', + title: 'Network', + active: true + }, + { + icon: Shield, + path: '/account/billing/plans', + title: 'Plans' + }, + { + icon: MessageSquare, + path: '/account/security/security-log', + title: 'Security Logs' + }, + { + icon: Bell, + path: '/account/notifications', + title: 'Notifications' + }, + { + icon: CheckSquare, + path: '/account/members/roles', + title: 'ACL' + }, + { + icon: Code, + path: '/account/api-keys', + title: 'API Keys' + }, + { + icon: HelpCircle, + path: 'https://docs.keenthemes.com/metronic-vite', + title: 'Docs' + } + ]; + + return ( + +
+ {items.map((item, index) => ( + + + + + {item.title} + + ))} +
+
+ ); +} diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/components/Toolbar.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/components/Toolbar.tsx new file mode 100755 index 0000000..594197e --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/components/Toolbar.tsx @@ -0,0 +1,87 @@ +import { ChevronRight } from 'lucide-react'; +import { Fragment, ReactNode } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; +import { Container } from '#shared/widgets/common/Container'; + +export interface ToolbarHeadingProps { + title?: string | ReactNode; + description?: string | ReactNode; +} + +function Toolbar({ children }: { children?: ReactNode }) { + return ( +
+ + {children} + +
+ ); +} + +function ToolbarActions({ children }: { children?: ReactNode }) { + return
{children}
; +} + +function ToolbarBreadcrumbs() { + const menuConfig = useMenuConfig(); + + const { pathname } = useLocation(); + const { getBreadcrumb, isActive } = useMenu(pathname); + const items: MenuItem[] = getBreadcrumb(menuConfig); + + if (items.length === 0) { + return null; + } + + return ( +
+
+ {items.map((item, index) => { + const isLast = index === items.length - 1; + const active = item.path ? isActive(item.path) : false; + + return ( + + {item.path ? ( + + {item.title} + + ) : ( + + {item.title} + + )} + {!isLast && } + + ); + })} +
+
+ ); +} + +const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => { + const { pathname } = useLocation(); + const { getCurrentItem } = useMenu(pathname); + const menuConfig = useMenuConfig(); + const item = getCurrentItem(menuConfig); + + return ( +
+

{title || item?.title}

+ +
+ ); +}; + +export { Toolbar, ToolbarActions, ToolbarBreadcrumbs, ToolbarHeading }; diff --git a/apps/admin/src/app/layouts/03__CompactSidebar/layout.tsx b/apps/admin/src/app/layouts/03__CompactSidebar/layout.tsx new file mode 100755 index 0000000..1b0d9ed --- /dev/null +++ b/apps/admin/src/app/layouts/03__CompactSidebar/layout.tsx @@ -0,0 +1,70 @@ +// DEMO 3 +// https://keenthemes.com/metronic/tailwind/react/demo3 + +import { Download } from 'lucide-react'; +import { useEffect } from 'react'; +import { Link, Outlet, useLocation } from 'react-router-dom'; +import { useBodyClass, useIsMobile } from '@crux-kit/hooks'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { Button } from '#shared/ui/Button'; +import { Footer } from './components/Footer'; +import { Header } from './components/Header'; +import { Navbar } from './components/Navbar'; +import { Sidebar } from './components/Sidebar'; +import { Toolbar, ToolbarActions, ToolbarHeading } from './components/Toolbar'; + +export function CompactSidebarLayout() { + const { pathname } = useLocation(); + const { setOption } = useSettings(); + const isMobileMode = useIsMobile(); + + useBodyClass(` + [--header-height:58px] + [--sidebar-width:58px] + [--navbar-height:56px] + lg:overflow-hidden + bg-muted! + `); + + useEffect(() => { + setOption('layout', LayoutNames.COMPACT_SIDEBAR); + setOption('container', 'fluid'); + }, [setOption]); + + return ( + <> +
+
+ +
+ {!isMobileMode && } + + + +
+
+
+ {pathname !== '/' && ( + + + + + + + )} + +
+
+
+
+
+
+ + ); +} diff --git a/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Footer.tsx b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Footer.tsx new file mode 100755 index 0000000..39d24e5 --- /dev/null +++ b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Footer.tsx @@ -0,0 +1,42 @@ +import { generalSettings } from '#app/config/general'; +import { Container } from '#shared/widgets/common/Container'; + +export function Footer() { + const currentYear = new Date().getFullYear(); + + return ( + + ); +} diff --git a/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Header.tsx b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Header.tsx new file mode 100755 index 0000000..a30498d --- /dev/null +++ b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Header.tsx @@ -0,0 +1,53 @@ +import { Menu } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import { Button } from '#shared/ui/Button'; +import { Sheet, SheetBody, SheetContent, SheetHeader, SheetTrigger } from '#shared/ui/Sheet'; +import { Container } from '#shared/widgets/common/Container'; +import { SidebarPrimary } from './SidebarPrimary'; +import { SidebarSecondary } from './SidebarSecondary'; + +export function Header() { + const [isSheetOpen, setIsSheetOpen] = useState(false); + const { pathname } = useLocation(); + + // Close sheet when route changes + useEffect(() => { + setIsSheetOpen(false); + }, [pathname]); + + return ( +
+ + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Sidebar.tsx b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Sidebar.tsx new file mode 100755 index 0000000..cadf301 --- /dev/null +++ b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Sidebar.tsx @@ -0,0 +1,11 @@ +import { SidebarPrimary } from './SidebarPrimary'; +import { SidebarSecondary } from './SidebarSecondary'; + +export function Sidebar() { + return ( +
+ + +
+ ); +} diff --git a/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarMenuDashboard.tsx b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarMenuDashboard.tsx new file mode 100755 index 0000000..6757b4b --- /dev/null +++ b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarMenuDashboard.tsx @@ -0,0 +1,161 @@ +import { Badge, ChevronDown, FileText, Settings, SquareCode, UserCircle } from 'lucide-react'; +import { useCallback, useMemo } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { AccordionMenu, AccordionMenuClassNames, AccordionMenuGroup, AccordionMenuItem, AccordionMenuLabel } from '#shared/ui/AccordionMenu'; +import { Button } from '#shared/ui/Button'; +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '#shared/ui/DropdownMenu'; + +interface DropdownItem { + title: string; + path: string; + icon: React.ComponentType<{ className?: string }>; + active?: boolean; +} + +interface MenuItem { + title: string; + path?: string; + active?: boolean; +} + +interface MenuLabel { + label: string; +} + +type MenuNode = MenuItem | MenuLabel; + +export function SidebarMenuDashboard() { + const { pathname } = useLocation(); + + const dropdownItems: DropdownItem[] = [ + { + title: 'Client API', + path: '/account/home/user-profile', + icon: SquareCode, + active: true + }, + { + title: 'Profile', + path: '/public-profile/profiles/company', + icon: UserCircle + }, + { + title: 'My Account', + path: '/account/integrations', + icon: Settings + }, + { + title: 'Projects', + path: '/public-profile/projects/3-columns', + icon: FileText + }, + { + title: 'Personal info', + path: '/public-profile/profiles/creator', + icon: Badge + } + ]; + + const currentDropdownItem = dropdownItems[0]; + + const menuItems = useMemo( + () => [ + { label: 'Configuration' }, + { title: 'API Setup', path: '/account/api-keys' }, + { title: 'Team Settings', path: '/account/home/settings-sidebar' }, + { title: 'Authentication', path: '/authentication/classic/sign-in' }, + { title: 'Endpoints Configs', path: '/account/appearance' }, + { title: 'Rate Limiting', path: '/public-profile/network' }, + { label: 'Security' }, + { title: 'Data Encryption', path: '/account/billing/enterprise' }, + { title: 'Text', path: '/account/security/overview' }, + { title: 'Access Control', path: '/account/security/privacy-settings' }, + { label: 'Analytics' }, + { + title: 'Incident Response', + path: '/account/security/current-sessions' + }, + { title: 'Fetching Data', path: '/account/members/team-info' }, + { title: 'Custom Reports', path: '/account/home/user-profile' }, + { + title: 'Real Time Analytics', + path: '/account/home/settings-enterprise' + }, + { title: 'Exporting Data', path: '/account/members/import-members' }, + { title: 'Dashboard Integration', path: '/account/members/team-info' } + ], + [] + ); + + const classNames: AccordionMenuClassNames = { + root: 'space-y-1', + label: 'uppercase text-xs font-medium text-muted-foreground/80 pt-6 mb-2 pb-0', + item: 'h-8 hover:bg-background border-accent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-background data-[selected=true]:font-medium' + }; + + const matchPath = useCallback( + (path: string): boolean => path === pathname || (path.length > 1 && pathname.startsWith(path)), + [pathname] + ); + + const buildDropdown = () => { + return ( + + + + + + {dropdownItems.map((item, index) => ( + + + + {item.title} + + + ))} + + + ); + }; + + const buildMenu = () => { + return ( + + + {menuItems.map((item, index) => + 'label' in item ? ( + {item.label} + ) : ( + + {item.title} + + ) + )} + + + ); + }; + + return ( +
+ {buildDropdown()} + {buildMenu()} +
+ ); +} diff --git a/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarMenuDefault.tsx b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarMenuDefault.tsx new file mode 100755 index 0000000..5e70a92 --- /dev/null +++ b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarMenuDefault.tsx @@ -0,0 +1,183 @@ +'use client'; + +import { JSX, useMemo } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuConfig, MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; +import { createMenuPathMatcher } from '#shared/lib/menuPath'; +import { AccordionMenu, AccordionMenuClassNames, AccordionMenuGroup, AccordionMenuItem, AccordionMenuLabel, AccordionMenuSub, AccordionMenuSubContent, AccordionMenuSubTrigger } from '#shared/ui/AccordionMenu'; +import { Badge } from '#shared/ui/Badge'; + +export function SidebarMenuDefault() { + const { pathname } = useLocation(); + const fullMenuConfig = useMenuConfig(); + + // Memoize matchPath to prevent unnecessary re-renders + const matchPath = useMemo( + () => createMenuPathMatcher(fullMenuConfig, pathname), + [fullMenuConfig, pathname] + ); + + // Global classNames for consistent styling + const classNames: AccordionMenuClassNames = { + root: 'lg:ps-1 space-y-1', + group: 'gap-px', + label: 'uppercase text-xs font-medium text-muted-foreground/70 pt-2.25 pb-px', + separator: '', + item: 'h-8 hover:bg-background border-accent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-background data-[selected=true]:font-medium', + sub: '', + subTrigger: + 'h-8 hover:bg-transparent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-transparent data-[selected=true]:font-medium', + subContent: 'ps-3 py-0', + indicator: '' + }; + + const buildMenu = (items: MenuConfig): JSX.Element[] => { + return items.map((item: MenuItem, index: number) => { + if (item.heading) { + return buildMenuHeading(item, index); + } else if (item.disabled) { + return buildMenuItemRootDisabled(item, index); + } else { + return buildMenuItemRoot(item, index); + } + }); + }; + + const buildMenuItemRoot = (item: MenuItem, index: number): JSX.Element => { + if (item.children) { + return ( + + + {item.icon && } + {item.title} + + + {buildMenuItemChildren(item.children, 1)} + + + ); + } else { + return ( + + + {item.icon && } + {item.title} + + + ); + } + }; + + const buildMenuItemRootDisabled = (item: MenuItem, index: number): JSX.Element => { + return ( + + {item.icon && } + {item.title} + {item.disabled && ( + + Soon + + )} + + ); + }; + + const buildMenuItemChildren = (items: MenuConfig, level: number = 0): JSX.Element[] => { + return items.map((item: MenuItem, index: number) => { + if (item.disabled) { + return buildMenuItemChildDisabled(item, index, level); + } else { + return buildMenuItemChild(item, index, level); + } + }); + }; + + const buildMenuItemChild = (item: MenuItem, index: number, level: number = 0): JSX.Element => { + if (item.children) { + return ( + + + {item.collapse ? ( + + + {item.collapseTitle} + + {item.expandTitle} + + ) : ( + item.title + )} + + 0 ? '' : '') + )} + > + + {buildMenuItemChildren(item.children, item.collapse ? level : level + 1)} + + + + ); + } else { + return ( + + {item.title} + + ); + } + }; + + const buildMenuItemChildDisabled = ( + item: MenuItem, + index: number, + level: number = 0 + ): JSX.Element => { + return ( + + {item.title} + {item.disabled && ( + + Soon + + )} + + ); + }; + + const buildMenuHeading = (item: MenuItem, index: number): JSX.Element => { + return {item.heading}; + }; + + // Memoize the menu to prevent unnecessary re-renders + const { getChildren } = useMenu(pathname); + const menuItems = getChildren(fullMenuConfig, 0); + + return ( + + {buildMenu(menuItems || [])} + + ); +} diff --git a/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarPrimary.tsx b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarPrimary.tsx new file mode 100755 index 0000000..6e4e40e --- /dev/null +++ b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarPrimary.tsx @@ -0,0 +1,186 @@ +import { BarChart3, Bell, CheckSquare, Code, MessageSquare, Settings, Shield, ShoppingCart, UserCircle, Users } from 'lucide-react'; +import { useEffect, useRef, useState } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { useViewport } from '@crux-kit/hooks'; +import { cn, getHeight } from '@crux-kit/utils'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import { Button } from '#shared/ui/Button'; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '#shared/ui/Tooltip'; +// import { AppsDropdownMenu } from '#shared/partials/topbar/apps-dropdown-menu'; +// import { ChatSheet } from '#shared/partials/topbar/chat-sheet'; +import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu'; + +interface MenuItem { + icon: React.ComponentType<{ className?: string }>; + tooltip: string; + path: string; + rootPath?: string; +} + +const menuItems: MenuItem[] = [ + { icon: BarChart3, tooltip: 'Dashboard', path: '/', rootPath: '/' }, + { + icon: UserCircle, + tooltip: 'Profile', + path: '/public-profile/profiles/default', + rootPath: '/public-profile/' + }, + { + icon: Settings, + tooltip: 'Account', + path: '/account/home/get-started', + rootPath: '/account/' + }, + { + icon: Users, + tooltip: 'Network', + path: '/network/get-started', + rootPath: '/network/' + }, + { + icon: ShoppingCart, + tooltip: 'Store - Client', + path: '/store-client/home', + rootPath: '' + }, + { + icon: Shield, + tooltip: 'Authentication', + path: '/authentication/get-started', + rootPath: '/authentication/' + }, + { + icon: MessageSquare, + tooltip: 'Security Logs', + path: '/account/security/security-log', + rootPath: '/account/' + }, + { + icon: Bell, + tooltip: 'Notifications', + path: '/account/notifications', + rootPath: '' + }, + { + icon: CheckSquare, + tooltip: 'ACL', + path: '/account/members/roles', + rootPath: '' + }, + { icon: Code, tooltip: 'API Keys', path: '/account/api-keys', rootPath: '' } +]; + +export function SidebarPrimary() { + const headerRef = useRef(null); + const footerRef = useRef(null); + const [scrollableHeight, setScrollableHeight] = useState(0); + const [viewportHeight] = useViewport(); + const scrollableOffset = 80; + const { pathname } = useLocation(); + + useEffect(() => { + if (headerRef.current && footerRef.current) { + const headerHeight = getHeight(headerRef.current); + const footerHeight = getHeight(footerRef.current); + const availableHeight = viewportHeight - headerHeight - footerHeight - scrollableOffset; + setScrollableHeight(availableHeight); + } else { + setScrollableHeight(viewportHeight); + } + }, [viewportHeight]); + + const [selectedMenuItem, setSelectedMenuItem] = useState(menuItems[0]); + + useEffect(() => { + menuItems.forEach((item) => { + if (item.rootPath === pathname || (item.rootPath && pathname.includes(item.rootPath))) { + setSelectedMenuItem(item); + } + }); + }, [pathname]); + + return ( + +
+
+ + + + +
+ +
+
+ {menuItems.map((item, index) => ( + + + + + {item.tooltip} + + ))} +
+
+ +
+ {/* + + + } + /> + + + + } + /> */} + + } + /> +
+
+
+ ); +} diff --git a/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarSecondary.tsx b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarSecondary.tsx new file mode 100755 index 0000000..469a516 --- /dev/null +++ b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/SidebarSecondary.tsx @@ -0,0 +1,13 @@ +import { useLocation } from 'react-router'; +import { SidebarMenuDashboard } from './SidebarMenuDashboard'; +import { SidebarMenuDefault } from './SidebarMenuDefault'; + +export function SidebarSecondary() { + const { pathname } = useLocation(); + + return ( +
+ {pathname === '/' ? : } +
+ ); +} diff --git a/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Toolbar.tsx b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Toolbar.tsx new file mode 100755 index 0000000..196da5b --- /dev/null +++ b/apps/admin/src/app/layouts/04__TwoColumnSidebar/components/Toolbar.tsx @@ -0,0 +1,83 @@ +import { Fragment, ReactNode } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; +import { Container } from '#shared/widgets/common/Container'; + +export interface ToolbarHeadingProps { + title?: string | ReactNode; + description?: string | ReactNode; +} + +function Toolbar({ children }: { children?: ReactNode }) { + return ( +
+ + {children} + +
+ ); +} + +function ToolbarActions({ children }: { children?: ReactNode }) { + return
{children}
; +} + +function ToolbarBreadcrumbs() { + const { pathname } = useLocation(); + const menuConfig = useMenuConfig(); + const { getBreadcrumb, isActive } = useMenu(pathname); + const items: MenuItem[] = getBreadcrumb(menuConfig); + + if (items.length === 0) { + return null; + } + + return ( +
+ {items.map((item, index) => { + const isLast = index === items.length - 1; + const active = item.path ? isActive(item.path) : false; + + return ( + + {item.path ? ( + + {item.title} + + ) : ( + + {item.title} + + )} + {!isLast && /} + + ); + })} +
+ ); +} + +const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => { + const { pathname } = useLocation(); + const { getCurrentItem } = useMenu(pathname); + const menuConfig = useMenuConfig(); + const item = getCurrentItem(menuConfig); + + return ( +
+

{title || item?.title}

+ +
+ ); +}; + +export { Toolbar, ToolbarActions, ToolbarBreadcrumbs, ToolbarHeading }; diff --git a/apps/admin/src/app/layouts/04__TwoColumnSidebar/layout.tsx b/apps/admin/src/app/layouts/04__TwoColumnSidebar/layout.tsx new file mode 100755 index 0000000..4d34533 --- /dev/null +++ b/apps/admin/src/app/layouts/04__TwoColumnSidebar/layout.tsx @@ -0,0 +1,94 @@ +// DEMO 4 +// https://keenthemes.com/metronic/tailwind/react/demo4 + +import { Download } from 'lucide-react'; +import { useEffect } from 'react'; +import { Link, Outlet } from 'react-router-dom'; +import { useBodyClass, useIsMobile } from '@crux-kit/hooks'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { Button } from '#shared/ui/Button'; +// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog'; +// import { NotificationsSheet } from '#shared/partials/topbar/notifications-sheet'; +import { Footer } from './components/Footer'; +import { Header } from './components/Header'; +import { Sidebar } from './components/Sidebar'; +import { Toolbar, ToolbarActions, ToolbarHeading } from './components/Toolbar'; + +export function TwoColumnSidebarLayout() { + const { setOption } = useSettings(); + const isMobileMode = useIsMobile(); + + // Using the custom hook to set multiple CSS variables and class properties + useBodyClass(` + [--header-height:60px] + [--sidebar-width:290px] + lg:overflow-hidden + bg-muted! + `); + + useEffect(() => { + setOption('layout', LayoutNames.TWO_COLUMN_SIDEBAR); + }, [setOption]); + + return ( + <> +
+ {isMobileMode &&
} + +
+ {!isMobileMode && } + +
+
+
+ + + + + {/* + + + } + /> + + + + } + /> */} + + + + + +
+ +
+
+
+
+
+ + ); +} diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/Footer.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Footer.tsx new file mode 100755 index 0000000..39d24e5 --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Footer.tsx @@ -0,0 +1,42 @@ +import { generalSettings } from '#app/config/general'; +import { Container } from '#shared/widgets/common/Container'; + +export function Footer() { + const currentYear = new Date().getFullYear(); + + return ( + + ); +} diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/Header.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Header.tsx new file mode 100755 index 0000000..de86bd0 --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Header.tsx @@ -0,0 +1,45 @@ +import { useEffect, useState } from 'react'; +import { useScrollPosition } from '@crux-kit/hooks'; +import { cn } from '@crux-kit/utils'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { Container } from '#shared/widgets/common/Container'; +import { HeaderLogo } from './HeaderLogo'; +import { HeaderTopbar } from './HeaderTopbar'; + +const Header = () => { + const { settings } = useSettings(); + const scrollPosition = useScrollPosition(); + const [headerStickyOn, setHeaderStickyOn] = useState(false); + + useEffect(() => { + const isSticky = + scrollPosition > settings.layouts[LayoutNames.HORIZONTAL_MENU].headerStickyOffset; + setHeaderStickyOn(isSticky); + }, [scrollPosition, settings]); + + useEffect(() => { + if (headerStickyOn === true) { + document.body.setAttribute('data-sticky-header', 'on'); + } else { + document.body.removeAttribute('data-sticky-header'); + } + }, [headerStickyOn]); + + return ( +
+ + + + +
+ ); +}; + +export { Header }; diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/HeaderLogo.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/HeaderLogo.tsx new file mode 100755 index 0000000..b4ad080 --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/HeaderLogo.tsx @@ -0,0 +1,201 @@ +import { ChevronDown, Menu, Settings, Shield, UserCircle, Users, type LucideIcon } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { useIsMobile } from '@crux-kit/hooks'; +import { cn } from '@crux-kit/utils'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import { Button } from '#shared/ui/Button'; +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '#shared/ui/DropdownMenu'; +import { Sheet, SheetBody, SheetContent, SheetHeader, SheetTrigger } from '#shared/ui/Sheet'; +import { SidebarMenuDashboard } from './SidebarMenuDashboard'; +import { SidebarMenuDefault } from './SidebarMenuDefault'; + +interface HeaderLogoTeam { + title: string; + icon?: LucideIcon; + urlPartial: string; + path: string; +} +type HeaderLogoTeams = Array; + +interface HeaderLogoItem { + title: string; + icon?: LucideIcon; +} +type HeaderLogoItems = Array; + +interface HeaderLogoStaging { + title: string; + icon?: LucideIcon; +} +type HeaderLogoStagings = Array; + +export function HeaderLogo() { + const { pathname } = useLocation(); + const [isSheetOpen, setIsSheetOpen] = useState(false); + const isMobile = useIsMobile(); + + const teams: HeaderLogoTeams = [ + { + title: 'MetronicTeam', + icon: UserCircle, + urlPartial: '/public-profile/', + path: '/public-profile/profiles/default' + }, + { + title: 'KeenTeam', + icon: Settings, + urlPartial: '/account/', + path: '/' + } + ]; + + const items: HeaderLogoItems = [ + { + title: 'Campaign', + icon: UserCircle + }, + { + title: 'Fall Winter 2024 ', + icon: Settings + }, + { + title: 'Barberry Autmn 24', + icon: Users + }, + { + title: 'PF24 Advertising', + icon: Shield + } + ]; + + const stagings: HeaderLogoStagings = [ + { + title: 'Staging', + icon: UserCircle + }, + { + title: 'Account', + icon: Settings + } + ]; + + const [selectedTeam, setSelectedTeam] = useState(teams[0]); + const [selectedItem, setSelectedItem] = useState(items[0]); + const [selectedStaging, setSelectedStaging] = useState(stagings[0]); + + // Close sheet when route changes + useEffect(() => { + setIsSheetOpen(false); + }, [pathname]); + + return ( +
+ + logo + logo + + + {isMobile && ( + + + + + + + + {pathname === '/' ? : } + + + + )} + + {!isMobile && ( +
+ {/* Teams Dropdown */} + + + {selectedTeam.title} + + + + {teams.map((team, index) => ( + setSelectedTeam(team)} + > + + {team.icon && } + {team.title} + + + ))} + + + + / + + {/* Items Dropdown */} + + + {selectedItem.title} + + + + {items.map((item, index) => ( + setSelectedItem(item)} + > + + {item.icon && } + {item.title} + + + ))} + + + + / + + {/* Staging Dropdown */} + + + {selectedStaging.title} + + + + {stagings.map((staging, index) => ( + setSelectedStaging(staging)} + > + + {staging.icon && } + {staging.title} + + + ))} + + +
+ )} +
+ ); +} diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/HeaderTopbar.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/HeaderTopbar.tsx new file mode 100755 index 0000000..52e22c2 --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/HeaderTopbar.tsx @@ -0,0 +1,83 @@ +import { Users } from 'lucide-react'; +import { Link } from 'react-router-dom'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import { Button } from '#shared/ui/Button'; +// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog'; +// import { AppsDropdownMenu } from '#shared/partials/topbar/apps-dropdown-menu'; +// import { ChatSheet } from '#shared/partials/topbar/chat-sheet'; +// import { NotificationsSheet } from '#shared/partials/topbar/notifications-sheet'; +import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu'; + +export function HeaderTopbar() { + return ( +
+ + +
+ {/* + + + } + /> */} + {/* + + + } + /> */} + {/* + + + } + /> */} + {/* + + + } + /> */} +
+ + + } + /> +
+ ); +} diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/Navbar.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Navbar.tsx new file mode 100755 index 0000000..c5173b0 --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Navbar.tsx @@ -0,0 +1,14 @@ +import { Container } from '#shared/widgets/common/Container'; +import { NavbarMenu } from './NavbarMenu'; + +const Navbar = () => { + return ( +
+ + + +
+ ); +}; + +export { Navbar }; diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/NavbarMenu.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/NavbarMenu.tsx new file mode 100755 index 0000000..ed2f7da --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/NavbarMenu.tsx @@ -0,0 +1,74 @@ +import { useEffect, useMemo, useState } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; + +export function NavbarMenu() { + const { pathname } = useLocation(); + + const items = useMemo( + () => [ + { + title: 'Dashboards', + path: '/', + partial: '/' + }, + { + title: 'Public Profiles', + path: '/public-profile/profiles/default', + partial: '/public-profile' + }, + { + title: 'Account Settings', + path: '/account/home/get-started', + partial: '/account' + }, + { + title: 'Network', + path: '/network/get-started', + partial: '/network' + }, + { + title: 'Store - Client', + path: '/store-client/home', + partial: '/store-client' + }, + { + title: 'Authentication', + path: '/authentication/get-started', + partial: '/authentication' + } + ], + [] // Empty dependency array since the data is static + ); + + const [selectedItem, setSelectedItem] = useState(items[0]); + + useEffect(() => { + items.forEach((item) => { + if (item.partial !== '' && pathname.startsWith(item.partial)) { + setSelectedItem(item); + } + }); + }, [items, pathname]); + + return ( +
+
+
+ {items.map((item, index) => ( + + {item.title} + + ))} +
+
+
+ ); +} diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/Sidebar.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Sidebar.tsx new file mode 100755 index 0000000..845f6fb --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Sidebar.tsx @@ -0,0 +1,13 @@ +import { useLocation } from 'react-router-dom'; +import { SidebarMenuDashboard } from './SidebarMenuDashboard'; +import { SidebarMenuDefault } from './SidebarMenuDefault'; + +export function Sidebar() { + const { pathname } = useLocation(); + + return ( +
+ {pathname === '/' ? : } +
+ ); +} diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/SidebarMenuDashboard.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/SidebarMenuDashboard.tsx new file mode 100755 index 0000000..58e44f3 --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/SidebarMenuDashboard.tsx @@ -0,0 +1,171 @@ +import { Badge, ChevronDown, FileText, LucideIcon, Settings, SquareCode, UserCircle } from 'lucide-react'; +import { useCallback, useMemo } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { AccordionMenu, AccordionMenuClassNames, AccordionMenuGroup, AccordionMenuItem, AccordionMenuLabel } from '#shared/ui/AccordionMenu'; +import { Button } from '#shared/ui/Button'; +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '#shared/ui/DropdownMenu'; + +interface DropdownItem { + title: string; + path: string; + icon: LucideIcon; + active?: boolean; +} + +interface MenuItem { + title: string; + path?: string; + active?: boolean; +} + +interface MenuLabel { + label: string; +} + +type MenuNode = MenuItem | MenuLabel; + +export function SidebarMenuDashboard() { + const { pathname } = useLocation(); + + const dropdownItems = useMemo( + () => [ + { + title: 'Client API', + path: '/account/home/user-profile', + icon: SquareCode, + active: true + }, + { + title: 'Profile', + path: '/public-profile/profiles/company', + icon: UserCircle + }, + { + title: 'My Account', + path: '/account/integrations', + icon: Settings + }, + { + title: 'Projects', + path: '/public-profile/projects/3-columns', + icon: FileText + }, + { + title: 'Personal info', + path: '/public-profile/profiles/creator', + icon: Badge + } + ], + [] + ); + + const currentDropdownItem = dropdownItems[0]; + + const menuItems = useMemo( + () => [ + { label: 'Configuration' }, + { title: 'API Setup', path: '/account/api-keys' }, + { title: 'Team Settings', path: '/account/home/settings-sidebar' }, + { title: 'Authentication', path: '/authentication/classic/sign-in' }, + { title: 'Endpoints Configs', path: '/account/appearance' }, + { title: 'Rate Limiting', path: '/public-profile/network' }, + { label: 'Security' }, + { title: 'Data Encryption', path: '/account/billing/enterprise' }, + { title: 'Text', path: '/account/security/overview' }, + { title: 'Access Control', path: '/account/security/privacy-settings' }, + { label: 'Analytics' }, + { + title: 'Incident Response', + path: '/account/security/current-sessions' + }, + { title: 'Fetching Data', path: '/account/members/team-info' }, + { title: 'Custom Reports', path: '/account/home/user-profile' }, + { + title: 'Real Time Analytics', + path: '/account/home/settings-enterprise' + }, + { title: 'Exporting Data', path: '/account/members/import-members' }, + { title: 'Dashboard Integration', path: '/account/members/team-info' } + ], + [] // Empty dependency array since the data is static + ); + + const classNames: AccordionMenuClassNames = { + root: 'space-y-1', + label: 'uppercase text-xs font-medium text-muted-foreground/80 pt-6 mb-2 pb-0', + item: 'h-8 hover:bg-background border-accent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-background data-[selected=true]:font-medium' + }; + + const matchPath = useCallback( + (path: string): boolean => path === pathname || (path.length > 1 && pathname.startsWith(path)), + [pathname] + ); + + const buildDropdown = () => { + return ( + + + + + + {dropdownItems.map((item, index) => ( + + + + {item.title} + + + ))} + + + ); + }; + + const memoizedMenu = useMemo( + () => ( + + {menuItems.map((item, index) => + 'label' in item ? ( + {item.label} + ) : ( + + {item.title} + + ) + )} + + ), + [menuItems] + ); + + const buildMenu = () => { + return ( + + {memoizedMenu} + + ); + }; + + return ( +
+ {buildDropdown()} + {buildMenu()} +
+ ); +} diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/SidebarMenuDefault.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/SidebarMenuDefault.tsx new file mode 100755 index 0000000..fd9031a --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/SidebarMenuDefault.tsx @@ -0,0 +1,181 @@ +import { JSX, useMemo } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuConfig, MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; +import { createMenuPathMatcher } from '#shared/lib/menuPath'; +import { AccordionMenu, AccordionMenuClassNames, AccordionMenuGroup, AccordionMenuItem, AccordionMenuLabel, AccordionMenuSub, AccordionMenuSubContent, AccordionMenuSubTrigger } from '#shared/ui/AccordionMenu'; +import { Badge } from '#shared/ui/Badge'; + +export function SidebarMenuDefault() { + const { pathname } = useLocation(); + const menuConfig = useMenuConfig(); + + // Memoize matchPath to prevent unnecessary re-renders + const matchPath = useMemo( + () => createMenuPathMatcher(menuConfig, pathname), + [menuConfig, pathname] + ); + + // Global classNames for consistent styling + const classNames: AccordionMenuClassNames = { + root: 'lg:ps-1 space-y-1', + group: 'gap-px', + label: 'uppercase text-xs font-medium text-muted-foreground/70 pt-2.25 pb-px', + separator: '', + item: 'border border-transparent h-9 hover:bg-background text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-background data-[selected=true]:font-medium data-[selected=true]:border-border', + sub: '', + subTrigger: + 'h-8 hover:bg-transparent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-transparent data-[selected=true]:font-medium', + subContent: 'ps-3 py-0', + indicator: '' + }; + + const buildMenu = (items: MenuConfig): JSX.Element[] => { + return items.map((item: MenuItem, index: number) => { + if (item.heading) { + return buildMenuHeading(item, index); + } else if (item.disabled) { + return buildMenuItemRootDisabled(item, index); + } else { + return buildMenuItemRoot(item, index); + } + }); + }; + + const buildMenuItemRoot = (item: MenuItem, index: number): JSX.Element => { + if (item.children) { + return ( + + + {item.icon && } + {item.title} + + + {buildMenuItemChildren(item.children, 1)} + + + ); + } else { + return ( + + + {item.icon && } + {item.title} + + + ); + } + }; + + const buildMenuItemRootDisabled = (item: MenuItem, index: number): JSX.Element => { + return ( + + {item.icon && } + {item.title} + {item.disabled && ( + + Soon + + )} + + ); + }; + + const buildMenuItemChildren = (items: MenuConfig, level: number = 0): JSX.Element[] => { + return items.map((item: MenuItem, index: number) => { + if (item.disabled) { + return buildMenuItemChildDisabled(item, index, level); + } else { + return buildMenuItemChild(item, index, level); + } + }); + }; + + const buildMenuItemChild = (item: MenuItem, index: number, level: number = 0): JSX.Element => { + if (item.children) { + return ( + + + {item.collapse ? ( + + + {item.collapseTitle} + + {item.expandTitle} + + ) : ( + item.title + )} + + 0 ? '' : '') + )} + > + + {buildMenuItemChildren(item.children, item.collapse ? level : level + 1)} + + + + ); + } else { + return ( + + {item.title} + + ); + } + }; + + const buildMenuItemChildDisabled = ( + item: MenuItem, + index: number, + level: number = 0 + ): JSX.Element => { + return ( + + {item.title} + {item.disabled && ( + + Soon + + )} + + ); + }; + + const buildMenuHeading = (item: MenuItem, index: number): JSX.Element => { + return {item.heading}; + }; + + // Memoize the menu to prevent unnecessary re-renders + const { getChildren } = useMenu(pathname); + const menuItems = getChildren(menuConfig, 0); + + return ( + + {buildMenu(menuItems || [])} + + ); +} diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/components/Toolbar.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Toolbar.tsx new file mode 100755 index 0000000..9a81bb6 --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/components/Toolbar.tsx @@ -0,0 +1,83 @@ +import { Fragment, ReactNode } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; +import { Container } from '#shared/widgets/common/Container'; + +export interface ToolbarHeadingProps { + title?: string | ReactNode; + description?: string | ReactNode; +} + +function Toolbar({ children }: { children?: ReactNode }) { + return ( +
+ + {children} + +
+ ); +} + +function ToolbarActions({ children }: { children?: ReactNode }) { + return
{children}
; +} + +function ToolbarBreadcrumbs() { + const menuConfig = useMenuConfig(); + const { pathname } = useLocation(); + const { getBreadcrumb, isActive } = useMenu(pathname); + const items: MenuItem[] = getBreadcrumb(menuConfig); + + if (items.length === 0) { + return null; + } + + return ( +
+ {items.map((item, index) => { + const isLast = index === items.length - 1; + const active = item.path ? isActive(item.path) : false; + + return ( + + {item.path ? ( + + {item.title} + + ) : ( + + {item.title} + + )} + {!isLast && /} + + ); + })} +
+ ); +} + +const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => { + const { pathname } = useLocation(); + const { getCurrentItem } = useMenu(pathname); + const menuConfig = useMenuConfig(); + const item = getCurrentItem(menuConfig); + + return ( +
+

{title || item?.title}

+ +
+ ); +}; + +export { Toolbar, ToolbarActions, ToolbarBreadcrumbs, ToolbarHeading }; diff --git a/apps/admin/src/app/layouts/05__DualRowsHeader/layout.tsx b/apps/admin/src/app/layouts/05__DualRowsHeader/layout.tsx new file mode 100755 index 0000000..ae7a60d --- /dev/null +++ b/apps/admin/src/app/layouts/05__DualRowsHeader/layout.tsx @@ -0,0 +1,96 @@ +// DEMO 5 +// https://keenthemes.com/metronic/tailwind/react/demo5 + +import { addDays, format } from 'date-fns'; +import { CalendarDays } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { DateRange } from 'react-day-picker'; +import { Outlet, useLocation } from 'react-router'; +import { useBodyClass, useIsMobile } from '@crux-kit/hooks'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { Button } from '#shared/ui/Button'; +import { Calendar } from '#shared/ui/Calendar'; +import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover'; +import { Footer } from './components/Footer'; +import { Header } from './components/Header'; +import { Navbar } from './components/Navbar'; +import { Sidebar } from './components/Sidebar'; +import { Toolbar, ToolbarActions, ToolbarHeading } from './components/Toolbar'; + +export const DualRowsHeaderLayout = () => { + const isMobile = useIsMobile(); + const { pathname } = useLocation(); + const { setOption } = useSettings(); + + const [date, setDate] = useState({ + from: new Date(2025, 0, 20), + to: addDays(new Date(2025, 0, 20), 20) + }); + + // Using the custom hook to set multiple CSS variables and class properties + useBodyClass(` + [--header-height:54px] + [--sidebar-width:200px] + `); + + useEffect(() => { + setOption('layout', LayoutNames.DUAL_ROW_HEADER); + setOption('container', 'fluid'); + }, [setOption]); + + return ( + <> +
+
+ + + +
+ {!isMobile && } + +
+ {!pathname.includes('/public-profile/') && ( + + + + + + + + + + + + + + )} + + + +
+
+
+
+ + ); +}; diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/components/Footer.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/components/Footer.tsx new file mode 100755 index 0000000..c10dae4 --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/components/Footer.tsx @@ -0,0 +1,48 @@ +import { APP_VERSION } from '#app/config/app'; +import { Dialog, DialogBody, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '#shared/ui/Dialog'; +import { Container } from '#shared/widgets/common/Container'; + +const currentYear = new Date().getFullYear(); + +export function Footer() { + return ( +
+ +
+ + + + + + + Very nice + + + + + + + + + +
+
+
+ ); +} diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/components/Header.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/components/Header.tsx new file mode 100755 index 0000000..d049bfa --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/components/Header.tsx @@ -0,0 +1,60 @@ +import { Menu } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { useIsMobile } from '@crux-kit/hooks'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import { Button } from '#shared/ui/Button'; +import { Sheet, SheetBody, SheetContent, SheetHeader, SheetTrigger } from '#shared/ui/Sheet'; +import { Container } from '#shared/widgets/common/Container'; +import { SidebarFooter } from './SidebarFooter'; +import { SidebarHeader } from './SidebarHeader'; +import { SidebarMenu } from './SidebarMenu'; + +const Header = () => { + const { pathname } = useLocation(); + const [isSheetOpen, setIsSheetOpen] = useState(false); + const isMobile = useIsMobile(); + + useEffect(() => { + setIsSheetOpen(false); + }, [pathname]); + + return ( +
+ + + Logo + Logo + + + {isMobile && ( + + + + + + + + + + + + + + )} + +
+ ); +}; + +export { Header }; diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/components/RoosterPeek.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/components/RoosterPeek.tsx new file mode 100644 index 0000000..3cdda5f --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/components/RoosterPeek.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { IS_PROD_MODE } from '#app/config/app'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; + +const PEEK_INTERVAL_MS = 120_000; + +type Side = 'bottom' | 'top' | 'bottom-left' | 'bottom-right'; +const SIDES: Side[] = ['bottom', 'top', 'bottom-left', 'bottom-right']; + +const ROTATION: Record = { + 'bottom': 0, + 'top': 180, + 'bottom-left': 45, + 'bottom-right': -45 +}; + +function buildKeyframes(side: Side): string { + if (side === 'bottom-left') { + return `@keyframes rooster-peek { + 0% { left: -200px; bottom: -200px; } + 40% { left: 20px; bottom: 20px; } + 70% { left: 20px; bottom: 20px; } + 100% { left: -200px; bottom: -200px; } + }`; + } + if (side === 'bottom-right') { + return `@keyframes rooster-peek { + 0% { right: -200px; bottom: -200px; } + 40% { right: 20px; bottom: 20px; } + 70% { right: 20px; bottom: 20px; } + 100% { right: -200px; bottom: -200px; } + }`; + } + const prop = side; + return `@keyframes rooster-peek { + 0% { ${prop}: -200px; } + 40% { ${prop}: 20px; } + 70% { ${prop}: 20px; } + 100% { ${prop}: -200px; } + }`; +} + +// prettier-ignore +function buildStyle(side: Side): React.CSSProperties { + const rotation = `rotate(${ROTATION[side]}deg)`; + const base: React.CSSProperties = { + animation: 'rooster-peek 4s ease-in-out 1 forwards', + transform: rotation, + }; + + if (side === 'bottom') return { ...base, bottom: '-200px', left: '20px' }; + if (side === 'top') return { ...base, top: '-200px', left: '20px' }; + if (side === 'bottom-left') return { ...base, left: '-200px', bottom: '-200px' }; + return { ...base, right: '-200px', bottom: '-200px' }; +} + +function randomSide(): Side { + return SIDES[Math.floor(Math.random() * SIDES.length)]; +} + +export const RoosterPeek: React.FC = () => { + const [{ tick, side }, setState] = React.useState(() => ({ tick: 0, side: randomSide() })); + + React.useEffect(() => { + if (IS_PROD_MODE) return; + + const id = setInterval( + () => setState((s) => ({ tick: s.tick + 1, side: randomSide() })), + PEEK_INTERVAL_MS + ); + + return () => clearInterval(id); + }, []); + + if (IS_PROD_MODE) return null; + + return ( + + + Brutal rooster + + ); +}; diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/components/Sidebar.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/components/Sidebar.tsx new file mode 100755 index 0000000..a660f32 --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/components/Sidebar.tsx @@ -0,0 +1,13 @@ +import { SidebarFooter } from './SidebarFooter'; +import { SidebarHeader } from './SidebarHeader'; +import { SidebarMenu } from './SidebarMenu'; + +export function Sidebar() { + return ( +
+ + + +
+ ); +} diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarFooter.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarFooter.tsx new file mode 100755 index 0000000..899cb07 --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarFooter.tsx @@ -0,0 +1,24 @@ +import useIntlName from '#app/i18n/useIntlName'; +import { useAuth } from '#core/Auth/providers/AuthProvider'; +import { Avatar, AvatarFallback, AvatarImage } from '#shared/ui/Avatar'; +import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu'; + +export function SidebarFooter() { + const { user } = useAuth(); + const formatName = useIntlName(); + + return ( +
+ {user && ( + + + {formatName(user, 'INITIALS_LF')} + + } + /> + )} +
+ ); +} diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarHeader.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarHeader.tsx new file mode 100755 index 0000000..d83a759 --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarHeader.tsx @@ -0,0 +1,45 @@ +import { Search } from 'lucide-react'; +import { Link } from 'react-router-dom'; +import { toAbsoluteUrl } from '#shared/lib/helpers'; +import { Input } from '#shared/ui/Input'; + +export function SidebarHeader() { + const handleInputChange = () => {}; + + return ( +
+
+ + + + +
+ C R U X Goat +
+
+ +
+
+ + + + cmd + / + +
+
+
+ ); +} diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarMenu.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarMenu.tsx new file mode 100755 index 0000000..fff5c3d --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarMenu.tsx @@ -0,0 +1,9 @@ +import { SidebarMenuPrimary } from './SidebarMenuPrimary'; + +export function SidebarMenu() { + return ( +
+ +
+ ); +} diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarMenuPrimary.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarMenuPrimary.tsx new file mode 100755 index 0000000..e2a1499 --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/components/SidebarMenuPrimary.tsx @@ -0,0 +1,142 @@ +'use client'; + +import { Fragment, JSX, useMemo } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuConfig, MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useAuth } from '#core/Auth/providers/AuthProvider'; +import { createMenuPathMatcher } from '#shared/lib/menuPath'; +import { AccordionMenu, AccordionMenuClassNames, AccordionMenuGroup, AccordionMenuItem, AccordionMenuSub, AccordionMenuSubContent, AccordionMenuSubTrigger } from '#shared/ui/AccordionMenu'; +import { getPermittedMenuItems } from '../lib'; + +export function SidebarMenuPrimary() { + const { pathname } = useLocation(); + const { user } = useAuth(); + const menuConfig = useMenuConfig(); + + const userPermissions = user?.permissions ?? []; + + const matchPath = useMemo( + () => createMenuPathMatcher(menuConfig, pathname), + [menuConfig, pathname] + ); + + const classNames: AccordionMenuClassNames = { + root: 'space-y-2.5 px-3.5', + group: 'gap-px', + label: 'uppercase text-xs font-medium text-muted-foreground/70 pt-2.25 pb-px', + separator: '', + item: 'h-9 hover:bg-transparent border border-transparent text-accent-foreground hover:text-mono data-[selected=true]:text-mono data-[selected=true]:bg-background data-[selected=true]:border-border data-[selected=true]:font-medium', + sub: '', + subTrigger: + 'h-9 hover:bg-transparent border border-transparent text-accent-foreground hover:text-mono data-[selected=true]:text-mono data-[selected=true]:bg-background data-[selected=true]:border-border data-[selected=true]:font-medium', + subContent: 'py-0', + indicator: '' + }; + + const buildMenu = (items: MenuConfig): JSX.Element[] => { + const menuItems = getPermittedMenuItems(items, userPermissions); + + return menuItems.map((item: MenuItem, index: number) => { + if (!item.heading && !item.disabled) { + return buildMenuItemRoot(item, index); + } else { + return <>; + } + }); + }; + + const buildMenuItemRoot = (item: MenuItem, index: number): JSX.Element => { + if (item.children) { + return ( + + + {item.icon && } + {item.title} + + + {buildMenuItemChildren(item.children, 1)} + + + ); + } else { + return ( + + + {item.icon && } + {item.title} + + + ); + } + }; + + const buildMenuItemChildren = (items: MenuConfig, level: number = 0): JSX.Element[] => { + return items.map((item: MenuItem, index: number) => { + if (!item.heading && !item.disabled) { + return buildMenuItemChild(item, index, level); + } else { + return ; + } + }); + }; + + const buildMenuItemChild = (item: MenuItem, index: number, level: number = 0): JSX.Element => { + if (item.children) { + return ( + + + {item.collapse ? ( + + + {item.collapseTitle} + + {item.expandTitle} + + ) : ( + item.title + )} + + 0 ? '' : '') + )} + > + + {buildMenuItemChildren(item.children, item.collapse ? level : level + 1)} + + + + ); + } else { + return ( + + {item.title} + + ); + } + }; + + return ( + + {buildMenu(menuConfig)} + + ); +} diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/components/Toolbar.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/components/Toolbar.tsx new file mode 100755 index 0000000..57cffc4 --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/components/Toolbar.tsx @@ -0,0 +1,104 @@ +import { HomeIcon } from 'lucide-react'; +import { Fragment, ReactNode } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import { cn } from '@crux-kit/utils'; +import { MenuItem } from '#app/config/types'; +import { useMenuConfig } from '#app/menu'; +import { useMenu } from '#shared/hooks/useMenu'; +import { Container } from '#shared/widgets/common/Container'; + +export interface ToolbarHeadingProps { + title?: string | ReactNode; + description?: string | ReactNode; +} + +function Toolbar({ children }: { children?: ReactNode }) { + return ( +
+ + {children} + +
+ ); +} + +function ToolbarActions({ children }: { children?: ReactNode }) { + return
{children}
; +} + +function ToolbarBreadcrumbs({ homeVisible = true }: { homeVisible?: boolean }) { + const menuConfig = useMenuConfig(); + + const dashboard = menuConfig[0]; + + const { pathname } = useLocation(); + const { getBreadcrumb, isActive } = useMenu(pathname); + const items: MenuItem[] = getBreadcrumb(menuConfig); + + if (items.length === 0) { + return null; + } + + return ( +
+ {homeVisible && ( + <> + + + + / + + )} + + {items.map((item, index) => { + const isLast = index === items.length - 1; + const active = item.path ? isActive(item.path) : false; + + return ( + + {item.path ? ( + + {item.title} + + ) : ( + + {item.title} + + )} + {!isLast && /} + + ); + })} +
+ ); +} + +const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => { + const { pathname } = useLocation(); + const { getCurrentItem } = useMenu(pathname); + const menuConfig = useMenuConfig(); + const item = getCurrentItem(menuConfig); + + return ( +
+

{title || item?.title}

+ +
+ ); +}; + +export { Toolbar, ToolbarActions, ToolbarBreadcrumbs, ToolbarHeading }; diff --git a/apps/admin/src/app/layouts/06__MultipleMenus/layout.tsx b/apps/admin/src/app/layouts/06__MultipleMenus/layout.tsx new file mode 100755 index 0000000..79c2d7f --- /dev/null +++ b/apps/admin/src/app/layouts/06__MultipleMenus/layout.tsx @@ -0,0 +1,69 @@ +// DEMO 6 +// https://keenthemes.com/metronic/tailwind/react/demo6 + +import { Fragment, useEffect, useMemo } from 'react'; +import { Outlet, useLocation } from 'react-router-dom'; +import { useBodyClass, useIsMobile } from '@crux-kit/hooks'; +import { LayoutNames } from '#app/config/types'; +import { useSettings } from '#app/providers/SettingsProvider'; +import { Footer } from './components/Footer'; +import { Header } from './components/Header'; +import { Sidebar } from './components/Sidebar'; +import { Toolbar, ToolbarHeading } from './components/Toolbar'; + +export const MultipleMenusLayout = () => { + const isMobile = useIsMobile(); + const { setOption } = useSettings(); + const { pathname } = useLocation(); + + useBodyClass(` + [--header-height:60px] + [--sidebar-width:270px] + lg:overflow-hidden + bg-muted! + `); + + useEffect(() => { + setOption('layout', LayoutNames.MULTIPLE_MENUS); + }, [setOption]); + + const toolbar = useMemo(() => { + if (pathname.includes('/devtools')) return null; + if (pathname.includes('/access-control')) return null; + if (pathname.includes('/file-manager')) return null; + if (pathname.includes('/web-studio')) return null; + + return ( + + + + ); + }, [pathname]); + + const footer = useMemo(() => { + if (pathname.includes('/file-manager')) return null; + return