@stacksjs/defaults 0.70.207 → 0.70.208
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/TODO.md +21 -0
- package/ai/AGENTS.md +79 -0
- package/ai/README.md +45 -0
- package/ai/claude/launch.json +12 -0
- package/ai/skills/stacks-actions/SKILL.md +128 -0
- package/ai/skills/stacks-ai/SKILL.md +276 -0
- package/ai/skills/stacks-alias/SKILL.md +94 -0
- package/ai/skills/stacks-analytics/SKILL.md +91 -0
- package/ai/skills/stacks-api/SKILL.md +738 -0
- package/ai/skills/stacks-arrays/SKILL.md +277 -0
- package/ai/skills/stacks-auth/SKILL.md +422 -0
- package/ai/skills/stacks-auto-imports/SKILL.md +138 -0
- package/ai/skills/stacks-brandkit/SKILL.md +811 -0
- package/ai/skills/stacks-browse/SKILL.md +127 -0
- package/ai/skills/stacks-browse/scripts/browse.ts +492 -0
- package/ai/skills/stacks-browser/SKILL.md +145 -0
- package/ai/skills/stacks-buddy/SKILL.md +676 -0
- package/ai/skills/stacks-build/SKILL.md +163 -0
- package/ai/skills/stacks-cache/SKILL.md +125 -0
- package/ai/skills/stacks-calendar/SKILL.md +113 -0
- package/ai/skills/stacks-chat/SKILL.md +371 -0
- package/ai/skills/stacks-cli/SKILL.md +112 -0
- package/ai/skills/stacks-cloud/SKILL.md +192 -0
- package/ai/skills/stacks-cms/SKILL.md +217 -0
- package/ai/skills/stacks-collections/SKILL.md +82 -0
- package/ai/skills/stacks-commerce/SKILL.md +114 -0
- package/ai/skills/stacks-composables/SKILL.md +161 -0
- package/ai/skills/stacks-config/SKILL.md +144 -0
- package/ai/skills/stacks-configuration/SKILL.md +154 -0
- package/ai/skills/stacks-cron/SKILL.md +123 -0
- package/ai/skills/stacks-crosswind/SKILL.md +190 -0
- package/ai/skills/stacks-dashboard/SKILL.md +173 -0
- package/ai/skills/stacks-database/SKILL.md +286 -0
- package/ai/skills/stacks-datetime/SKILL.md +269 -0
- package/ai/skills/stacks-dependencies/SKILL.md +111 -0
- package/ai/skills/stacks-deploy/SKILL.md +102 -0
- package/ai/skills/stacks-design-brutalist/SKILL.md +110 -0
- package/ai/skills/stacks-design-minimalist/SKILL.md +115 -0
- package/ai/skills/stacks-design-output/SKILL.md +55 -0
- package/ai/skills/stacks-design-soft/SKILL.md +156 -0
- package/ai/skills/stacks-design-taste/SKILL.md +1012 -0
- package/ai/skills/stacks-design-taste-codex/SKILL.md +294 -0
- package/ai/skills/stacks-desktop/SKILL.md +78 -0
- package/ai/skills/stacks-development/SKILL.md +298 -0
- package/ai/skills/stacks-dns/SKILL.md +149 -0
- package/ai/skills/stacks-docs/SKILL.md +109 -0
- package/ai/skills/stacks-email/SKILL.md +236 -0
- package/ai/skills/stacks-enums/SKILL.md +100 -0
- package/ai/skills/stacks-env/SKILL.md +181 -0
- package/ai/skills/stacks-error-handling/SKILL.md +137 -0
- package/ai/skills/stacks-events/SKILL.md +228 -0
- package/ai/skills/stacks-faker/SKILL.md +158 -0
- package/ai/skills/stacks-git/SKILL.md +158 -0
- package/ai/skills/stacks-guard/SKILL.md +98 -0
- package/ai/skills/stacks-health/SKILL.md +75 -0
- package/ai/skills/stacks-http/SKILL.md +316 -0
- package/ai/skills/stacks-i18n/SKILL.md +198 -0
- package/ai/skills/stacks-image-to-code/SKILL.md +629 -0
- package/ai/skills/stacks-imagegen-mobile/SKILL.md +1474 -0
- package/ai/skills/stacks-imagegen-web/SKILL.md +998 -0
- package/ai/skills/stacks-investigate/SKILL.md +119 -0
- package/ai/skills/stacks-jobs/SKILL.md +136 -0
- package/ai/skills/stacks-lint/SKILL.md +184 -0
- package/ai/skills/stacks-listeners/SKILL.md +99 -0
- package/ai/skills/stacks-logging/SKILL.md +78 -0
- package/ai/skills/stacks-mail/SKILL.md +120 -0
- package/ai/skills/stacks-middleware/SKILL.md +249 -0
- package/ai/skills/stacks-migrations/SKILL.md +105 -0
- package/ai/skills/stacks-models/SKILL.md +267 -0
- package/ai/skills/stacks-new-feature/SKILL.md +206 -0
- package/ai/skills/stacks-notifications/SKILL.md +210 -0
- package/ai/skills/stacks-objects/SKILL.md +205 -0
- package/ai/skills/stacks-office-hours/SKILL.md +134 -0
- package/ai/skills/stacks-orm/SKILL.md +342 -0
- package/ai/skills/stacks-path/SKILL.md +118 -0
- package/ai/skills/stacks-payments/SKILL.md +373 -0
- package/ai/skills/stacks-plan-review/SKILL.md +152 -0
- package/ai/skills/stacks-plugins/SKILL.md +149 -0
- package/ai/skills/stacks-push/SKILL.md +376 -0
- package/ai/skills/stacks-query-builder/SKILL.md +128 -0
- package/ai/skills/stacks-queue/SKILL.md +559 -0
- package/ai/skills/stacks-realtime/SKILL.md +442 -0
- package/ai/skills/stacks-redesign/SKILL.md +182 -0
- package/ai/skills/stacks-registry/SKILL.md +58 -0
- package/ai/skills/stacks-repl/SKILL.md +80 -0
- package/ai/skills/stacks-retro/SKILL.md +122 -0
- package/ai/skills/stacks-review/SKILL.md +135 -0
- package/ai/skills/stacks-router/SKILL.md +231 -0
- package/ai/skills/stacks-routes/SKILL.md +105 -0
- package/ai/skills/stacks-scaffolding/SKILL.md +162 -0
- package/ai/skills/stacks-scheduler/SKILL.md +363 -0
- package/ai/skills/stacks-search-engine/SKILL.md +112 -0
- package/ai/skills/stacks-security/SKILL.md +129 -0
- package/ai/skills/stacks-security-audit/SKILL.md +128 -0
- package/ai/skills/stacks-server/SKILL.md +458 -0
- package/ai/skills/stacks-shell/SKILL.md +62 -0
- package/ai/skills/stacks-slug/SKILL.md +87 -0
- package/ai/skills/stacks-sms/SKILL.md +385 -0
- package/ai/skills/stacks-socials/SKILL.md +303 -0
- package/ai/skills/stacks-storage/SKILL.md +576 -0
- package/ai/skills/stacks-strings/SKILL.md +416 -0
- package/ai/skills/stacks-stx/SKILL.md +176 -0
- package/ai/skills/stacks-technical-diagrams/LICENSE +22 -0
- package/ai/skills/stacks-technical-diagrams/SKILL.md +290 -0
- package/ai/skills/stacks-technical-diagrams/agents/openai.yaml +4 -0
- package/ai/skills/stacks-technical-diagrams/assets/template.html +1252 -0
- package/ai/skills/stacks-technical-diagrams/bin/technical-diagrams.mjs +289 -0
- package/ai/skills/stacks-technical-diagrams/bunfig.toml +1 -0
- package/ai/skills/stacks-technical-diagrams/examples/agent-run.lifecycle.json +64 -0
- package/ai/skills/stacks-technical-diagrams/examples/agent-tool-call.workflow.json +88 -0
- package/ai/skills/stacks-technical-diagrams/examples/cache-miss-request.sequence.json +75 -0
- package/ai/skills/stacks-technical-diagrams/examples/product-analytics.dataflow.json +70 -0
- package/ai/skills/stacks-technical-diagrams/examples/web-app.architecture.json +41 -0
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/grid.mjs +62 -0
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/render-architecture.mjs +371 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/README.md +82 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/render-dataflow.mjs +295 -0
- package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/README.md +91 -0
- package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/render-lifecycle.mjs +384 -0
- package/ai/skills/stacks-technical-diagrams/renderers/sequence/README.md +84 -0
- package/ai/skills/stacks-technical-diagrams/renderers/sequence/render-sequence.mjs +257 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/cli.mjs +42 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/generated-validators.mjs +13 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/geometry.mjs +230 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/layout-report.mjs +40 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/utils.mjs +88 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/validator.mjs +40 -0
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/README.md +103 -0
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/render-workflow.mjs +481 -0
- package/ai/skills/stacks-technical-diagrams/schemas/README.md +68 -0
- package/ai/skills/stacks-technical-diagrams/schemas/architecture.schema.json +121 -0
- package/ai/skills/stacks-technical-diagrams/schemas/common.schema.json +43 -0
- package/ai/skills/stacks-technical-diagrams/schemas/dataflow.schema.json +221 -0
- package/ai/skills/stacks-technical-diagrams/schemas/lifecycle.schema.json +241 -0
- package/ai/skills/stacks-technical-diagrams/schemas/sequence.schema.json +186 -0
- package/ai/skills/stacks-technical-diagrams/schemas/workflow.schema.json +332 -0
- package/ai/skills/stacks-technical-diagrams/scripts/check-render-output.mjs +297 -0
- package/ai/skills/stacks-technical-diagrams/scripts/render-examples.mjs +28 -0
- package/ai/skills/stacks-testing/SKILL.md +129 -0
- package/ai/skills/stacks-tunnel/SKILL.md +125 -0
- package/ai/skills/stacks-types/SKILL.md +178 -0
- package/ai/skills/stacks-ui/SKILL.md +246 -0
- package/ai/skills/stacks-utils/SKILL.md +444 -0
- package/ai/skills/stacks-validation/SKILL.md +371 -0
- package/ai/skills/stacks-whois/SKILL.md +315 -0
- package/assets/world-map-data.ts +121 -0
- package/bootstrap.ts +114 -0
- package/docs/api-examples.md +46 -0
- package/docs/index.md +24 -0
- package/docs/markdown-examples.md +87 -0
- package/functions/analytics.ts +97 -0
- package/functions/api.ts +143 -0
- package/functions/auth.ts +208 -0
- package/functions/billing/payments.ts +149 -0
- package/functions/blog.ts +120 -0
- package/functions/cms/categorizables.ts +107 -0
- package/functions/cms/pages.ts +108 -0
- package/functions/cms/posts.ts +100 -0
- package/functions/cms/taggables.ts +102 -0
- package/functions/commerce/coupons.ts +128 -0
- package/functions/commerce/customers.ts +128 -0
- package/functions/commerce/gift-cards.ts +119 -0
- package/functions/commerce/orders.ts +112 -0
- package/functions/commerce/payments.ts +119 -0
- package/functions/commerce/products/categories.ts +123 -0
- package/functions/commerce/products/manufacturers.ts +123 -0
- package/functions/commerce/products/products.ts +123 -0
- package/functions/commerce/products/reviews.ts +123 -0
- package/functions/commerce/products/units.ts +123 -0
- package/functions/commerce/products/variants.ts +123 -0
- package/functions/commerce/shippings/delivery-routes.ts +123 -0
- package/functions/commerce/shippings/digital-deliveries.ts +119 -0
- package/functions/commerce/shippings/drivers.ts +123 -0
- package/functions/commerce/shippings/license-keys.ts +123 -0
- package/functions/commerce/shippings/shipping-methods.ts +123 -0
- package/functions/commerce/shippings/shipping-rates.ts +119 -0
- package/functions/commerce/shippings/shipping-zones.ts +119 -0
- package/functions/commerce/taxes.ts +119 -0
- package/functions/commerce/waitlist/products.ts +123 -0
- package/functions/commerce/waitlist/restaurants.ts +123 -0
- package/functions/craft.ts +107 -0
- package/functions/dashboard.ts +153 -0
- package/functions/inbox.ts +95 -0
- package/functions/jobs.ts +86 -0
- package/functions/monitoring/errors.ts +295 -0
- package/functions/queue.ts +111 -0
- package/functions/realtime/websockets.ts +96 -0
- package/functions/realtime.ts +52 -0
- package/functions/releases.ts +49 -0
- package/functions/search.ts +126 -0
- package/functions/toasts.ts +95 -0
- package/functions/uploads.ts +216 -0
- package/ide/.gitignore +4 -0
- package/ide/cursor/rules/auto-imports.mdc +574 -0
- package/ide/cursor/rules/code-style.mdc +12 -0
- package/ide/cursor/rules/documentation.mdc +9 -0
- package/ide/cursor/rules/error-handling-validation.mdc +11 -0
- package/ide/cursor/rules/key-conventions.mdc +11 -0
- package/ide/cursor/rules/project-structure.mdc +169 -0
- package/ide/cursor/rules/readme.mdc +318 -0
- package/ide/cursor/rules/syntax-formatting.mdc +9 -0
- package/ide/cursor/rules/testing.mdc +10 -0
- package/ide/cursor/rules/typescript.mdc +9 -0
- package/ide/cursor/rules/ui-styling.mdc +0 -0
- package/ide/dictionary.txt +397 -0
- package/ide/jetbrains/.fleet/settings.json +4 -0
- package/ide/jetbrains/.idea/.gitignore +5 -0
- package/ide/jetbrains/.idea/.name +1 -0
- package/ide/jetbrains/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/ide/jetbrains/.idea/jsLinters/eslint.xml +7 -0
- package/ide/jetbrains/.idea/modules.xml +8 -0
- package/ide/jetbrains/.idea/stacks.iml +22 -0
- package/ide/jetbrains/.idea/vcs.xml +6 -0
- package/ide/jetbrains/.idea/webResources.xml +14 -0
- package/ide/jetbrains/IntelliJ IDEA Global Settings +0 -0
- package/ide/jetbrains/installed.txt +4 -0
- package/ide/jetbrains/options/github-copilot.xml +5 -0
- package/ide/jetbrains/options/nodejs.xml +7 -0
- package/ide/jetbrains/options/templates.xml +124 -0
- package/ide/jetbrains/templates/JavaScript.xml +6 -0
- package/ide/jetbrains/templates/Stacks.xml +8 -0
- package/ide/vscode/.vscode/README.md +23 -0
- package/ide/vscode/.vscode/extensions.json +5 -0
- package/ide/vscode/.vscode/settings.json +176 -0
- package/ide/vscode/.vscode/stacks.code-snippets +181 -0
- package/ide/vscode/LICENSE.md +21 -0
- package/ide/vscode/README.md +36 -0
- package/ide/vscode/logo.png +0 -0
- package/ide/vscode/package.json +79 -0
- package/ide/zed/.zed/settings.json +139 -0
- package/lang/README.md +28 -0
- package/lang/de.yml +14 -0
- package/lang/en.yml +15 -0
- package/package.json +19 -3
- package/project/bootstrap +161 -0
- package/project/buddy +175 -0
- package/project/storage/framework/tsconfig.app.json +50 -0
- package/project/storage/framework/tsconfig.base.json +58 -0
- package/routes/core.ts +78 -0
- package/routes/dashboard-api.ts +233 -0
- package/routes/dashboard.ts +739 -0
- package/routes/email.ts +129 -0
- package/stores/[name].stx +16 -0
- package/stores/git.ts +71 -0
- package/stores/payment.ts +474 -0
- package/stores/queue.ts +43 -0
- package/stores/user.ts +29 -0
- package/stx-components-plugin.ts +25 -0
- package/styles/design-tokens.css +597 -0
- package/types/dashboard.ts +70 -0
- package/types/defaults.ts +438 -0
- package/vcs/github/CODE_OF_CONDUCT.md +83 -0
- package/vcs/github/CONTRIBUTING.md +187 -0
- package/vcs/github/EXPLANATIONS.md +41 -0
- package/vcs/github/FUNDING.yml +1 -0
- package/vcs/github/ISSUE_TEMPLATE/bug_report.yml +49 -0
- package/vcs/github/ISSUE_TEMPLATE/config.yml +10 -0
- package/vcs/github/ISSUE_TEMPLATE/feature_request.yml +44 -0
- package/vcs/github/SECURITY.md +70 -0
- package/vcs/github/renovate.json +5 -0
- package/vcs/github/stale.yml +14 -0
- package/vcs/github/workflows/README.md +16 -0
- package/vcs/github/workflows/ci.yml +114 -0
- package/vcs/github/workflows/export-size.yml +25 -0
- package/vcs/github/workflows/labeler.yml +13 -0
- package/vcs/github/workflows/release.yml +219 -0
- package/views/[...all].stx +8 -0
- package/views/about.md +3 -0
- package/views/auth/login.stx +1 -0
- package/views/auth/signup.stx +85 -0
- package/views/dashboard/.discovered-models.json +542 -0
- package/views/dashboard/AUDIT.md +904 -0
- package/views/dashboard/[...all].stx +89 -0
- package/views/dashboard/access-tokens/index.stx +177 -0
- package/views/dashboard/actions/index.stx +129 -0
- package/views/dashboard/analytics/blog/index.stx +356 -0
- package/views/dashboard/analytics/browsers/index.stx +263 -0
- package/views/dashboard/analytics/commerce/sales/index.stx +329 -0
- package/views/dashboard/analytics/commerce/web/index.stx +379 -0
- package/views/dashboard/analytics/countries/index.stx +289 -0
- package/views/dashboard/analytics/devices/index.stx +305 -0
- package/views/dashboard/analytics/events/index.stx +536 -0
- package/views/dashboard/analytics/index.stx +88 -0
- package/views/dashboard/analytics/marketing/index.stx +315 -0
- package/views/dashboard/analytics/pages/index.stx +271 -0
- package/views/dashboard/analytics/referrers/index.stx +319 -0
- package/views/dashboard/analytics/web/index.stx +356 -0
- package/views/dashboard/buddy/index.stx +198 -0
- package/views/dashboard/ci/index.stx +462 -0
- package/views/dashboard/cloud/index.stx +452 -0
- package/views/dashboard/commands/index.stx +295 -0
- package/views/dashboard/commerce/categories/index.stx +406 -0
- package/views/dashboard/commerce/coupons/index.stx +485 -0
- package/views/dashboard/commerce/customers/index.stx +410 -0
- package/views/dashboard/commerce/dashboard/index.stx +287 -0
- package/views/dashboard/commerce/delivery/delivery-routes.stx +305 -0
- package/views/dashboard/commerce/delivery/digital-delivery.stx +332 -0
- package/views/dashboard/commerce/delivery/drivers.stx +397 -0
- package/views/dashboard/commerce/delivery/index.stx +18 -0
- package/views/dashboard/commerce/delivery/license-keys.stx +380 -0
- package/views/dashboard/commerce/delivery/shipping-methods.stx +346 -0
- package/views/dashboard/commerce/delivery/shipping-rates.stx +338 -0
- package/views/dashboard/commerce/delivery/shipping-zones.stx +302 -0
- package/views/dashboard/commerce/delivery/tabs.ts +25 -0
- package/views/dashboard/commerce/gift-cards/index.stx +561 -0
- package/views/dashboard/commerce/manufacturers/index.stx +308 -0
- package/views/dashboard/commerce/orders/index.stx +247 -0
- package/views/dashboard/commerce/payments/index.stx +535 -0
- package/views/dashboard/commerce/pos/index.stx +653 -0
- package/views/dashboard/commerce/printers/devices/index.stx +273 -0
- package/views/dashboard/commerce/printers/receipts/index.stx +308 -0
- package/views/dashboard/commerce/products/detail.stx +563 -0
- package/views/dashboard/commerce/products/index.stx +370 -0
- package/views/dashboard/commerce/reviews/index.stx +656 -0
- package/views/dashboard/commerce/reviews/index.ts +0 -0
- package/views/dashboard/commerce/taxes/index.stx +377 -0
- package/views/dashboard/commerce/units/index.stx +317 -0
- package/views/dashboard/commerce/variants/index.stx +319 -0
- package/views/dashboard/commerce/waitlist/products.stx +942 -0
- package/views/dashboard/commerce/waitlist/restaurant.stx +1024 -0
- package/views/dashboard/components/index.stx +330 -0
- package/views/dashboard/composables/index.ts +19 -0
- package/views/dashboard/composables/useChart.ts +77 -0
- package/views/dashboard/composables/useNavigation.ts +99 -0
- package/views/dashboard/composables/useRole.ts +58 -0
- package/views/dashboard/composables/useTheme.ts +74 -0
- package/views/dashboard/content/authors/index.stx +171 -0
- package/views/dashboard/content/blog/index.stx +493 -0
- package/views/dashboard/content/categories/index.stx +169 -0
- package/views/dashboard/content/comments/index.stx +189 -0
- package/views/dashboard/content/dashboard.stx +383 -0
- package/views/dashboard/content/files/index.stx +706 -0
- package/views/dashboard/content/pages/index.stx +174 -0
- package/views/dashboard/content/posts/index.stx +269 -0
- package/views/dashboard/content/seo/index.stx +240 -0
- package/views/dashboard/content/tags/index.stx +167 -0
- package/views/dashboard/data/activity/index.stx +261 -0
- package/views/dashboard/data/dashboard/index.stx +116 -0
- package/views/dashboard/data/subscribers.stx +270 -0
- package/views/dashboard/data/teams.stx +275 -0
- package/views/dashboard/data/users.stx +279 -0
- package/views/dashboard/dependencies/index.stx +178 -0
- package/views/dashboard/deployments/[id].stx +234 -0
- package/views/dashboard/deployments/index.stx +9 -0
- package/views/dashboard/dns/index.stx +163 -0
- package/views/dashboard/environment/index.stx +283 -0
- package/views/dashboard/errors/index.stx +274 -0
- package/views/dashboard/forgot-password.stx +57 -0
- package/views/dashboard/functions/index.stx +159 -0
- package/views/dashboard/health/index.stx +248 -0
- package/views/dashboard/inbox/activity.stx +350 -0
- package/views/dashboard/inbox/index.stx +452 -0
- package/views/dashboard/inbox/settings.stx +290 -0
- package/views/dashboard/index.stx +252 -0
- package/views/dashboard/insights/index.stx +529 -0
- package/views/dashboard/jobs/[id].stx +430 -0
- package/views/dashboard/jobs/history.stx +222 -0
- package/views/dashboard/jobs/index.stx +214 -0
- package/views/dashboard/kanban/[id].stx +899 -0
- package/views/dashboard/kanban/index.stx +260 -0
- package/views/dashboard/layouts/default.stx +565 -0
- package/views/dashboard/layouts/guest.stx +10 -0
- package/views/dashboard/login.stx +48 -0
- package/views/dashboard/logs/index.stx +540 -0
- package/views/dashboard/mailboxes/index.stx +149 -0
- package/views/dashboard/management/permissions/index.stx +490 -0
- package/views/dashboard/marketing/campaigns/index.stx +604 -0
- package/views/dashboard/marketing/lists/index.stx +514 -0
- package/views/dashboard/marketing/reviews/index.stx +475 -0
- package/views/dashboard/marketing/social-posts/index.stx +560 -0
- package/views/dashboard/models/[model].stx +195 -0
- package/views/dashboard/models/index.stx +159 -0
- package/views/dashboard/monitoring/errors/index.stx +415 -0
- package/views/dashboard/notifications/dashboard.stx +383 -0
- package/views/dashboard/notifications/email.stx +336 -0
- package/views/dashboard/notifications/history.stx +373 -0
- package/views/dashboard/notifications/sms.stx +332 -0
- package/views/dashboard/packages/index.stx +195 -0
- package/views/dashboard/queries/[id].stx +381 -0
- package/views/dashboard/queries/history.stx +227 -0
- package/views/dashboard/queries/index.stx +335 -0
- package/views/dashboard/queries/slow.stx +318 -0
- package/views/dashboard/queue/index.stx +427 -0
- package/views/dashboard/realtime/index.stx +429 -0
- package/views/dashboard/register.stx +46 -0
- package/views/dashboard/releases/index.stx +389 -0
- package/views/dashboard/requests/index.stx +462 -0
- package/views/dashboard/serverless/index.stx +475 -0
- package/views/dashboard/servers/[id].stx +299 -0
- package/views/dashboard/servers/index.stx +483 -0
- package/views/dashboard/settings/billing.stx +50 -0
- package/views/dashboard/settings/index.stx +256 -0
- package/views/dashboard/settings/mail.stx +252 -0
- package/views/dashboard/stores/auth.ts +123 -0
- package/views/dashboard/stores/ci.ts +342 -0
- package/views/dashboard/stores/index.ts +129 -0
- package/views/dashboard/stores/kanban.ts +723 -0
- package/views/dashboard/stores/rbac.ts +350 -0
- package/views/dashboard/stx.config.ts +34 -0
- package/views/dashboard/teams/[id].stx +170 -0
- package/views/forum/category.stx +92 -0
- package/views/forum/index.stx +209 -0
- package/views/forum/new-topic.stx +113 -0
- package/views/forum/profile.stx +1 -0
- package/views/forum/topic.stx +143 -0
- package/views/hello-world/[name].stx +47 -0
- package/views/index.stx +21 -0
- package/views/system-tray/index.stx +147 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
@extends('layouts/default')
|
|
2
|
+
|
|
3
|
+
@section('content')
|
|
4
|
+
@title('Dashboard - Food Vendors')
|
|
5
|
+
<PageLayout>
|
|
6
|
+
<div class="sm:flex sm:items-center sm:justify-between">
|
|
7
|
+
<PageHeader title="Manufacturers" description="Manage your product manufacturers" />
|
|
8
|
+
<div class="mt-4 sm:mt-0">
|
|
9
|
+
<button
|
|
10
|
+
type="button"
|
|
11
|
+
@click="openAddModal()"
|
|
12
|
+
class="inline-flex items-center px-3 py-2 font-semibold text-sm text-white bg-blue-600 hover:bg-blue-500 rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-blue-600 focus-visible:outline-offset-2 shadow-sm"
|
|
13
|
+
>
|
|
14
|
+
<div class="mr-1 h-5 w-5 i-hugeicons-plus-sign"></div>
|
|
15
|
+
Add manufacturer
|
|
16
|
+
</button>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<!-- Filters -->
|
|
21
|
+
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between mt-6">
|
|
22
|
+
<div class="relative max-w-sm">
|
|
23
|
+
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
|
|
24
|
+
<div class="h-5 w-5 text-gray-400 i-hugeicons-search-01"></div>
|
|
25
|
+
</div>
|
|
26
|
+
<input
|
|
27
|
+
x-model="searchQuery"
|
|
28
|
+
type="text"
|
|
29
|
+
class="block pl-10 pr-3 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white placeholder:text-gray-400 dark:placeholder:text-neutral-500 dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600 focus:ring-inset"
|
|
30
|
+
placeholder="Search manufacturers..."
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="flex flex-col gap-4 sm:flex-row">
|
|
35
|
+
<select
|
|
36
|
+
x-model="featuredFilter"
|
|
37
|
+
class="block pl-3 pr-10 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600 focus:ring-inset"
|
|
38
|
+
>
|
|
39
|
+
<option value="all">All Manufacturers</option>
|
|
40
|
+
<option value="featured">Featured Only</option>
|
|
41
|
+
<option value="not-featured">Not Featured</option>
|
|
42
|
+
</select>
|
|
43
|
+
|
|
44
|
+
<select
|
|
45
|
+
x-model="countryFilter"
|
|
46
|
+
class="block pl-3 pr-10 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600 focus:ring-inset"
|
|
47
|
+
>
|
|
48
|
+
<option value="all">All Countries</option>
|
|
49
|
+
<template :for="country in countries">
|
|
50
|
+
<option value="{{ country }}">{{ country }}</option>
|
|
51
|
+
</template>
|
|
52
|
+
</select>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<!-- Manufacturers table -->
|
|
57
|
+
<div class="flow-root mt-6">
|
|
58
|
+
<div class="overflow-x-auto -mx-4 -my-2 sm:-mx-6 lg:-mx-8">
|
|
59
|
+
<div class="inline-block py-2 sm:px-6 lg:px-8 min-w-full align-middle">
|
|
60
|
+
<div class="overflow-hidden ring-1 ring-black ring-opacity-5 sm:rounded-lg shadow">
|
|
61
|
+
<table class="min-w-full divide-gray-300 divide-y dark:divide-neutral-700">
|
|
62
|
+
<thead class="bg-gray-50 dark:bg-neutral-700">
|
|
63
|
+
<tr>
|
|
64
|
+
<th scope="col" class="pl-4 pr-3 py-3.5 sm:pl-6 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">
|
|
65
|
+
<button @click="toggleSort('name')" class="inline-flex items-center group">
|
|
66
|
+
Manufacturer
|
|
67
|
+
<span class="group-focus:visible group-hover:visible flex-none ml-2 text-gray-400 rounded">
|
|
68
|
+
<div class="h-4 w-4 {{ sortBy() === 'name' ? (sortOrder() === 'asc' ? 'i-hugeicons-arrow-up-02' : 'i-hugeicons-arrow-down-02') : 'i-hugeicons-arrows-up-down' }}"></div>
|
|
69
|
+
</span>
|
|
70
|
+
</button>
|
|
71
|
+
</th>
|
|
72
|
+
<th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">Description</th>
|
|
73
|
+
<th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">
|
|
74
|
+
<button @click="toggleSort('country')" class="inline-flex items-center group">
|
|
75
|
+
Country
|
|
76
|
+
<span class="group-focus:visible group-hover:visible flex-none ml-2 text-gray-400 rounded">
|
|
77
|
+
<div class="h-4 w-4 {{ sortBy() === 'country' ? (sortOrder() === 'asc' ? 'i-hugeicons-arrow-up-02' : 'i-hugeicons-arrow-down-02') : 'i-hugeicons-arrows-up-down' }}"></div>
|
|
78
|
+
</span>
|
|
79
|
+
</button>
|
|
80
|
+
</th>
|
|
81
|
+
<th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">
|
|
82
|
+
<button @click="toggleSort('productCount')" class="inline-flex items-center group">
|
|
83
|
+
Products
|
|
84
|
+
<span class="group-focus:visible group-hover:visible flex-none ml-2 text-gray-400 rounded">
|
|
85
|
+
<div class="h-4 w-4 {{ sortBy() === 'productCount' ? (sortOrder() === 'asc' ? 'i-hugeicons-arrow-up-02' : 'i-hugeicons-arrow-down-02') : 'i-hugeicons-arrows-up-down' }}"></div>
|
|
86
|
+
</span>
|
|
87
|
+
</button>
|
|
88
|
+
</th>
|
|
89
|
+
<th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-left text-sm dark:text-neutral-200">Featured</th>
|
|
90
|
+
<th scope="col" class="px-3 py-3.5 font-semibold text-gray-900 text-right text-sm dark:text-neutral-200">
|
|
91
|
+
<button @click="toggleSort('createdAt')" class="inline-flex items-center text-right group">
|
|
92
|
+
Created
|
|
93
|
+
<span class="group-focus:visible group-hover:visible flex-none ml-2 text-gray-400 rounded">
|
|
94
|
+
<div class="h-4 w-4 {{ sortBy() === 'createdAt' ? (sortOrder() === 'asc' ? 'i-hugeicons-arrow-up-02' : 'i-hugeicons-arrow-down-02') : 'i-hugeicons-arrows-up-down' }}"></div>
|
|
95
|
+
</span>
|
|
96
|
+
</button>
|
|
97
|
+
</th>
|
|
98
|
+
<th scope="col" class="relative pl-3 pr-4 py-3.5 sm:pr-6">
|
|
99
|
+
<span class="sr-only">Actions</span>
|
|
100
|
+
</th>
|
|
101
|
+
</tr>
|
|
102
|
+
</thead>
|
|
103
|
+
<tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
|
|
104
|
+
<template :for="manufacturer in filteredManufacturers">
|
|
105
|
+
<tr>
|
|
106
|
+
<td class="pl-4 pr-3 py-4 sm:pl-6 font-medium text-gray-900 text-sm whitespace-nowrap dark:text-white">{{ manufacturer.name }}</td>
|
|
107
|
+
<td class="px-3 py-4 text-gray-500 text-sm dark:text-neutral-300">{{ manufacturer.description }}</td>
|
|
108
|
+
<td class="px-3 py-4 text-gray-500 text-sm whitespace-nowrap dark:text-neutral-300">{{ manufacturer.country }}</td>
|
|
109
|
+
<td class="px-3 py-4 text-gray-500 text-sm whitespace-nowrap dark:text-neutral-300">{{ manufacturer.productCount }}</td>
|
|
110
|
+
<td class="px-3 py-4 text-gray-500 text-sm whitespace-nowrap dark:text-neutral-300">
|
|
111
|
+
@if(manufacturer.featured)
|
|
112
|
+
<div class="h-5 w-5 text-green-500 i-hugeicons-checkmark-circle-02"></div>
|
|
113
|
+
@else
|
|
114
|
+
<div class="h-5 w-5 text-gray-400 i-hugeicons-cancel-circle"></div>
|
|
115
|
+
@endif
|
|
116
|
+
</td>
|
|
117
|
+
<td class="px-3 py-4 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">{{ manufacturer.createdAt }}</td>
|
|
118
|
+
<td class="relative pl-3 pr-4 py-4 sm:pr-6 font-medium text-right text-sm whitespace-nowrap">
|
|
119
|
+
<div class="flex items-center justify-end space-x-2">
|
|
120
|
+
<button type="button" class="text-gray-400 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300 duration-150 transition-colors">
|
|
121
|
+
<div class="h-5 w-5 i-hugeicons-edit-01"></div>
|
|
122
|
+
</button>
|
|
123
|
+
<button type="button" class="text-gray-400 dark:text-red-400 hover:text-red-900 dark:hover:text-red-300 duration-150 transition-colors">
|
|
124
|
+
<div class="h-5 w-5 i-hugeicons-waste"></div>
|
|
125
|
+
</button>
|
|
126
|
+
</div>
|
|
127
|
+
</td>
|
|
128
|
+
</tr>
|
|
129
|
+
</template>
|
|
130
|
+
@if(filteredManufacturers().length === 0)
|
|
131
|
+
<tr>
|
|
132
|
+
<td colspan="7" class="px-6 py-4 text-center text-gray-500 text-sm dark:text-neutral-400">
|
|
133
|
+
No manufacturers found matching your criteria
|
|
134
|
+
</td>
|
|
135
|
+
</tr>
|
|
136
|
+
@endif
|
|
137
|
+
</tbody>
|
|
138
|
+
</table>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<!-- Add Manufacturer Modal -->
|
|
147
|
+
<div :show="showAddModal" class="fixed inset-0 overflow-y-auto z-10">
|
|
148
|
+
<div class="flex items-end justify-center sm:items-center p-4 sm:p-0 min-h-full text-center">
|
|
149
|
+
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" @click="closeAddModal()"></div>
|
|
150
|
+
|
|
151
|
+
<div class="overflow-hidden relative pb-4 pt-5 px-4 sm:my-8 sm:p-6 sm:max-w-lg sm:w-full text-left bg-white dark:bg-neutral-800 rounded-lg shadow-xl transition-all transform">
|
|
152
|
+
<div>
|
|
153
|
+
<div class="mt-3 sm:mt-5 text-center">
|
|
154
|
+
<h3 class="font-semibold leading-6 text-base text-gray-900 dark:text-white">Add New Manufacturer</h3>
|
|
155
|
+
<div class="mt-4">
|
|
156
|
+
<div class="space-y-4">
|
|
157
|
+
<div>
|
|
158
|
+
<label for="manufacturer-name" class="block font-medium leading-6 text-gray-900 text-left text-sm dark:text-neutral-200">Name</label>
|
|
159
|
+
<div class="mt-2">
|
|
160
|
+
<input type="text" id="manufacturer-name" x-model="newName" class="block py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white placeholder:text-gray-400 dark:bg-neutral-700 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-600 focus:ring-2 focus:ring-blue-600 focus:ring-inset shadow-sm" />
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
<div>
|
|
164
|
+
<label for="manufacturer-description" class="block font-medium leading-6 text-gray-900 text-left text-sm dark:text-neutral-200">Description</label>
|
|
165
|
+
<div class="mt-2">
|
|
166
|
+
<textarea id="manufacturer-description" x-model="newDescription" rows="3" class="block py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white placeholder:text-gray-400 dark:bg-neutral-700 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-600 focus:ring-2 focus:ring-blue-600 focus:ring-inset shadow-sm"></textarea>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
<div>
|
|
170
|
+
<label for="manufacturer-country" class="block font-medium leading-6 text-gray-900 text-left text-sm dark:text-neutral-200">Country</label>
|
|
171
|
+
<div class="mt-2">
|
|
172
|
+
<input type="text" id="manufacturer-country" x-model="newCountry" class="block py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white placeholder:text-gray-400 dark:bg-neutral-700 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-600 focus:ring-2 focus:ring-blue-600 focus:ring-inset shadow-sm" />
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
<div>
|
|
176
|
+
<label for="manufacturer-website" class="block font-medium leading-6 text-gray-900 text-left text-sm dark:text-neutral-200">Website</label>
|
|
177
|
+
<div class="mt-2">
|
|
178
|
+
<input type="url" id="manufacturer-website" x-model="newWebsite" class="block py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white placeholder:text-gray-400 dark:bg-neutral-700 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-600 focus:ring-2 focus:ring-blue-600 focus:ring-inset shadow-sm" />
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
<div class="flex items-center">
|
|
182
|
+
<input id="manufacturer-featured" type="checkbox" x-model="newFeatured" class="h-4 w-4 text-blue-600 dark:bg-neutral-700 border-gray-300 rounded dark:border-neutral-600 focus:ring-blue-600" />
|
|
183
|
+
<label for="manufacturer-featured" class="block ml-2 text-gray-900 text-sm dark:text-neutral-200">Featured manufacturer</label>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
<div class="sm:grid sm:gap-3 sm:grid-cols-2 sm:grid-flow-row-dense mt-5 sm:mt-6">
|
|
190
|
+
<button type="button" @click="addManufacturer()" class="inline-flex justify-center sm:col-start-2 px-3 py-2 w-full font-semibold text-sm text-white bg-blue-600 hover:bg-blue-500 rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-blue-600 focus-visible:outline-offset-2 shadow-sm">Add</button>
|
|
191
|
+
<button type="button" @click="closeAddModal()" class="inline-flex justify-center sm:col-start-1 mt-3 px-3 py-2 sm:mt-0 w-full font-semibold text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-700 hover:bg-gray-50 dark:hover:bg-neutral-600 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-600 shadow-sm">Cancel</button>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
</PageLayout>
|
|
195
|
+
<script client>
|
|
196
|
+
interface Manufacturer {
|
|
197
|
+
id: number
|
|
198
|
+
name: string
|
|
199
|
+
slug: string
|
|
200
|
+
description: string
|
|
201
|
+
productCount: number
|
|
202
|
+
featured: boolean
|
|
203
|
+
country: string
|
|
204
|
+
website: string
|
|
205
|
+
createdAt: string
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const initialManufacturers: Manufacturer[] = [
|
|
209
|
+
{ id: 1, name: 'Pizza Palace', slug: 'pizza-palace', description: 'Authentic Italian pizzeria with handcrafted pizzas and fresh ingredients', productCount: 24, featured: true, country: 'United States', website: 'https://pizzapalace.foodmarket.org', createdAt: '2023-05-10' },
|
|
210
|
+
{ id: 2, name: 'Burger Bistro', slug: 'burger-bistro', description: 'Gourmet burgers made with locally sourced ingredients', productCount: 18, featured: true, country: 'United States', website: 'https://burgerbistro.foodmarket.org', createdAt: '2023-05-15' },
|
|
211
|
+
{ id: 3, name: 'Sushi Supreme', slug: 'sushi-supreme', description: 'Premium sushi and Japanese cuisine prepared by master chefs', productCount: 32, featured: true, country: 'United States', website: 'https://sushisupreme.foodmarket.org', createdAt: '2023-06-01' },
|
|
212
|
+
{ id: 4, name: 'Taco Tiempo', slug: 'taco-tiempo', description: 'Authentic Mexican street food with fresh, bold flavors', productCount: 22, featured: false, country: 'United States', website: 'https://tacotime.foodmarket.org', createdAt: '2023-06-10' },
|
|
213
|
+
{ id: 5, name: 'Pasta Paradise', slug: 'pasta-paradise', description: 'Handmade pasta and traditional Italian recipes', productCount: 16, featured: false, country: 'United States', website: 'https://pastaparadise.foodmarket.org', createdAt: '2023-06-20' },
|
|
214
|
+
{ id: 6, name: 'Healthy Harvest', slug: 'healthy-harvest', description: 'Nutritious, plant-based meals for health-conscious customers', productCount: 28, featured: true, country: 'United States', website: 'https://healthyharvest.foodmarket.org', createdAt: '2023-07-05' },
|
|
215
|
+
{ id: 7, name: 'Sweet Sensations', slug: 'sweet-sensations', description: 'Artisanal desserts, cakes, and pastries for every occasion', productCount: 35, featured: false, country: 'United States', website: 'https://sweetsensations.foodmarket.org', createdAt: '2023-07-15' },
|
|
216
|
+
{ id: 8, name: 'Beverage Boutique', slug: 'beverage-boutique', description: 'Specialty coffees, teas, smoothies, and craft beverages', productCount: 19, featured: false, country: 'United States', website: 'https://beverageboutique.foodmarket.org', createdAt: '2023-08-01' },
|
|
217
|
+
]
|
|
218
|
+
|
|
219
|
+
const manufacturers = state(initialManufacturers)
|
|
220
|
+
const searchQuery = state('')
|
|
221
|
+
const sortBy = state<'name' | 'productCount' | 'country' | 'createdAt'>('name')
|
|
222
|
+
const sortOrder = state<'asc' | 'desc'>('asc')
|
|
223
|
+
const featuredFilter = state<'all' | 'featured' | 'not-featured'>('all')
|
|
224
|
+
const countryFilter = state<string>('all')
|
|
225
|
+
|
|
226
|
+
const showAddModal = state(false)
|
|
227
|
+
const newName = state('')
|
|
228
|
+
const newDescription = state('')
|
|
229
|
+
const newFeatured = state(false)
|
|
230
|
+
const newCountry = state('')
|
|
231
|
+
const newWebsite = state('')
|
|
232
|
+
|
|
233
|
+
function countries(): string[] {
|
|
234
|
+
return Array.from(new Set(manufacturers().map(m => m.country))).sort()
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const filteredManufacturers = derived(() => {
|
|
238
|
+
const q = searchQuery().toLowerCase()
|
|
239
|
+
const fFilter = featuredFilter()
|
|
240
|
+
const cFilter = countryFilter()
|
|
241
|
+
const by = sortBy()
|
|
242
|
+
const dir = sortOrder()
|
|
243
|
+
|
|
244
|
+
return manufacturers()
|
|
245
|
+
.filter((m) => {
|
|
246
|
+
const matchesSearch
|
|
247
|
+
= m.name.toLowerCase().includes(q)
|
|
248
|
+
|| m.description.toLowerCase().includes(q)
|
|
249
|
+
const matchesFeatured
|
|
250
|
+
= fFilter === 'all'
|
|
251
|
+
|| (fFilter === 'featured' && m.featured)
|
|
252
|
+
|| (fFilter === 'not-featured' && !m.featured)
|
|
253
|
+
const matchesCountry = cFilter === 'all' || m.country === cFilter
|
|
254
|
+
return matchesSearch && matchesFeatured && matchesCountry
|
|
255
|
+
})
|
|
256
|
+
.sort((a, b) => {
|
|
257
|
+
let cmp = 0
|
|
258
|
+
if (by === 'name') cmp = a.name.localeCompare(b.name)
|
|
259
|
+
else if (by === 'productCount') cmp = a.productCount - b.productCount
|
|
260
|
+
else if (by === 'country') cmp = a.country.localeCompare(b.country)
|
|
261
|
+
else if (by === 'createdAt') cmp = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
|
|
262
|
+
return dir === 'asc' ? cmp : -cmp
|
|
263
|
+
})
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
function toggleSort(column: 'name' | 'productCount' | 'country' | 'createdAt'): void {
|
|
267
|
+
if (sortBy() === column) {
|
|
268
|
+
sortOrder.update(d => d === 'asc' ? 'desc' : 'asc')
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
sortBy.set(column)
|
|
272
|
+
sortOrder.set('asc')
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function openAddModal(): void {
|
|
277
|
+
newName.set('')
|
|
278
|
+
newDescription.set('')
|
|
279
|
+
newFeatured.set(false)
|
|
280
|
+
newCountry.set('')
|
|
281
|
+
newWebsite.set('')
|
|
282
|
+
showAddModal.set(true)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function closeAddModal(): void {
|
|
286
|
+
showAddModal.set(false)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function addManufacturer(): void {
|
|
290
|
+
const list = manufacturers()
|
|
291
|
+
const id = list.length > 0 ? Math.max(...list.map(m => m.id)) + 1 : 1
|
|
292
|
+
const name = newName()
|
|
293
|
+
manufacturers.set([...list, {
|
|
294
|
+
id,
|
|
295
|
+
name,
|
|
296
|
+
slug: name.toLowerCase().replace(/\s+/g, '-'),
|
|
297
|
+
description: newDescription(),
|
|
298
|
+
productCount: 0,
|
|
299
|
+
featured: newFeatured(),
|
|
300
|
+
country: newCountry(),
|
|
301
|
+
website: newWebsite(),
|
|
302
|
+
createdAt: new Date().toISOString().split('T')[0] || '',
|
|
303
|
+
}])
|
|
304
|
+
closeAddModal()
|
|
305
|
+
}
|
|
306
|
+
</script>
|
|
307
|
+
|
|
308
|
+
@endsection
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
@extends('layouts/default')
|
|
2
|
+
|
|
3
|
+
@section('content')
|
|
4
|
+
<div class="p-6 space-y-6">
|
|
5
|
+
|
|
6
|
+
<PageHeader title="Orders" description="Manage commerce orders">
|
|
7
|
+
<template #actions>
|
|
8
|
+
<Button variant="primary" @click="openAddModal()">
|
|
9
|
+
<div class="h-4 w-4 i-hugeicons-plus-sign"></div>
|
|
10
|
+
Add Order
|
|
11
|
+
</Button>
|
|
12
|
+
</template>
|
|
13
|
+
</PageHeader>
|
|
14
|
+
|
|
15
|
+
<div class="bg-white dark:bg-neutral-800/90 border border-black/5 rounded-xl dark:border-white/5">
|
|
16
|
+
<!-- Filters -->
|
|
17
|
+
<div class="p-4 border-b border-neutral-200/60 dark:border-white/5">
|
|
18
|
+
<FilterBar :searchPlaceholder="'Search orders...'" :searchValue="searchQuery" :itemsPerPage="itemsPerPage">
|
|
19
|
+
<Select
|
|
20
|
+
placeholder="All Statuses"
|
|
21
|
+
:options="statuses.map(s => ({ value: s, label: s === 'all' ? 'All Statuses' : s }))"
|
|
22
|
+
size="sm"
|
|
23
|
+
/>
|
|
24
|
+
</FilterBar>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<!-- Orders Table -->
|
|
28
|
+
<OrdersTable
|
|
29
|
+
:orders="paginatedOrders"
|
|
30
|
+
:searchQuery="searchQuery"
|
|
31
|
+
:statusFilter="statusFilter"
|
|
32
|
+
:sortBy="sortBy"
|
|
33
|
+
:sortOrder="sortOrder"
|
|
34
|
+
:currentPage="currentPage"
|
|
35
|
+
:itemsPerPage="itemsPerPage"
|
|
36
|
+
:statuses="statuses"
|
|
37
|
+
@toggle-sort="toggleSort"
|
|
38
|
+
/>
|
|
39
|
+
|
|
40
|
+
<!-- Pagination -->
|
|
41
|
+
<div class="p-4 border-neutral-200/60 border-t dark:border-white/5">
|
|
42
|
+
<Pagination
|
|
43
|
+
:currentPage="currentPage"
|
|
44
|
+
:totalPages="totalPages"
|
|
45
|
+
:totalItems="totalItems"
|
|
46
|
+
:itemsPerPage="itemsPerPage"
|
|
47
|
+
showItemsPerPage
|
|
48
|
+
/>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<!-- Add Order Modal -->
|
|
53
|
+
<Modal :isOpen="showAddModal" title="Add New Order" @close="closeAddModal">
|
|
54
|
+
<form @submit.prevent="addOrder()" class="space-y-4">
|
|
55
|
+
<Input label="Customer ID" name="customer_id" type="number" placeholder="Enter customer ID" :value="newCustomerId" required />
|
|
56
|
+
<Input label="Total Amount" name="total_amount" type="number" placeholder="0.00" :value="newTotalAmount" required />
|
|
57
|
+
<Select
|
|
58
|
+
label="Order Type"
|
|
59
|
+
:options="orderTypes"
|
|
60
|
+
:value="newOrderType"
|
|
61
|
+
/>
|
|
62
|
+
<Select
|
|
63
|
+
label="Status"
|
|
64
|
+
:options="newOrderStatusOptions"
|
|
65
|
+
:value="newStatus"
|
|
66
|
+
/>
|
|
67
|
+
<div class="flex gap-2 justify-end pt-4 border-neutral-200 border-t dark:border-neutral-700">
|
|
68
|
+
<Button variant="secondary" @click.prevent="closeAddModal()">Cancel</Button>
|
|
69
|
+
<Button variant="primary" type="submit">Add Order</Button>
|
|
70
|
+
</div>
|
|
71
|
+
</form>
|
|
72
|
+
</Modal>
|
|
73
|
+
|
|
74
|
+
<!-- Delete Confirmation -->
|
|
75
|
+
<ConfirmDialog
|
|
76
|
+
:isOpen="showDeleteModal"
|
|
77
|
+
title="Delete Order"
|
|
78
|
+
description="Are you sure you want to delete this order? This action cannot be undone."
|
|
79
|
+
confirmLabel="Delete Order"
|
|
80
|
+
variant="danger"
|
|
81
|
+
@confirm="confirmDelete"
|
|
82
|
+
@cancel="closeDeleteModal"
|
|
83
|
+
/>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<script client>
|
|
87
|
+
import { useOrders } from '../../../../functions/commerce/orders'
|
|
88
|
+
// Filter options — moved out of the former `<script server>` block
|
|
89
|
+
// (stacksjs/stacks#1838).
|
|
90
|
+
const statuses = ['all', 'Completed', 'Processing', 'Shipped', 'Cancelled', 'Refunded'] as const
|
|
91
|
+
const orderTypes = [
|
|
92
|
+
{ value: 'delivery', label: 'Delivery' },
|
|
93
|
+
{ value: 'pickup', label: 'Pickup' },
|
|
94
|
+
{ value: 'dine-in', label: 'Dine-in' },
|
|
95
|
+
] as const
|
|
96
|
+
|
|
97
|
+
interface Order {
|
|
98
|
+
id: number
|
|
99
|
+
customer_id: number
|
|
100
|
+
total_amount: number
|
|
101
|
+
status: string
|
|
102
|
+
order_type: string
|
|
103
|
+
coupon_id?: number
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const { orders, createOrder, fetchOrders, deleteOrder } = useOrders()
|
|
107
|
+
|
|
108
|
+
const statusFilter = state<string>('all')
|
|
109
|
+
const sortBy = state<'date' | 'total_amount' | 'customer_id'>('date')
|
|
110
|
+
const sortOrder = state<'asc' | 'desc'>('desc')
|
|
111
|
+
const searchQuery = state('')
|
|
112
|
+
const currentPage = state(1)
|
|
113
|
+
const itemsPerPage = state(10)
|
|
114
|
+
|
|
115
|
+
// Modal state.
|
|
116
|
+
const showAddModal = state(false)
|
|
117
|
+
const showDeleteModal = state(false)
|
|
118
|
+
const orderToDelete = state<Order | null>(null)
|
|
119
|
+
|
|
120
|
+
// New-order form fields — flat signals keep each x-model binding 1:1.
|
|
121
|
+
const newCustomerId = state(1)
|
|
122
|
+
const newTotalAmount = state(0)
|
|
123
|
+
const newStatus = state<'Completed' | 'Processing' | 'Shipped' | 'Cancelled' | 'Refunded'>('Processing')
|
|
124
|
+
const newOrderType = state<'delivery' | 'pickup' | 'dine-in'>('delivery')
|
|
125
|
+
|
|
126
|
+
// Status list for the modal excludes the 'all' filter sentinel.
|
|
127
|
+
const newOrderStatusOptions = derived(() =>
|
|
128
|
+
['Completed', 'Processing', 'Shipped', 'Cancelled', 'Refunded']
|
|
129
|
+
.map(s => ({ value: s, label: s })),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
const filteredOrders = derived(() => {
|
|
133
|
+
const q = searchQuery().toLowerCase()
|
|
134
|
+
const filter = statusFilter()
|
|
135
|
+
const by = sortBy()
|
|
136
|
+
const dir = sortOrder()
|
|
137
|
+
|
|
138
|
+
return (orders.value as Order[])
|
|
139
|
+
.filter((o) => {
|
|
140
|
+
const matchesSearch
|
|
141
|
+
= o.id.toString().toLowerCase().includes(q)
|
|
142
|
+
|| o.customer_id.toString().toLowerCase().includes(q)
|
|
143
|
+
|| o.order_type.toLowerCase().includes(q)
|
|
144
|
+
const matchesStatus = filter === 'all' || o.status === filter
|
|
145
|
+
return matchesSearch && matchesStatus
|
|
146
|
+
})
|
|
147
|
+
.sort((a, b) => {
|
|
148
|
+
let cmp = 0
|
|
149
|
+
if (by === 'total_amount')
|
|
150
|
+
cmp = a.total_amount - b.total_amount
|
|
151
|
+
else if (by === 'customer_id')
|
|
152
|
+
cmp = a.customer_id - b.customer_id
|
|
153
|
+
return dir === 'asc' ? cmp : -cmp
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
const paginatedOrders = derived(() => {
|
|
158
|
+
const start = (currentPage() - 1) * itemsPerPage()
|
|
159
|
+
return filteredOrders().slice(start, start + itemsPerPage())
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
const totalItems = derived(() => filteredOrders().length)
|
|
163
|
+
const totalPages = derived(() => Math.ceil(totalItems() / itemsPerPage()))
|
|
164
|
+
|
|
165
|
+
function toggleSort(column: 'date' | 'total_amount' | 'customer_id'): void {
|
|
166
|
+
if (sortBy() === column) {
|
|
167
|
+
sortOrder.update(d => d === 'asc' ? 'desc' : 'asc')
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
sortBy.set(column)
|
|
171
|
+
sortOrder.set('desc')
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function openAddModal(): void {
|
|
176
|
+
newCustomerId.set(1)
|
|
177
|
+
newTotalAmount.set(0)
|
|
178
|
+
newStatus.set('Processing')
|
|
179
|
+
newOrderType.set('delivery')
|
|
180
|
+
showAddModal.set(true)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function closeAddModal(): void {
|
|
184
|
+
showAddModal.set(false)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function closeDeleteModal(): void {
|
|
188
|
+
showDeleteModal.set(false)
|
|
189
|
+
orderToDelete.set(null)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function addOrder(): Promise<void> {
|
|
193
|
+
const list = orders.value as Order[]
|
|
194
|
+
const id = list.length > 0 ? Math.max(...list.map(o => o.id || 0)) + 1 : 1
|
|
195
|
+
const optimistic: Order = {
|
|
196
|
+
id,
|
|
197
|
+
customer_id: newCustomerId(),
|
|
198
|
+
coupon_id: 0,
|
|
199
|
+
status: newStatus(),
|
|
200
|
+
total_amount: newTotalAmount(),
|
|
201
|
+
order_type: newOrderType(),
|
|
202
|
+
}
|
|
203
|
+
orders.value = [optimistic, ...list]
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
const created = await createOrder(optimistic)
|
|
207
|
+
if (created) {
|
|
208
|
+
closeAddModal()
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
orders.value = (orders.value as Order[]).filter(o => o.id !== id)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
orders.value = (orders.value as Order[]).filter(o => o.id !== id)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async function confirmDelete(): Promise<void> {
|
|
220
|
+
const target = orderToDelete()
|
|
221
|
+
if (!target)
|
|
222
|
+
return
|
|
223
|
+
|
|
224
|
+
const id = target.id
|
|
225
|
+
const list = orders.value as Order[]
|
|
226
|
+
orders.value = list.filter(o => o.id !== id)
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
const ok = await deleteOrder(id)
|
|
230
|
+
if (ok) {
|
|
231
|
+
closeDeleteModal()
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
orders.value = [...orders.value, target]
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
orders.value = [...orders.value, target]
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
onMount(async () => {
|
|
243
|
+
await fetchOrders()
|
|
244
|
+
})
|
|
245
|
+
</script>
|
|
246
|
+
|
|
247
|
+
@endsection
|