diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f3f77c3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,14 @@ +.git +node_modules +vendor +public/build +public/hot +public/storage +storage/logs/* +storage/framework/cache/* +storage/framework/sessions/* +storage/framework/views/* +.env +.env.* +!.env.example +graphify-out diff --git a/app/Providers/HorizonServiceProvider.php b/app/Providers/HorizonServiceProvider.php new file mode 100644 index 0000000..bfe19ed --- /dev/null +++ b/app/Providers/HorizonServiceProvider.php @@ -0,0 +1,17 @@ +level === UserEnum::Admin->value; + }); + } +} diff --git a/bootstrap/providers.php b/bootstrap/providers.php index 38b258d..4e3b440 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -2,4 +2,5 @@ return [ App\Providers\AppServiceProvider::class, + App\Providers\HorizonServiceProvider::class, ]; diff --git a/composer.json b/composer.json index 23729a1..9d95de0 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ "hekmatinasser/verta": "^8.5", "inertiajs/inertia-laravel": "^2.0", "laravel/framework": "^12.0", + "laravel/horizon": "^5.49", "laravel/tinker": "^2.10.1", "maatwebsite/excel": "^3.1", "spatie/laravel-permission": "^6.17", diff --git a/composer.lock b/composer.lock index 94a14ef..36dfccb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7aaff316edab008067e96caa26142a24", + "content-hash": "2f1cb367cfe5d850b1483797ac0810ee", "packages": [ { "name": "brick/math", @@ -1741,6 +1741,86 @@ }, "time": "2025-04-08T19:58:59+00:00" }, + { + "name": "laravel/horizon", + "version": "v5.49.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/horizon.git", + "reference": "6dce8a97b426be5305adad537ad4b6a99de61b31" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/horizon/zipball/6dce8a97b426be5305adad537ad4b6a99de61b31", + "reference": "6dce8a97b426be5305adad537ad4b6a99de61b31", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcntl": "*", + "ext-posix": "*", + "illuminate/contracts": "^9.21|^10.0|^11.0|^12.0|^13.0", + "illuminate/queue": "^9.21|^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^9.21|^10.0|^11.0|^12.0|^13.0", + "laravel/sentinel": "^1.0", + "nesbot/carbon": "^2.17|^3.0", + "php": "^8.0", + "ramsey/uuid": "^4.0", + "symfony/console": "^6.0|^7.0|^8.0", + "symfony/error-handler": "^6.0|^7.0|^8.0", + "symfony/polyfill-php83": "^1.28", + "symfony/process": "^6.0|^7.0|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^7.56|^8.37|^9.16|^10.9|^11.0", + "phpstan/phpstan": "^1.10|^2.0", + "predis/predis": "^1.1|^2.0|^3.0" + }, + "suggest": { + "ext-redis": "Required to use the Redis PHP driver.", + "predis/predis": "Required when not using the Redis PHP driver (^1.1|^2.0|^3.0)." + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Horizon": "Laravel\\Horizon\\Horizon" + }, + "providers": [ + "Laravel\\Horizon\\HorizonServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Horizon\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Dashboard and code-driven configuration for Laravel queues.", + "keywords": [ + "laravel", + "queue" + ], + "support": { + "issues": "https://github.com/laravel/horizon/issues", + "source": "https://github.com/laravel/horizon/tree/v5.49.0" + }, + "time": "2026-09-07T12:00:27+00:00" + }, { "name": "laravel/prompts", "version": "v0.3.5", @@ -1800,6 +1880,62 @@ }, "time": "2025-02-11T13:34:40+00:00" }, + { + "name": "laravel/sentinel", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/sentinel.git", + "reference": "972d9885d9d14312a118e9565c4e6ecc5e751ea1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sentinel/zipball/972d9885d9d14312a118e9565c4e6ecc5e751ea1", + "reference": "972d9885d9d14312a118e9565c4e6ecc5e751ea1", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/container": "^8.37|^9.0|^10.0|^11.0|^12.0|^13.0", + "php": "^8.0" + }, + "require-dev": { + "laravel/pint": "^1.27", + "orchestra/testbench": "^6.47.1|^7.56|^8.37|^9.16|^10.9|^11.0", + "phpstan/phpstan": "^2.1.33" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sentinel\\SentinelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sentinel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mior Muhammad Zaki", + "email": "mior@laravel.com" + } + ], + "support": { + "source": "https://github.com/laravel/sentinel/tree/v1.1.0" + }, + "time": "2026-03-24T14:03:38+00:00" + }, { "name": "laravel/serializable-closure", "version": "v2.0.4", diff --git a/config/horizon.php b/config/horizon.php new file mode 100644 index 0000000..a9df214 --- /dev/null +++ b/config/horizon.php @@ -0,0 +1,254 @@ + env('HORIZON_NAME'), + + /* + |-------------------------------------------------------------------------- + | Horizon Domain + |-------------------------------------------------------------------------- + | + | This is the subdomain where Horizon will be accessible from. If this + | setting is null, Horizon will reside under the same domain as the + | application. Otherwise, this value will serve as the subdomain. + | + */ + + 'domain' => env('HORIZON_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | Horizon Path + |-------------------------------------------------------------------------- + | + | This is the URI path where Horizon will be accessible from. Feel free + | to change this path to anything you like. Note that the URI will not + | affect the paths of its internal API that aren't exposed to users. + | + */ + + 'path' => env('HORIZON_PATH', 'admin/horizon'), + + /* + |-------------------------------------------------------------------------- + | Horizon Redis Connection + |-------------------------------------------------------------------------- + | + | This is the name of the Redis connection where Horizon will store the + | meta information required for it to function. It includes the list + | of supervisors, failed jobs, job metrics, and other information. + | + */ + + 'use' => 'default', + + /* + |-------------------------------------------------------------------------- + | Horizon Redis Prefix + |-------------------------------------------------------------------------- + | + | This prefix will be used when storing all Horizon data in Redis. You + | may modify the prefix when you are running multiple installations + | of Horizon on the same server so that they don't have problems. + | + */ + + 'prefix' => env( + 'HORIZON_PREFIX', + Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' + ), + + /* + |-------------------------------------------------------------------------- + | Horizon Route Middleware + |-------------------------------------------------------------------------- + | + | These middleware will get attached onto each Horizon route, giving you + | the chance to add your own middleware to this list or change any of + | the existing middleware. Or, you can simply stick with this list. + | + */ + + 'middleware' => ['web', 'admin.access'], + + /* + |-------------------------------------------------------------------------- + | Queue Wait Time Thresholds + |-------------------------------------------------------------------------- + | + | This option allows you to configure when the LongWaitDetected event + | will be fired. Every connection / queue combination may have its + | own, unique threshold (in seconds) before this event is fired. + | + */ + + 'waits' => [ + 'redis:default' => 60, + ], + + /* + |-------------------------------------------------------------------------- + | Job Trimming Times + |-------------------------------------------------------------------------- + | + | Here you can configure for how long (in minutes) you desire Horizon to + | persist the recent and failed jobs. Typically, recent jobs are kept + | for one hour while all failed jobs are stored for an entire week. + | + */ + + 'trim' => [ + 'recent' => 60, + 'pending' => 60, + 'completed' => 60, + 'recent_failed' => 10080, + 'failed' => 10080, + 'monitored' => 10080, + ], + + /* + |-------------------------------------------------------------------------- + | Silenced Jobs + |-------------------------------------------------------------------------- + | + | Silencing a job will instruct Horizon to not place the job in the list + | of completed jobs within the Horizon dashboard. This setting may be + | used to fully remove any noisy jobs from the completed jobs list. + | + */ + + 'silenced' => [ + // App\Jobs\ExampleJob::class, + ], + + 'silenced_tags' => [ + // 'notifications', + ], + + /* + |-------------------------------------------------------------------------- + | Metrics + |-------------------------------------------------------------------------- + | + | Here you can configure how many snapshots should be kept to display in + | the metrics graph. This will get used in combination with Horizon's + | `horizon:snapshot` schedule to define how long to retain metrics. + | + */ + + 'metrics' => [ + 'trim_snapshots' => [ + 'job' => 24, + 'queue' => 24, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Fast Termination + |-------------------------------------------------------------------------- + | + | When this option is enabled, Horizon's "terminate" command will not + | wait on all of the workers to terminate unless the --wait option + | is provided. Fast termination can shorten deployment delay by + | allowing a new instance of Horizon to start while the last + | instance will continue to terminate each of its workers. + | + */ + + 'fast_termination' => false, + + /* + |-------------------------------------------------------------------------- + | Memory Limit (MB) + |-------------------------------------------------------------------------- + | + | This value describes the maximum amount of memory the Horizon master + | supervisor may consume before it is terminated and restarted. For + | configuring these limits on your workers, see the next section. + | + */ + + 'memory_limit' => 64, + + /* + |-------------------------------------------------------------------------- + | Queue Worker Configuration + |-------------------------------------------------------------------------- + | + | Here you may define the queue worker settings used by your application + | in all environments. These supervisors and settings handle all your + | queued jobs and will be provisioned by Horizon during deployment. + | + */ + + 'defaults' => [ + 'supervisor-1' => [ + 'connection' => 'redis', + 'queue' => ['default'], + 'balance' => 'auto', + 'autoScalingStrategy' => 'time', + 'maxProcesses' => 1, + 'maxTime' => 0, + 'maxJobs' => 0, + 'memory' => 128, + 'tries' => 1, + 'timeout' => 60, + 'nice' => 0, + ], + ], + + 'environments' => [ + 'production' => [ + 'supervisor-1' => [ + 'maxProcesses' => 10, + 'balanceMaxShift' => 1, + 'balanceCooldown' => 3, + ], + ], + + 'local' => [ + 'supervisor-1' => [ + 'maxProcesses' => 3, + ], + ], + ], + + /* + |-------------------------------------------------------------------------- + | File Watcher Configuration + |-------------------------------------------------------------------------- + | + | The following list of directories and files will be watched when using + | the `horizon:listen` command. Whenever any directories or files are + | changed, Horizon will automatically restart to apply all changes. + | + */ + + 'watch' => [ + 'app', + 'bootstrap', + 'config/**/*.php', + 'database/**/*.php', + 'public/**/*.php', + 'resources/**/*.php', + 'routes', + 'composer.lock', + 'composer.json', + '.env', + ], +]; diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..0ddfbce --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,87 @@ +x-app: &app + build: + context: . + dockerfile: docker/php/Dockerfile + image: radical-app + volumes: + - .:/var/www/html + environment: &app-env + DB_CONNECTION: pgsql + DB_HOST: postgres + DB_PORT: 5432 + DB_DATABASE: ${DB_DATABASE:-radical} + DB_USERNAME: ${DB_USERNAME:-radical} + DB_PASSWORD: ${DB_PASSWORD:-secret} + REDIS_HOST: redis + REDIS_PORT: 6379 + QUEUE_CONNECTION: redis + CACHE_STORE: redis + SESSION_DRIVER: redis + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + +services: + app: + <<: *app + + horizon: + <<: *app + command: php artisan horizon + restart: unless-stopped + depends_on: + app: + condition: service_started + + nginx: + image: nginx:1.27-alpine + ports: + - "${APP_PORT:-8000}:80" + volumes: + - .:/var/www/html:ro + - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + - app + + node: + image: node:24-alpine + working_dir: /var/www/html + command: sh -c "npm install && npm run dev -- --host 0.0.0.0" + volumes: + - .:/var/www/html + - node-modules:/var/www/html/node_modules + ports: + - "5173:5173" + + postgres: + image: postgres:16-alpine + environment: + POSTGRES_DB: ${DB_DATABASE:-radical} + POSTGRES_USER: ${DB_USERNAME:-radical} + POSTGRES_PASSWORD: ${DB_PASSWORD:-secret} + ports: + - "${DB_FORWARD_PORT:-5432}:5432" + volumes: + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USERNAME:-radical} -d ${DB_DATABASE:-radical}"] + interval: 5s + timeout: 5s + retries: 10 + + redis: + image: redis:7-alpine + volumes: + - redis-data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 10 + +volumes: + postgres-data: + redis-data: + node-modules: diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf new file mode 100644 index 0000000..c2b38dc --- /dev/null +++ b/docker/nginx/default.conf @@ -0,0 +1,22 @@ +server { + listen 80; + server_name _; + root /var/www/html/public; + index index.php; + client_max_body_size 64M; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass app:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\.(?!well-known).* { + deny all; + } +} diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile new file mode 100644 index 0000000..bf87533 --- /dev/null +++ b/docker/php/Dockerfile @@ -0,0 +1,19 @@ +FROM php:8.4-fpm-alpine + +RUN apk add --no-cache \ + bash curl git postgresql-dev libzip-dev icu-dev libpng-dev libjpeg-turbo-dev freetype-dev oniguruma-dev linux-headers $PHPIZE_DEPS \ + && docker-php-ext-configure gd --with-freetype --with-jpeg \ + && docker-php-ext-install -j"$(nproc)" pdo_pgsql pgsql gd zip intl bcmath exif pcntl opcache \ + && pecl install redis \ + && docker-php-ext-enable redis \ + && apk del $PHPIZE_DEPS + +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer +COPY docker/php/php.ini /usr/local/etc/php/conf.d/app.ini +COPY docker/php/entrypoint.sh /usr/local/bin/entrypoint +RUN chmod +x /usr/local/bin/entrypoint + +WORKDIR /var/www/html + +ENTRYPOINT ["entrypoint"] +CMD ["php-fpm"] diff --git a/docker/php/entrypoint.sh b/docker/php/entrypoint.sh new file mode 100644 index 0000000..eec1e5d --- /dev/null +++ b/docker/php/entrypoint.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e + +if [ "$1" = "php-fpm" ]; then + [ -d vendor ] || composer install --no-interaction --prefer-dist + [ -f .env ] || cp .env.example .env + grep -q '^APP_KEY=.\+' .env || php artisan key:generate --no-interaction + + until php -r "new PDO('pgsql:host=${DB_HOST};port=${DB_PORT};dbname=${DB_DATABASE}', '${DB_USERNAME}', '${DB_PASSWORD}');" >/dev/null 2>&1; do + echo "waiting for postgres..." + sleep 2 + done + + php artisan migrate --force --no-interaction + php artisan storage:link --no-interaction || true + chown -R www-data:www-data storage bootstrap/cache +fi + +exec "$@" diff --git a/docker/php/php.ini b/docker/php/php.ini new file mode 100644 index 0000000..4299df4 --- /dev/null +++ b/docker/php/php.ini @@ -0,0 +1,6 @@ +upload_max_filesize = 64M +post_max_size = 64M +memory_limit = 512M +max_execution_time = 120 +opcache.enable = 1 +opcache.validate_timestamps = 1 diff --git a/public/images/landing-hero.jpg b/public/images/landing-hero.jpg new file mode 100644 index 0000000..d94c587 Binary files /dev/null and b/public/images/landing-hero.jpg differ diff --git a/resources/css/Client/landing.css b/resources/css/Client/landing.css new file mode 100644 index 0000000..3f030a5 --- /dev/null +++ b/resources/css/Client/landing.css @@ -0,0 +1,195 @@ +@keyframes landing-float { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-12px); } +} + +@keyframes landing-scan { + 0% { top: 0; opacity: 0; } + 8% { opacity: 1; } + 92% { opacity: 1; } + 100% { top: 100%; opacity: 0; } +} + +@keyframes landing-pulse { + 0% { transform: scale(0.9); opacity: 0.8; } + 100% { transform: scale(1.7); opacity: 0; } +} + +@keyframes landing-blob { + 0%, 100% { border-radius: 42% 58% 60% 40% / 45% 40% 60% 55%; } + 50% { border-radius: 58% 42% 40% 60% / 55% 60% 40% 45%; } +} + +@keyframes landing-kenburns { + from { transform: scale(1); } + to { transform: scale(1.08); } +} + +@keyframes landing-spin { + to { transform: rotate(360deg); } +} + +@keyframes landing-marquee { + from { transform: translateX(0); } + to { transform: translateX(50%); } +} + +@keyframes landing-draw { + to { stroke-dashoffset: 0; } +} + +@keyframes landing-timeline { + 0%, 12% { opacity: 0.35; } + 18%, 100% { opacity: 1; } +} + +@keyframes landing-toggle { + 0%, 40% { transform: translateX(0); } + 50%, 90% { transform: translateX(-100%); } + 100% { transform: translateX(0); } +} + +@keyframes landing-bubble { + 0% { opacity: 0; transform: translateY(12px) scale(0.96); } + 100% { opacity: 1; transform: translateY(0) scale(1); } +} + +.landing-page { + background-image: radial-gradient(rgba(128, 14, 19, 0.08) 1px, transparent 1px); + background-size: 28px 28px; +} + +.landing-grid { + background-image: linear-gradient(#DEE3EB 1px, transparent 1px), linear-gradient(90deg, #DEE3EB 1px, transparent 1px); + background-size: 32px 32px; +} + +.landing-float { + animation: landing-float 6s ease-in-out infinite; +} + +.landing-float--delay { + animation-delay: 1.6s; +} + +.landing-scan { + animation: landing-scan 3.6s ease-in-out infinite; +} + +.landing-pulse::after { + content: ''; + @apply absolute inset-0 rounded-full border-2 border-complement-700; + animation: landing-pulse 2.2s ease-out infinite; +} + +.landing-blob { + animation: landing-blob 14s ease-in-out infinite; +} + +.landing-kenburns { + animation: landing-kenburns 24s ease-out forwards; +} + +.landing-spin svg { + animation: landing-spin 18s linear infinite; +} + +.landing-marquee { + animation: landing-marquee 32s linear infinite; +} + +.landing-marquee:hover { + animation-play-state: paused; +} + +.landing-underline path { + stroke-dasharray: 320; + stroke-dashoffset: 320; + animation: landing-draw 1.1s ease-out 0.5s forwards; +} + +.landing-timeline-step { + animation: landing-timeline 8s ease-in-out infinite; +} + +.landing-timeline-step:nth-child(2) { animation-delay: 1.6s; } +.landing-timeline-step:nth-child(3) { animation-delay: 3.2s; } +.landing-timeline-step:nth-child(4) { animation-delay: 4.8s; } + +.landing-toggle-thumb { + animation: landing-toggle 6s ease-in-out infinite; +} + +.landing-bubble { + opacity: 0; + animation: landing-bubble 0.5s ease-out forwards; +} + +.landing-bubble:nth-child(2) { animation-delay: 0.6s; } +.landing-bubble:nth-child(3) { animation-delay: 1.2s; } + +.landing-reveal { + @apply opacity-0 translate-y-8 transition-all duration-700 ease-out; +} + +.landing-reveal.is-visible { + @apply opacity-100 translate-y-0; +} + +.landing-reveal--1 { transition-delay: 100ms; } +.landing-reveal--2 { transition-delay: 200ms; } +.landing-reveal--3 { transition-delay: 300ms; } +.landing-reveal--4 { transition-delay: 400ms; } +.landing-reveal--5 { transition-delay: 500ms; } + +.landing-timeline-line { + @apply origin-top scale-y-0 transition-transform duration-1000 ease-out; +} + +.landing-reveal.is-visible .landing-timeline-line { + @apply scale-y-100; +} + +.landing-faq summary::-webkit-details-marker { + display: none; +} + +.landing-faq[open] .landing-faq-icon { + @apply rotate-45; +} + +html:has(.landing-page) { + scroll-behavior: smooth; +} + +@media (prefers-reduced-motion: reduce) { + .landing-float, + .landing-scan, + .landing-kenburns, + .landing-spin svg, + .landing-blob, + .landing-marquee, + .landing-timeline-step, + .landing-toggle-thumb, + .landing-pulse::after { + animation: none; + } + + .landing-underline path { + animation: none; + stroke-dashoffset: 0; + } + + .landing-bubble { + animation: none; + opacity: 1; + } + + .landing-reveal { + @apply opacity-100 translate-y-0 transition-none; + } + + .landing-timeline-line { + @apply scale-y-100 transition-none; + } +} diff --git a/resources/css/Client/ui/button.css b/resources/css/Client/ui/button.css index ad624ca..2993ac7 100644 --- a/resources/css/Client/ui/button.css +++ b/resources/css/Client/ui/button.css @@ -23,19 +23,19 @@ } .ui-button--dominant.p-button.p-button-outlined { - @apply bg-transparent text-dominant-500 border-dominant-500; + @apply !bg-transparent !text-dominant-500 border-dominant-500; } .ui-button--dominant.p-button.p-button-outlined:hover { - @apply bg-dominant-500 text-white; + @apply !bg-dominant-500 !text-white; } .ui-button--dominant.p-button.p-button-text { - @apply bg-transparent text-dominant-500 border-transparent; + @apply !bg-transparent !text-dominant-500 !border-transparent; } .ui-button--dominant.p-button.p-button-text:hover { - background-color: rgba(128, 14, 19, 0.1); + background-color: rgba(128, 14, 19, 0.1) !important; } diff --git a/resources/css/Client/ui/fast-request.css b/resources/css/Client/ui/fast-request.css index 0f8ff8d..e088a66 100644 --- a/resources/css/Client/ui/fast-request.css +++ b/resources/css/Client/ui/fast-request.css @@ -81,3 +81,10 @@ background: #576989 !important; } + +@media (max-width: 767px) { + .fast-request-dialog { + width: calc(100vw - 1.5rem) !important; + max-width: 688px; + } +} diff --git a/resources/css/Client/ui/table.css b/resources/css/Client/ui/table.css index e368777..8b2391f 100644 --- a/resources/css/Client/ui/table.css +++ b/resources/css/Client/ui/table.css @@ -48,3 +48,13 @@ .p-datatable-tbody > tr > td{ @apply !border-0 } + +.table-generic { + @apply w-full min-w-0; +} +.table-generic-scroll { + @apply w-full overflow-x-auto; +} +.table-generic-scroll .p-datatable-table { + @apply min-w-full; +} diff --git a/resources/css/client.css b/resources/css/client.css index c441f8d..3dd2b0c 100644 --- a/resources/css/client.css +++ b/resources/css/client.css @@ -14,6 +14,7 @@ @import "tailwindcss"; @import "./Client/sidebar/sidebar.css"; @import "./Client/page-transitions.css"; +@import "./Client/landing.css"; @config "../../Client-tailwind.config.js"; diff --git a/resources/js/Client/Pages/Dashboard/Dashboard.vue b/resources/js/Client/Pages/Dashboard/Dashboard.vue index 164b53e..3783c2d 100644 --- a/resources/js/Client/Pages/Dashboard/Dashboard.vue +++ b/resources/js/Client/Pages/Dashboard/Dashboard.vue @@ -55,7 +55,7 @@ defineProps({

فقط چند قدم ساده برای ثبت درخواست کافیه.

-
+
-import { Link } from '@inertiajs/inertia-vue3' +import { ref } from 'vue' import { usePage } from '@inertiajs/inertia-vue3' +import { useScrollReveal } from '../composables/useScrollReveal' +import LandingHeader from '../components/landing/LandingHeader.vue' +import LandingHero from '../components/landing/LandingHero.vue' +import LandingMarquee from '../components/landing/LandingMarquee.vue' +import LandingSteps from '../components/landing/LandingSteps.vue' +import LandingFeatures from '../components/landing/LandingFeatures.vue' +import LandingModalities from '../components/landing/LandingModalities.vue' +import LandingComparison from '../components/landing/LandingComparison.vue' +import LandingFaq from '../components/landing/LandingFaq.vue' +import LandingCta from '../components/landing/LandingCta.vue' +import LandingFooter from '../components/landing/LandingFooter.vue' -const {url ,props} = usePage(); -const user = props.value.auth.User || null; +const { props } = usePage() +const user = props.value.auth.User || null +const page = ref(null) + +useScrollReveal(page) - diff --git a/resources/js/Client/components/dashboard/RequestCard.vue b/resources/js/Client/components/dashboard/RequestCard.vue index a081f91..afaf1dc 100644 --- a/resources/js/Client/components/dashboard/RequestCard.vue +++ b/resources/js/Client/components/dashboard/RequestCard.vue @@ -65,9 +65,9 @@ props.selectable && 'cursor-pointer', fastRequestStore.requestType === props.value ? 'border-[#576989] border-2': 'border-[#DEE3EB]' ]"> - +
-

{{ title }}

+

{{ title }}

diff --git a/resources/js/Client/components/dashboard/fastRequest/RequestCase.vue b/resources/js/Client/components/dashboard/fastRequest/RequestCase.vue index 5fbe4e5..8315c0c 100644 --- a/resources/js/Client/components/dashboard/fastRequest/RequestCase.vue +++ b/resources/js/Client/components/dashboard/fastRequest/RequestCase.vue @@ -32,7 +32,7 @@ const showChooseArchive = () => {

-
+

جزئیات درخواست و اطلاعات مورد نیاز را با دقت و حوصله وارد نمایید.

-
+