[
  {
    "path": ".dockerignore",
    "content": "# Git\n.git\n.gitignore\n.gitattributes\n\n# Environment\n.env\n.env.*\n!.env.example\n\n# IDE\n.idea\n.vscode\n*.sublime*\n\n# OS\n.DS_Store\nThumbs.db\n\n# Build artifacts\nnode_modules\nnpm-debug.log\nyarn-error.log\n\n# Laravel\n/vendor\n/storage/*.key\n/public/hot\n/public/storage\n/public/build\n\n# Testing\n/coverage\n/.phpunit.result.cache\n\n# Documentation\nREADME.md\nCHANGELOG.md\n/doc\n\n# Docker\ndocker-compose*.yml\nDockerfile\n.dockerignore\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 4\nindent_style = space\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[*.{yml,yaml}]\nindent_size = 2\n\n[docker-compose.yml]\nindent_size = 4\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n\n*.blade.php diff=html\n*.css diff=css\n*.html diff=html\n*.md diff=markdown\n*.php diff=php\n\n/.github export-ignore\nCHANGELOG.md export-ignore\n.styleci.yml export-ignore\n"
  },
  {
    "path": ".github/workflows/laravel.yml",
    "content": "name: Laravel\n\non:\n  push:\n    branches: [ \"main\" ]\n  pull_request:\n    branches: [ \"main\" ]\n\njobs:\n  laravel-tests:\n\n    runs-on: ubuntu-latest\n\n    services:\n      mysql:\n        image: mysql:latest\n        env:\n          MYSQL_DATABASE: posts-test\n          MYSQL_ROOT_PASSWORD: 123456\n        ports:\n          - 3306:3306\n        options: --health-cmd=\"mysqladmin ping\"\n\n    steps:\n    - uses: shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e\n      with:\n        php-version: '8.2'\n    - uses: actions/checkout@v4\n    - name: Copy .env\n      run: php -r \"file_exists('.env') || copy('.env.example', '.env');\"\n    - name: Install Dependencies\n      run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist\n    - name: Generate key\n      run: php artisan key:generate\n    - name: Directory Permissions\n      run: chmod -R 777 storage bootstrap/cache\n    - name: phpstan\n      run: ./vendor/bin/phpstan analyse --memory-limit=1G\n    - name: Create Database\n      run: |\n        mkdir -p database\n        touch database/database.sqlite\n    - name: Execute tests (Unit and Feature tests) via PHPUnit/Pest\n      env:\n        DB_CONNECTION: sqlite\n        DB_DATABASE: database/database.sqlite\n      run: php artisan test\n"
  },
  {
    "path": ".gitignore",
    "content": "/.phpunit.cache\n/node_modules\n/public/build\n/public/hot\n/public/storage\n/storage/*.key\n/vendor\n.env\n.env.backup\n.env.production\n.phpunit.result.cache\nHomestead.json\nHomestead.yaml\nauth.json\nnpm-debug.log\nyarn-error.log\n/.fleet\n/.idea\n/.vscode\n/.composer\n/.npm\n/.config\n.DS_Store"
  },
  {
    "path": ".styleci.yml",
    "content": "php:\n  preset: laravel\n  disabled:\n    - no_unused_imports\n  finder:\n    not-name:\n      - index.php\njs: true\ncss: true\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Release Notes\n\n## [Unreleased](https://github.com/laravel/laravel/compare/v11.0.7...11.x)\n\n## [v11.0.7](https://github.com/laravel/laravel/compare/v11.0.6...v11.0.7) - 2024-05-03\n\n* Remove obsolete driver option by [@u01jmg3](https://github.com/u01jmg3) in https://github.com/laravel/laravel/pull/6395\n\n## [v11.0.6](https://github.com/laravel/laravel/compare/v11.0.5...v11.0.6) - 2024-04-09\n\n* Fix PHPUnit constraint by [@szepeviktor](https://github.com/szepeviktor) in https://github.com/laravel/laravel/pull/6389\n* [11.x] Add missing roundrobin transport driver config by [@u01jmg3](https://github.com/u01jmg3) in https://github.com/laravel/laravel/pull/6392\n\n## [v11.0.5](https://github.com/laravel/laravel/compare/v11.0.4...v11.0.5) - 2024-03-26\n\n* [11.x] Use PHPUnit v11 by [@philbates35](https://github.com/philbates35) in https://github.com/laravel/laravel/pull/6385\n\n## [v11.0.4](https://github.com/laravel/laravel/compare/v11.0.3...v11.0.4) - 2024-03-15\n\n* [11.x] Removed useless null parameter for env helper (cache.php) by [@siarheipashkevich](https://github.com/siarheipashkevich) in https://github.com/laravel/laravel/pull/6374\n* [11.x] Removed useless null parameter for env helper (queue.php) by [@siarheipashkevich](https://github.com/siarheipashkevich) in https://github.com/laravel/laravel/pull/6373\n* [11.x] Fix retry_after to be an integer by [@driesvints](https://github.com/driesvints) in https://github.com/laravel/laravel/pull/6377\n* [11.x] Fix on hover animation and ring by [@michaelnabil230](https://github.com/michaelnabil230) in https://github.com/laravel/laravel/pull/6376\n\n## [v11.0.3](https://github.com/laravel/laravel/compare/v11.0.2...v11.0.3) - 2024-03-14\n\n* [11.x] Revert collation change by [@driesvints](https://github.com/driesvints) in https://github.com/laravel/laravel/pull/6372\n\n## [v11.0.2](https://github.com/laravel/laravel/compare/v11.0.1...v11.0.2) - 2024-03-13\n\n* [11.x] Remove branch alias from composer.json by [@zepfietje](https://github.com/zepfietje) in https://github.com/laravel/laravel/pull/6366\n* [11.x] Fixes typo in welcome page by [@jrd-lewis](https://github.com/jrd-lewis) in https://github.com/laravel/laravel/pull/6363\n* change mariadb default by [@taylorotwell](https://github.com/taylorotwell) in https://github.com/laravel/laravel/commit/79969c99c6456a6d6edfbe78d241575fe1f65594\n\n## [v11.0.1](https://github.com/laravel/laravel/compare/v11.0.0...v11.0.1) - 2024-03-12\n\n* [11.x] Fixes SQLite driver missing by [@nunomaduro](https://github.com/nunomaduro) in https://github.com/laravel/laravel/pull/6361\n\n## [v11.0.0 (2023-02-17)](https://github.com/laravel/laravel/compare/v10.3.2...v11.0.0)\n\nLaravel 11 includes a variety of changes to the application skeleton. Please consult the diff to see what's new.\n"
  },
  {
    "path": "DOCKER.md",
    "content": "# Docker Setup for Examinee Application\n\n## Quick Start\n\n### 1. Build and start the containers\n```bash\ndocker compose up -d\n```\n\n### 2. Install dependencies and build assets\n```bash\n# Install PHP dependencies (if not already done)\ndocker compose exec app composer install\n\n# Install Node dependencies and build assets\ndocker compose run --rm node sh -c \"npm install && npm run build\"\n\n# Or use the build profile\ndocker compose --profile build up node\n```\n\n### 3. Setup the application\n```bash\n# Copy environment file\ncp .env.example .env\n\n# Generate application key\ndocker compose exec app php artisan key:generate\n\n# Run migrations\ndocker compose exec app php artisan migrate\n\n# Run seeders (optional)\ndocker compose exec app php artisan db:seed\n\n# Create storage link\ndocker compose exec app php artisan storage:link\n\n# Clear and cache config\ndocker compose exec app php artisan config:cache\ndocker compose exec app php artisan route:cache\ndocker compose exec app php artisan view:cache\n```\n\n### 4. Access the application\n- **Application**: http://localhost:8000\n- **Database**: localhost:3307\n  - Database: examinee_db\n  - User: examinee_user\n  - Password: examinee_password\n  - Root Password: root_password\n- **Redis**: localhost:6380\n\n## Services\n\n- **app**: PHP 8.2-FPM application container\n- **nginx**: Nginx web server (port 8000)\n- **db**: MySQL 8.0 database (port 3307)\n- **redis**: Redis cache and queue backend (port 6380)\n- **queue**: Laravel queue worker\n- **node**: Node.js for asset compilation (run on-demand)\n\n## Common Commands\n\n### Container Management\n```bash\n# Start containers\ndocker compose up -d\n\n# Stop containers\ndocker compose down\n\n# View logs\ndocker compose logs -f\n\n# View specific service logs\ndocker compose logs -f app\ndocker compose logs -f nginx\ndocker compose logs -f queue\n\n# Restart a service\ndocker compose restart app\n```\n\n### Laravel Commands\n```bash\n# Run artisan commands\ndocker compose exec app php artisan [command]\n\n# Access Laravel tinker\ndocker compose exec app php artisan tinker\n\n# Clear caches\ndocker compose exec app php artisan cache:clear\ndocker compose exec app php artisan config:clear\ndocker compose exec app php artisan route:clear\ndocker compose exec app php artisan view:clear\n\n# Run migrations\ndocker compose exec app php artisan migrate\ndocker compose exec app php artisan migrate:fresh --seed\n```\n\n### Asset Building\n```bash\n# Development build\ndocker compose run --rm node npm run dev\n\n# Production build\ndocker compose run --rm node npm run build\n\n# Watch mode (for development)\ndocker compose run --rm node npm run watch\n```\n\n### Database Access\n```bash\n# Access MySQL CLI\ndocker compose exec db mysql -u examinee_user -pexaminee_password examinee_db\n\n# Import database\ndocker compose exec -T db mysql -u examinee_user -pexaminee_password examinee_db < backup.sql\n\n# Export database\ndocker compose exec db mysqldump -u examinee_user -pexaminee_password examinee_db > backup.sql\n```\n\n### Queue Management\n```bash\n# View queue logs\ndocker compose logs -f queue\n\n# Restart queue worker\ndocker compose restart queue\n\n# Run queue manually (for testing)\ndocker compose exec app php artisan queue:work\n```\n\n### Shell Access\n```bash\n# Access app container shell\ndocker compose exec app bash\n\n# Access as root\ndocker compose exec -u root app bash\n```\n\n## Environment Variables\n\nUpdate your `.env` file with these Docker settings:\n\n```env\nDB_CONNECTION=mysql\nDB_HOST=db\nDB_PORT=3306\nDB_DATABASE=examinee_db\nDB_USERNAME=examinee_user\nDB_PASSWORD=examinee_password\n\nREDIS_HOST=redis\nREDIS_PORT=6379\n\nCACHE_DRIVER=redis\nSESSION_DRIVER=redis\nQUEUE_CONNECTION=redis\n```\n\n## Troubleshooting\n\n### Permission Issues\n```bash\n# Fix storage permissions\ndocker compose exec -u root app chown -R www-data:www-data /var/www/html/storage\ndocker compose exec -u root app chmod -R 755 /var/www/html/storage\n```\n\n### Reset Everything\n```bash\n# Stop and remove containers, volumes\ndocker compose down -v\n\n# Rebuild from scratch\ndocker compose build --no-cache\ndocker compose up -d\n```\n\n### Database Connection Issues\n- Ensure the `db` service is running: `docker compose ps`\n- Check database logs: `docker compose logs db`\n- Verify credentials in `.env` match `docker-compose.yml`\n\n## Production Considerations\n\n1. **Change default passwords** in `docker-compose.yml`\n2. **Use environment-specific files**: Create `docker-compose.prod.yml`\n3. **Enable HTTPS**: Add SSL certificates and update nginx config\n4. **Set proper APP_ENV**: Change to `production` in `.env`\n5. **Disable debug mode**: Set `APP_DEBUG=false`\n6. **Use proper storage**: Mount volumes for persistent data\n7. **Implement backups**: Regular database and file backups\n8. **Monitoring**: Add logging and monitoring solutions\n\n## Development vs Production\n\nFor development with hot reload:\n```bash\n# Run Vite dev server on host machine\nnpm install\nnpm run dev\n\n# Access via http://localhost:5173\n```\n\nUpdate `.env`:\n```env\nVITE_DEV_SERVER_URL=http://localhost:5173\n```\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM php:8.3-fpm\n\n# Set working directory\nWORKDIR /var/www/html\n\n# Install system dependencies\nRUN apt-get update && apt-get install -y \\\n    git \\\n    curl \\\n    libpng-dev \\\n    libonig-dev \\\n    libxml2-dev \\\n    libzip-dev \\\n    libpq-dev \\\n    zip \\\n    unzip \\\n    libfreetype6-dev \\\n    libjpeg62-turbo-dev \\\n    libwebp-dev \\\n    && docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \\\n    && docker-php-ext-install pdo_mysql pdo_pgsql mbstring exif pcntl bcmath gd zip\n\n# Install Redis extension\nRUN pecl install redis && docker-php-ext-enable redis\n\n# Clear cache\nRUN apt-get clean && rm -rf /var/lib/apt/lists/*\n\n# Install Composer\nCOPY --from=composer:latest /usr/bin/composer /usr/bin/composer\n\n# Copy application files\nCOPY . /var/www/html\n\n# Copy php.ini configuration\nRUN cp \"$PHP_INI_DIR/php.ini-production\" \"$PHP_INI_DIR/php.ini\" \\\n    && echo \"upload_max_filesize = 50M\" >> \"$PHP_INI_DIR/php.ini\" \\\n    && echo \"post_max_size = 50M\" >> \"$PHP_INI_DIR/php.ini\" \\\n    && echo \"memory_limit = 512M\" >> \"$PHP_INI_DIR/php.ini\"\n\n# Expose port 9000 for PHP-FPM\nEXPOSE 9000\n\nCMD [\"php-fpm\"]\n"
  },
  {
    "path": "Makefile",
    "content": ".PHONY: help build up down restart logs shell composer artisan migrate fresh test clean\n\n# Colors for output\nBLUE=\\033[0;34m\nGREEN=\\033[0;32m\nRED=\\033[0;31m\nNC=\\033[0m # No Color\n\nhelp: ## Show this help message\n\t@echo '${BLUE}Available commands:${NC}'\n\t@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = \":.*?## \"}; {printf \"  ${GREEN}%-15s${NC} %s\\n\", $$1, $$2}'\n\nbuild: ## Build Docker containers\n\t@echo \"${BLUE}Building Docker containers...${NC}\"\n\tdocker compose build\n\nup: ## Start all containers\n\t@echo \"${BLUE}Starting containers...${NC}\"\n\tdocker compose up -d\n\t@echo \"${GREEN}Containers started! Access the app at http://localhost:8000${NC}\"\n\ndown: ## Stop all containers\n\t@echo \"${BLUE}Stopping containers...${NC}\"\n\tdocker compose down\n\nrestart: ## Restart all containers\n\t@echo \"${BLUE}Restarting containers...${NC}\"\n\tdocker compose restart\n\nlogs: ## Show logs from all containers\n\tdocker compose logs -f\n\nlogs-app: ## Show logs from app container\n\tdocker compose logs -f app\n\nlogs-queue: ## Show logs from queue container\n\tdocker compose logs -f queue\n\nlogs-nginx: ## Show logs from nginx container\n\tdocker compose logs -f nginx\n\nshell: ## Access app container shell\n\tdocker compose exec app bash\n\nshell-root: ## Access app container shell as root\n\tdocker compose exec -u root app bash\n\ncomposer: ## Install PHP dependencies\n\t@echo \"${BLUE}Installing PHP dependencies...${NC}\"\n\tdocker compose exec app composer install\n\nnpm: ## Install Node dependencies and build assets\n\t@echo \"${BLUE}Installing Node dependencies and building assets...${NC}\"\n\tdocker compose run --rm node sh -c \"npm install && npm run build\"\n\nnpm-dev: ## Run Vite in development mode\n\t@echo \"${BLUE}Running Vite dev server...${NC}\"\n\tdocker compose run --rm -p 5173:5173 node npm run dev\n\nnpm-watch: ## Build assets and watch for changes\n\t@echo \"${BLUE}Watching for asset changes...${NC}\"\n\tdocker compose run --rm node npm run watch\n\nartisan: ## Run artisan command (usage: make artisan cmd=\"migrate\")\n\tdocker compose exec app php artisan $(cmd)\n\nmigrate: ## Run database migrations\n\t@echo \"${BLUE}Running migrations...${NC}\"\n\tdocker compose exec app php artisan migrate\n\nmigrate-fresh: ## Fresh migration with seeding\n\t@echo \"${BLUE}Running fresh migrations with seeding...${NC}\"\n\tdocker compose exec app php artisan migrate:fresh --seed\n\nseed: ## Run database seeders\n\t@echo \"${BLUE}Running seeders...${NC}\"\n\tdocker compose exec app php artisan db:seed\n\ntest: ## Run tests\n\t@echo \"${BLUE}Running tests...${NC}\"\n\tdocker compose exec app php artisan test\n\ntinker: ## Run Laravel tinker\n\tdocker compose exec app php artisan tinker\n\ncache-clear: ## Clear all caches\n\t@echo \"${BLUE}Clearing caches...${NC}\"\n\tdocker compose exec app php artisan cache:clear\n\tdocker compose exec app php artisan config:clear\n\tdocker compose exec app php artisan route:clear\n\tdocker compose exec app php artisan view:clear\n\ncache: ## Cache config, routes, and views\n\t@echo \"${BLUE}Caching configuration...${NC}\"\n\tdocker compose exec app php artisan config:cache\n\tdocker compose exec app php artisan route:cache\n\tdocker compose exec app php artisan view:cache\n\noptimize: ## Optimize the application\n\t@echo \"${BLUE}Optimizing application...${NC}\"\n\tdocker compose exec app php artisan optimize\n\nqueue-restart: ## Restart queue worker\n\t@echo \"${BLUE}Restarting queue worker...${NC}\"\n\tdocker compose restart queue\n\ndb: ## Access MySQL CLI\n\tdocker compose exec db mysql -u examinee_user -pexaminee_password examinee_db\n\nsetup: ## Initial setup (for first time)\n\t@echo \"${BLUE}Setting up the application...${NC}\"\n\t@if [ ! -f .env ]; then \\\n\t\tcp .env.docker .env; \\\n\t\techo \"${GREEN}.env file created from .env.docker${NC}\"; \\\n\tfi\n\t@echo \"${BLUE}Building containers...${NC}\"\n\tdocker compose build\n\t@echo \"${BLUE}Starting containers...${NC}\"\n\tdocker compose up -d\n\t@echo \"${BLUE}Installing dependencies...${NC}\"\n\tdocker compose exec app composer install\n\t@echo \"${BLUE}Generating application key...${NC}\"\n\tdocker compose exec app php artisan key:generate\n\t@echo \"${BLUE}Running migrations...${NC}\"\n\tdocker compose exec app php artisan migrate\n\t@echo \"${BLUE}Creating storage link...${NC}\"\n\tdocker compose exec app php artisan storage:link\n\t@echo \"${BLUE}Installing Node dependencies and building assets...${NC}\"\n\tdocker compose run --rm node sh -c \"npm install && npm run build\"\n\t@echo \"${GREEN}Setup complete! Access the app at http://localhost:8000${NC}\"\n\nclean: ## Remove all containers, volumes, and images\n\t@echo \"${RED}Removing all containers, volumes, and images...${NC}\"\n\tdocker compose down -v\n\tdocker system prune -f\n\nfix-permissions: ## Fix storage permissions\n\t@echo \"${BLUE}Fixing permissions...${NC}\"\n\tdocker compose exec -u root app chown -R www-data:www-data /var/www/html/storage\n\tdocker compose exec -u root app chown -R www-data:www-data /var/www/html/bootstrap/cache\n\tdocker compose exec -u root app chmod -R 755 /var/www/html/storage\n\tdocker compose exec -u root app chmod -R 755 /var/www/html/bootstrap/cache\n\nstatus: ## Show status of all containers\n\tdocker compose ps\n"
  },
  {
    "path": "README.md",
    "content": "# examinee on Online exam system\n“examinee” is a platform for Schools, Colleges, Institute & Coaching Centers. With the help of this platform, you can take Online-Offline Course, Lesson, Exams, Quiz, Test, Quiz Competition, Challenges etc\n\n# Key Features\n- Course and lesson \n- Scholar and student mangement\n- Course enrollment \n- Quiz and Exam System\n- File Management\n- Login System\n- Secure login and change password\n- Bootstrap 4 Framework\n- Cross Browser Compatible\n- Unique and Exclusive Idea\n- Unique and Creative Project\n- Clean Code and Clean Design\n- Easy To Customize\n## Requirements\n------------\n - PHP >= 7.3.0\n - Laravel => 7.5.0\n - Fileinfo PHP Extension\n\n## How to install\n-------------\n1. Clone the repo  ```git clone https://github.com/mshossain110/examinee.git```\n2. Move Directory ```cd examinee```\n3. Install composer ```composer install```\n4. Copy .env file ```cp .env.example .env```\n5. Generate key ```php artisan key:generate```\n6. Create database and edit ```.env``` file to add database, MAIL_DRIVER\n7. Dont forget to edit APP_URL (required to assest compile ) and SANCTUM_STATEFUL_DOMAINS (For API Authentication)\n8. Migrate database ```php artisan migrate:fresh --seed```\n9. Install npm ```npm i```\n10. Watch file ```npm run watch```\n\n\n## Screen Shorts\n---\n![Dashboard, ](https://github.com/mshossain110/examinee/blob/develop/doc/screenshort/dashboard.png)\n\n![Exam](https://github.com/mshossain110/examinee/blob/develop/doc/screenshort/exam.png)\n\n![Question Form](https://github.com/mshossain110/examinee/blob/develop/doc/screenshort/question.png)\n"
  },
  {
    "path": "app/Actions/CourseWithSections.php",
    "content": "<?php\nnamespace App\\Actions;\n\nuse App\\Http\\Resources\\CourseResource;\nuse App\\Models\\Course;\nuse App\\Models\\Section;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Collection;\n\nclass CourseWithSections\n{\n    public static function getCourses(Course $course)\n    {\n        \n        return Cache::remember('courseforStudent-' . $course->id, now()->addDays(1), function()use ($course) {\n            $course->load(['sections.lessons', 'sections.exams']);\n\n                $course->sections->map( function(Section $section) {\n\n                    $resources = new Collection([]);\n                    $section->lessons->each(function($lesson) use($resources) {\n                        $resources->push($lesson);\n                    });\n\n                    \n                    $section->exams->each(function($exam) use($resources) {\n                        $resources->push($exam);\n                    });\n\n                    $resources->sortBy('pivot.order');\n\n                    $section->resources = $resources;\n\n                    unset($section->lessons);\n                    unset($section->exams);\n\n                    return $section;\n                });\n\n                return new CourseResource($course);\n        });\n    }\n}"
  },
  {
    "path": "app/Actions/GetEnrolledCousesAction.php",
    "content": "<?php\nnamespace App\\Actions;\n\nuse App\\Models\\User;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Pagination\\LengthAwarePaginator;\n\nclass GetEnrolledCousesAction\n{\n    public static function getCourses(User $student, bool $pagination = false):LengthAwarePaginator | Collection\n    {\n        if ($pagination) {\n            return $student->enrolledCourses()->paginate();\n        }\n\n        return $student->enrolledCourses;\n    }\n}"
  },
  {
    "path": "app/Actions/GetInstratorCousesAction.php",
    "content": "<?php\nnamespace App\\Actions;\n\nuse App\\Models\\User;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Pagination\\LengthAwarePaginator;\n\nclass GetInstratorCousesAction\n{\n    public static function getCourses(User $instraotor, bool $pagination = false):LengthAwarePaginator | Collection\n    {\n        if ($pagination) {\n            return $instraotor->instructCourses()->paginate();\n        }\n\n        return $instraotor->instructCourses;\n    }\n}"
  },
  {
    "path": "app/Enums/Attributes/Description.php",
    "content": "<?php\n\nnamespace App\\Domain\\Common\\Enums\\Attributes;\n\nuse Attribute;\n\n#[Attribute]\nclass Description\n{\n    public function __construct(\n        public string $description,\n    ) {\n        //\n    }\n}\n"
  },
  {
    "path": "app/Enums/PermissionsEnum.php",
    "content": "<?php\n\nnamespace App\\Enums;\n\nenum PermissionsEnum\n{\n    //\n}\n"
  },
  {
    "path": "app/Enums/StatusesEnum.php",
    "content": "<?php\n\nnamespace App\\Domain\\Common\\Enums;\n\nuse App\\Domain\\Common\\Enums\\Traits\\EnumToArray;\n\nenum StatusesEnum: string\n{\n    use EnumToArray;\n\n    case DISABLED = 'disabled';\n    case ENABLED = 'enabled';\n\n    public static function localizedList(): array\n    {\n        $result = [];\n\n        foreach (self::values() as $value) {\n            $result[$value] = __('statuses.'.$value);\n        }\n\n        return $result;\n    }\n}\n"
  },
  {
    "path": "app/Enums/Traits/AsSelectArray.php",
    "content": "<?php\n\nnamespace App\\Domain\\Common\\Enums\\Traits;\n\ntrait AsSelectArray\n{\n    /**\n     * @return array<string,string>\n     */\n    public static function asSelectArray(): array\n    {\n        /** @var array<string,string> $values */\n        $values = collect(self::cases())\n            ->map(function ($enum) {\n                return [\n                    'name' => self::getDescription($enum),\n                    'value' => $enum->value,\n                ];\n            })->toArray();\n\n        return $values;\n    }\n}\n"
  },
  {
    "path": "app/Enums/Traits/EnumToArray.php",
    "content": "<?php\n\nnamespace App\\Domain\\Common\\Enums\\Traits;\n\ntrait EnumToArray\n{\n    public static function names(): array\n    {\n        return array_column(self::cases(), 'name');\n    }\n\n    public static function values(): array\n    {\n        return array_column(self::cases(), 'value');\n    }\n\n    public static function array(): array\n    {\n        return array_combine(self::names(), self::values());\n    }\n}\n"
  },
  {
    "path": "app/Enums/Traits/GetsAttributes.php",
    "content": "<?php\n\nnamespace App\\Domain\\Common\\Enums\\Traits;\n\nuse App\\Domain\\Common\\Enums\\Attributes\\Description;\nuse Illuminate\\Support\\Str;\nuse ReflectionClassConstant;\n\ntrait GetsAttributes\n{\n    private static function getDescription(self $enum): string\n    {\n        $ref = new ReflectionClassConstant(self::class, $enum->name);\n        $classAttributes = $ref->getAttributes(Description::class);\n\n        if (count($classAttributes) === 0) {\n            return Str::headline($enum->value);\n        }\n\n        return $classAttributes[0]->newInstance()->description;\n    }\n\n    public function description(): string\n    {\n        return self::getDescription($this);\n    }\n}\n"
  },
  {
    "path": "app/Events/ExamCreated.php",
    "content": "<?php\n\nnamespace App\\Events;\n\nuse App\\Models\\Exam;\nuse Illuminate\\Broadcasting\\Channel;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Broadcasting\\PrivateChannel;\nuse Illuminate\\Broadcasting\\PresenceChannel;\nuse Illuminate\\Foundation\\Events\\Dispatchable;\nuse Illuminate\\Broadcasting\\InteractsWithSockets;\nuse Illuminate\\Contracts\\Broadcasting\\ShouldBroadcast;\n\nclass ExamCreated implements ShouldBroadcast\n{\n    use Dispatchable, InteractsWithSockets, SerializesModels;\n\n    public $exam;\n\n    /**\n     * Create a new event instance.\n     *\n     * @return void\n     */\n    public function __construct(Exam $exam)\n    {\n        $this->exam = $exam;\n    }\n\n    /**\n     * Get the channels the event should broadcast on.\n     *\n     * @return \\Illuminate\\Broadcasting\\Channel|array\n     */\n    public function broadcastOn()\n    {\n        return new PrivateChannel('exams');\n    }\n}\n"
  },
  {
    "path": "app/Exceptions/Handler.php",
    "content": "<?php\n\nnamespace App\\Exceptions;\n\nuse App\\Mail\\ExceptionOccured;\nuse Illuminate\\Foundation\\Exceptions\\Handler as ExceptionHandler;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Response;\nuse Illuminate\\Support\\Facades\\Log;\nuse Mail;\nuse Throwable;\n\nclass Handler extends ExceptionHandler\n{\n    /**\n     * A list of the exception types that are not reported.\n     *\n     * @var array<int, string|null>\n     */\n    protected $dontReport = [\n        //\n    ];\n\n    /**\n     * A list of the inputs that are never flashed for validation exceptions.\n     *\n     * @var array<int, string>\n     */\n    protected $dontFlash = [\n        'current_password',\n        'password',\n        'password_confirmation',\n    ];\n\n    /**\n     * Register the exception handling callbacks for the application.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        $this->reportable(function (Throwable $e) {\n            $this->sendEmail($e);\n\n            if (app()->bound('sentry') && config('services.sentry.enabled')) {\n                app('sentry')->captureException($e);\n            }\n        });\n    }\n\n    /**\n     * Render an exception into an HTTP response.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Throwable  $e\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function render($request, Throwable $e)\n    {\n        $userLevelCheck = $e instanceof \\jeremykenedy\\LaravelRoles\\App\\Exceptions\\RoleDeniedException ||\n            $e instanceof \\jeremykenedy\\LaravelRoles\\App\\Exceptions\\PermissionDeniedException ||\n            $e instanceof \\jeremykenedy\\LaravelRoles\\App\\Exceptions\\LevelDeniedException;\n\n        if ($userLevelCheck) {\n            if ($request->expectsJson()) {\n                return Response::json([\n                    'error'     => 403,\n                    'message'   => 'Unauthorized.',\n                ], 403);\n            }\n\n            abort(403);\n        }\n\n        return parent::render($request, $e);\n    }\n\n    /**\n     * Sends an email upon exception.\n     *\n     * @param  \\Throwable  $exception\n     * @return void\n     */\n    public function sendEmail(Throwable $exception)\n    {\n        try {\n            $content['message'] = $exception->getMessage();\n            $content['file'] = $exception->getFile();\n            $content['line'] = $exception->getLine();\n            $content['trace'] = $exception->getTrace();\n            $content['url'] = request()->url();\n            $content['body'] = request()->all();\n            $content['ip'] = request()->ip();\n            Mail::send(new ExceptionOccured($content));\n        } catch (Throwable $exception) {\n            Log::error($exception);\n        }\n    }\n}\n"
  },
  {
    "path": "app/Exceptions/SocialProviderDeniedException.php",
    "content": "<?php\n\nnamespace App\\Exceptions;\n\nuse Exception;\n\nclass SocialProviderDeniedException extends Exception\n{\n    /**\n     * Render the exception as an HTTP response.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function render($request)\n    {\n        return response()->view('socialite.denied', [], 401);\n    }\n}\n"
  },
  {
    "path": "app/Helpers/Functions/core.php",
    "content": "<?php\n\n/**\n * Get either a Gravatar URL or complete image tag for a specified email address.\n *\n * @param string $email The email address\n * @param string $s Size in pixels, defaults to 80px [ 1 - 2048 ]\n * @param string $d Default imageset to use [ 404 | mp | identicon | monsterid | wavatar ]\n * @param string $r Maximum rating (inclusive) [ g | pg | r | x ]\n * @param boole $img True to return a complete IMG tag False for just the URL\n * @param array $atts Optional, additional key/value attributes to include in the IMG tag\n * @return String containing either just a URL or a complete image tag\n * @source https://gravatar.com/site/implement/images/php/\n */\nfunction get_gravatar( $email, $s = 40, $d = 'mp', $r = 'g', $img = false, $atts = array() ) {\n    $url = 'https://www.gravatar.com/avatar/';\n    $url .= md5( strtolower( trim( $email ) ) );\n    $url .= \"?s=$s&d=$d&r=$r\";\n    if ( $img ) {\n        $url = '<img src=\"' . $url . '\"';\n        foreach ( $atts as $key => $val )\n            $url .= ' ' . $key . '=\"' . $val . '\"';\n        $url .= ' />';\n    }\n    return $url;\n}"
  },
  {
    "path": "app/Http/Controllers/API/FileController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\API;\n\nuse App\\Models\\File;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Jobs\\UploadToCloud;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\UploadedFile;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Intervention\\Image\\Facades\\Image;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Http\\File as FileAdapdar;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\nuse Pion\\Laravel\\ChunkUpload\\Receiver\\FileReceiver;\nuse Pion\\Laravel\\ChunkUpload\\Handler\\HandlerFactory;\nuse Pion\\Laravel\\ChunkUpload\\Handler\\AbstractHandler;\nuse Pion\\Laravel\\ChunkUpload\\Exceptions\\UploadMissingFileException;\n\nclass FileController extends Controller\n{\n\n    public function index(Request $request)\n    {\n        $user = $request->user();\n        $perpage = $request->get('per_page') ?: 30;\n        $type = $request->get('type');\n        $search = $request->get('search');        \n       \n        $files = File::with('uploader')->where('uploaded_by', $user->id);\n        \n\n        if ($type) {\n            $files = $files->where('type', $type);\n        }\n\n        if ($search) {\n            $files = $files->where('name', 'like', \"%$search%\");\n        }\n\n        $files = $files->paginate($perpage);\n\n        $resource = JsonResource::collection($files);\n\n        return $resource;\n    }\n\n    public function show(Request $request, File $file)\n    {\n        $with = ['uploader'];\n\n        $file->load($with);\n\n        $resource = New JsonResource($file);\n\n        return $resource;\n    }\n\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @param \\App\\Http\\Requests\\UserRequest $request\n    *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(Request $request)\n    {\n\n        $request->input('file_name', $request->get('dzuuid'));\n        $inputs = $request->all();\n        $inputs['meta']['sizes'] = $this->getDefaultSizes();\n        $inputs['meta']['permissions'] = $this->getFilePermissions($request);\n                \n\n        $chunkupload = true;\n        if ($chunkupload) {\n            // create the file receiver\n            $receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));\n\n            // check if the upload is success, throw exception or return response you need\n            if ($receiver->isUploaded() === false) {\n                throw new UploadMissingFileException();\n            }\n\n            // receive the file\n            $save = $receiver->receive();\n\n            // check if the upload has finished (in chunk mode it will send smaller files)\n            if ($save->isFinished()) {\n                // save the file and return any response you need, current example uses `move` function. If you are\n                // not using move, you need to manually delete the file by unlink($save->getFile()->getPathname())\n                $filedata = $this->getFileData($save->getFile(), $inputs);\n                $fileEntry = File::create($filedata);\n\n                $this->storeLocalUpload($fileEntry, $save->getFile());\n\n                // $this->file->resizeImage($fileEntry, $save->getFile());\n                \n\n                // UploadToCloud::dispatch($fileEntry)->delay(now()->addMinutes(10)); // fire resize event and uplad to cloud\n                $resource = new JsonResource($fileEntry);\n\n                return $resource;\n            }\n\n            // we are in chunk mode, lets send the current progress\n            /** @var AbstractHandler $handler */\n            $handler = $save->handler();\n\n            return response()->json([\n                'done' => $handler->getPercentageDone(),\n                'status' => true,\n            ]);\n        }\n\n        // $fileEntry    = $this->file->createFile($uploadedFile, ['parent_id' => $parent_id, 'path' => $path] );\n\n        // $this->file->storePrivateUpload($fileEntry, $uploadedFile);\n        // return $this->respondWithItem($fileEntry, new FileTransformer);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param  $request\n     * @param int $id\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update(Request $request, $id)\n    {\n        $user = $request->user();\n        $data = $request->only(['name', 'description']);\n        $file = File::findOrFail($id);\n\n        // not file owner\n        if ($file->uploaded_by != $user->id) {\n            return $this->errorUnauthorized('Unauthorized', [\"You can\\'t Update the file details.\"]);\n        }\n\n        $file->fill($data);\n        $file->save();\n\n\n        $resource = new JsonResource($file);\n\n        return $resource;\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param int $id\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroy(Request $request, $id)\n    {\n        $user = $request->user();\n        $file = File::findOrFail($id);\n\n        // not file owner\n        if ($file->uploaded_by != $user->id) {\n            return $this->errorUnauthorized('Unauthorized', [\"You can\\'t Delete the file.\"]);\n        }\n\n       $file->delete();\n\n        return $this->respondWithMessage('file deleted successfully.');\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param int $id\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroyAll(Request $request)\n    {\n        $user = $request->user();\n        $ids = $request->get('ids');\n        File::whereIn('id', $ids)->where('uploaded_by', $user->id)->delete();\n\n        return $this->respondWithMessage('file deleted successfully.');\n    }\n\n    protected function getFilePermissions(Request $request)\n    {\n        return [\n            'public' => true,\n        ];\n    }\n\n    protected function getDefaultSizes() {\n        return [\n            '120x80' => false\n        ];\n    }\n\n\n    /**\n     * @param UploadedFile $file\n     * @param array        $extra\n     *\n     * @return array\n     */\n    public function getFileData(UploadedFile $file, $extra)\n    {\n        // TODO: move mime/extension/type guessing into separate class\n        $originalMime = $file->getMimeType();\n\n        if ($originalMime === 'application/octet-stream') {\n            $originalMime = $file->getClientMimeType();\n        }\n\n        $file_name = Arr::get($extra, 'file_name') ? Arr::get($extra, 'file_name') : Str::random(36);\n        $data = [\n            'name' => Arr::get($extra, 'name', $file->getClientOriginalName()),\n            'file_name' => $file_name,\n            'mime' => $originalMime,\n            'type' => $this->getTypeFromMime($originalMime),\n            'extension' => $this->getExtension($file, $originalMime),\n            'path' => Arr::get($extra, 'path'),\n            'parent_id' => Arr::get($extra, 'parent_id'),\n            'public_path' => Arr::get($extra, 'public_path'),\n            'uploaded_by' => Arr::get($extra, 'uploaded_by', Auth::id()),\n            'driver' => Arr::get($extra, 'driver', config('filesystems.default')),\n            'driver_data' => Arr::get($extra, 'driver_data'),\n            'meta' => Arr::get($extra, 'meta'),\n        ];\n\n        return $data;\n    }\n\n    /**\n     * Extract file extension from specified file data.\n     *\n     * @param UploadedFile $file\n     * @param string       $mime\n     *\n     * @return string\n     */\n    private function getExtension(UploadedFile $file, $mime)\n    {\n        if ($extension = $file->getClientOriginalExtension()) {\n            return $extension;\n        }\n\n        $pathinfo = pathinfo($file->getClientOriginalName());\n\n        if (isset($pathinfo['extension'])) {\n            return $pathinfo['extension'];\n        }\n\n        return explode('/', $mime)[1];\n    }\n\n    /**\n     * Get type of file entry from specified mime.\n     *\n     * @param string $mime\n     *\n     * @return string\n     */\n    protected function getTypeFromMime($mime)\n    {\n        $default = explode('/', $mime)[0];\n\n        switch ($mime) {\n            case 'application/x-zip-compressed':\n            case 'application/zip':\n                return 'archive';\n            case 'application/pdf':\n                return 'pdf';\n            case 'vnd.android.package-archive':\n                return 'android package';\n            case Str::contains($mime, 'xml'):\n                return 'spreadsheet';\n            default:\n                return $default === 'application' ? 'file' : $default;\n        }\n    }\n\n    \n\n\n\n    public function createThumbanile (File $entry, UploadedFile $file, $size = '120x80') {\n        if ($entry->type !== 'image') return;\n        // Image not resized let resize it\n        $rs = explode('x', $size); // [150, 50]\n\n        //  create Intervention images\n        $image = Image::make($file)->resize($rs[0], $rs[1]);\n        $path = storage_path(\"app/uploads/{$entry->file_name}\");\n\n        $localFile = \"{$path}/{$size}-{$entry->name}\";\n        $image->save($localFile);\n\n        return $localFile;\n    }\n\n    /**\n     * @param FileEntry    $entry\n     * @param UploadedFile $contents\n     */\n    public function moveFile(file $entry, UploadedFile $file, $public = 'public', $disk = null, $file_name = null)\n    {\n        if (!$disk) {\n            $disk = config('filesystems.default');\n        }\n\n        if (!$file_name) {\n            $file_name = $entry->name;\n        }\n\n        Storage::disk($disk)->putFileAs($entry->file_name, $file, $file_name, $public);\n\n        $entry->updatePublicPaths($disk);\n    }\n\n    /**\n     * @param FileEntry    $entry\n     * @param UploadedFile $contents\n     */\n    public function storePublicUpload(File $entry, UploadedFile $file, $file_name = null)\n    {\n        $this->moveFile($entry, $file, 'public', 'public', $file_name);\n    }\n\n    /**\n     * @param FileEntry    $entry\n     * @param UploadedFile $contents\n     */\n    public function storeLocalUpload(File $entry, UploadedFile $file, $file_name = null)\n    {\n        $this->moveFile($entry, $file, 'public', 'local', $file_name);\n    }\n\n}\n"
  },
  {
    "path": "app/Http/Controllers/API/MyCourseController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\API;\n\nuse App\\Models\\Course;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\nclass MyCourseController extends Controller\n{\n    /**\n     * Display a listing of the resource.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function index(Request $request)\n    {\n        $user = $request->user();\n        $courses = Course::withCount('lessons')->whereHas('students', function($query) use($user){\n            $query->where('user_id', $user->id);\n        })->get();\n\n        $collection = JsonResource::collection($courses);\n\n        return $collection->response();\n    }\n\n\n\n    /**\n     * Display the specified resource.\n     *\n     * @param  \\App\\Course  $course\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function show(Request $request, Course $course)\n    {\n\n        $course->load([\n            'teachers'\n        ]);\n        \n        $resource = New JsonResource($course);\n\n        return $resource;\n    }\n\n}\n"
  },
  {
    "path": "app/Http/Controllers/API/SectionableController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\API;\n\nuse App\\Models\\Course;\nuse App\\Models\\Sectionable;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\nclass SectionableController extends Controller\n{\n    public function lessons(Request $request, Course $course)\n    {\n        $hasVisibility = $this->hasVisibility($course);\n\n        $with = ['lessons', 'exams'];\n        if ($hasVisibility) {\n            $with[] = 'lessons.files';\n        }\n\n\n        $sections= Sectionable::with($with)->where('course_id', $course->id)->get();\n        $sections = $sections->map(function($s) use($hasVisibility) {\n            $exams = $s->exams;\n            $lessons = $s->lessons;\n            if ($hasVisibility) {\n                $lessons->makeVisible(['object', 'full_text']);\n            }\n            unset($s->exams);\n            unset($s->lessons);\n\n            $s->resources = $lessons->merge($exams);\n\n            return $s;\n        });\n\n        return JsonResource::collection($sections);\n\n    }\n\n    protected function hasVisibility (Course $course) {\n        if (!Auth::check()) {\n            return false;\n        }\n\n        $user = Auth::user();\n\n        if ($course->teachers->where('id', $user->id)->isEmpty()) {\n            return false;\n        }\n\n        return true;\n    }\n}"
  },
  {
    "path": "app/Http/Controllers/API/TakeExamController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\API;\n\nuse App\\Models\\Exam;\nuse App\\Models\\User;\nuse App\\Models\\Result;\nuse Carbon\\Carbon;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Controllers\\Controller;\nuse Exception;\nuse Illuminate\\Support\\Facades\\Session;\n\nclass TakeExamController extends Controller\n{\n    public function show(Request $request, Exam $exam)\n    {\n        $user = $request->user();\n        $questions= collect();\n        $time = Session::get(\"exam.$exam->id\");\n        $exam->load('topics', 'subjects');\n        $result = $exam->results()->where('examinee', $user->id)->orderBy('created_at', \"DESC\")->first();\n\n        if ($result && !empty($exam->meta['show_answer']) &&  $exam->meta['show_answer']) {\n            $q = $exam->questions;\n            \n            \n            collect($result->answers)->map(function($qi) use($q, $questions){\n                $questions->push($q->firstWhere('id', $qi['id']));\n            });\n\n            // $questions = $questions->map(function($q) use($questionFields){\n            //     return collect($q->toArray())->only($questionFields)->all();\n            // })->values()->all();\n\n            if (!(!empty($exam->meta['show_answer']) &&  $exam->meta['show_answer'])) {\n                $questions = $questions->map(function($ques) {\n                    unset($ques->answers);\n                    return $ques;\n                });\n            }\n        }\n\n        \n        \n        return response()->json(compact(['exam', 'time', 'result',  'questions']));\n    }\n\n\n    public function start (Request $request, Exam $exam)\n    {\n        $user = $request->user();\n\n        if (!$this->userCanTakeExam($user, $exam)) {\n           return; \n        }\n    \n        \n        $time = Session::get(\"exam.$exam->id\");\n\n        if (!$time) {\n            $time = Session::put(\"exam.$exam->id\", Carbon::now());\n            $time = Session::get(\"exam.$exam->id\");\n        }\n        $answers = Session::get(\"exam_question\");\n        $answers = collect($answers);\n\n        $questionFields = ['id', 'qtype', 'question', 'options' , 'mark', 'nmark'];\n\n        if (!empty($exam->meta['show_hint']) && $exam->meta['show_hint']) {\n            $questionFields[] = 'hint';\n        }\n\n        if ($answers->isEmpty()) {\n            $questions = $exam->questions->shuffle()->take($exam->number_of_questions)->map(function($q) use($answers, $questionFields){\n                $answers->push(['id'=> $q->id]);\n                return collect($q->toArray())->only($questionFields)->all();\n            })->values()->all(); //\n\n            Session::put(\"exam_question\", $answers);\n        } else {\n            $q = $exam->questions;\n            $questions= collect();\n\n            $answers->map(function($qi) use($q, $questions){\n                $questions->push($q->firstWhere('id', $qi['id']));\n            });\n\n            $questions = $questions->map(function($q) use($questionFields){\n                return collect($q->toArray())->only($questionFields)->all();\n            })->values()->all();\n        }\n\n        return response()->json(compact('exam', 'time', 'questions', 'answers'));\n    }\n\n    public function answer(Request $request, Exam $exam)\n    {        \n        $user = $request->user();\n        $time = Session::get(\"exam.$exam->id\");\n\n        $answers = Session::get(\"exam_question\");\n        $answers = collect($answers);\n\n        if ($time && Carbon::parse($time)->diffInMinutes(Carbon::now()) < $exam->duration ) {\n            if(sizeof($request->keys()) === 1) {\n                $key = $request->keys()[0];\n                $ans = $request->get($key, []);\n                if (!empty($ans)) {\n                    $answers = $answers->map(function($q) use($ans, $key) {\n                        if ($q['id'] === $key) {\n                            $q['answer'] = $ans;\n                        }\n                        return $q;\n                    });\n                    Session::put(\"exam_question\", $answers);\n                }\n                \n            }\n        }\n        $answers = Session::get(\"exam_question\");\n\n        return compact('answers', 'time');\n    }\n\n    public function complete(Request $request, Exam $exam)\n    {\n\n        $time = Session::get(\"exam.$exam->id\");\n        $answers = Session::get(\"exam_question\");\n        $answers = collect($answers);\n\n        $obtainMark = $this->obtain_mark($exam);\n        $timeTaken = Carbon::parse($time)->diffInMinutes(Carbon::now());\n\n        $user = $request->user();\n        $result = new Result;\n        \n        $result->examinee = $user->id;\n        $result->exam_id = $exam->id;\n        $result->answers = $answers;\n        $result->time_taken = $timeTaken;\n        $result->obtain_mark = $obtainMark;\n        $result->is_pass = $exam->pass_mark < $obtainMark;\n\n        if ($result->save()) {\n            Session::forget(\"exam_question\");\n            Session::forget(\"exam\");\n        }\n\n        return response()->json(compact('result'));\n    }\n\n    private function obtain_mark(Exam $exam)\n    {\n        $number = 0;\n        $answers = Session::get(\"exam_question\");\n        $answers = collect($answers);\n\n        $questions = $exam->questions;\n\n        $answers->each(function($ans) use($questions, &$number) {\n            if(!empty($ans['answer'])) {\n\n                $ques = $questions->firstWhere('id', $ans['id']);\n                $intersect = array_intersect($ques->answers, $ans['answer'] );\n\n                if (sizeof($intersect) === sizeof($ques->answers)) {\n                    // answer is correct\n                    $number += floatval($ques->mark);\n                } else {\n                    $number -= floatval($ques->nmark);\n                }\n\n            }\n            \n        });\n\n        return $number;\n        \n    }\n\n    private function userCanTakeExam(User $user, Exam $exam)\n    {\n        $time = Session::get(\"exam\");\n        if ($time && empty($time[$exam->id])){\n            throw  new Exception(__(\"Exam id :key running\", [\"key\" => array_keys($time)[0]]));\n        }\n        \n        $result = $exam->results()->where('examinee', $user->id)->orderBy('created_at', \"DESC\")->first();\n        if ($result) {\n            $differ = ((intval($exam->meta['retake'])?: 0 )- Carbon::parse($result->created_at)->diffInDays(Carbon::now()) );\n            if ( $differ > 0){\n                throw  new Exception(__(\"You can retry after :day days\", [\"day\" => $differ]));\n            }\n        }\n        \n\n        return true;\n    }\n}"
  },
  {
    "path": "app/Http/Controllers/Admin/CourseStudentController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\nuse Inertia\\Inertia;\nuse App\\Models\\Course;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\CourseResource;\nuse App\\Http\\Resources\\CourseStudentsResource;\n\nclass CourseStudentController extends Controller\n{\n    public function __invoke(Course $course)\n    {\n        $students = $course->students;\n\n        return Inertia::render('admin/courses/CourseStudent', [\n            'course' => new CourseResource($course),\n            'students' => CourseStudentsResource::collection($students) \n        ]);\n    }\n}"
  },
  {
    "path": "app/Http/Controllers/Admin/CoursesController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\n\nuse Inertia\\Inertia;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\CourseResource;\nuse App\\Models\\Course;\n\nclass CoursesController extends Controller\n{\n    public function __construct()\n    {\n        $this->authorizeResource(Course::class);\n    }\n    /**\n     * Display a listing of the resource.\n     */\n    public function index(Request $request)\n    {\n        $user = $request->user();\n        $courses = Course::query();\n\n        if(! $user->isAdmin() ) {\n            $courses = $courses->whereHas('teachers', function($q) use($user){\n                $q->where('id', $user->id);\n            });\n        }\n\n        $courses = $courses->paginate();\n\n        return Inertia::render(\n            'admin/courses/Index', \n            [\n                'response' => CourseResource::collection($courses),\n            ]\n        );\n    }\n\n    /**\n     * Show the form for creating a new resource.\n     */\n    public function create()\n    {\n        return Inertia::render('admin/courses/CreateCourse');\n    }\n\n    /**\n     * Store a newly created resource in storage.\n     */\n    public function store(Request $request)\n    {\n        $user = $request->user();\n        $data = $request->only(['title', 'subtitle', 'slug', 'description', 'price', 'discount', 'thumbnail', 'start_date', 'status', 'certified']);\n        $data['created_by'] = $user->id;\n        $data['updated_by'] = $user->id;\n        $course = $user->instructCourses()->create($data);\n\n\n        return to_route('admin.courses.edit', $course);\n    }\n\n    /**\n     * Show the form for editing the specified resource.\n     */\n    public function edit(Course $course)\n    {\n        return Inertia::render('admin/courses/CreateCourse', [ 'course' => new CourseResource($course) ]);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     */\n    public function update(Request $request, course $course)\n    {\n        $user = $request->user();\n        $data = $request->all();\n        $data['updated_by'] = $user->id;\n\n        $course->update($data);\n\n        return to_route('admin.courses.edit', $course);\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     */\n    public function destroy(course $course)\n    {\n        $course->delete();\n\n        return to_route('admin.courses.index');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/DashboardController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\nuse Inertia\\Inertia;\nuse App\\Models\\Subject;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\SubjectResource;\n\nclass DashboardController extends Controller\n{\n\n\n    /**\n     * Show the application dashboard.\n     *\n     * @return \\Illuminate\\Contracts\\Support\\Renderable\n     */\n    public function __invoke(Request $request)\n    {\n        return Inertia::render('admin/Dashboard');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/ExamController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\nuse App\\Models\\Exam;\nuse Inertia\\Inertia;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Requests\\ExamRequest;\nuse Illuminate\\Support\\Facades\\DB;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\ExamResource;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\nclass ExamController extends Controller\n{\n    public function __construct()\n    {\n        $this->authorizeResource(Exam::class);\n    }\n    /**\n     * Display a listing of the resource.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function index(Request $request)\n    {\n        $user = $request->user();\n        $courseId = $request->get('course_id');\n\n        return (Exam::select(['exams.*'])->addSelect(['users' => DB::table('users')->whereColumn('users.id',  'exams.examiner')->select('email')->limit(1)])->where('exams.id', 10)->get()->toArray());\n        $exams = Exam::with(['subjects', 'questions', 'topics']);\n\n        if ($courseId) {\n            $exams = $exams->whereHas('courses', function ($q) use ($courseId) {\n                $q->where('course_id', $courseId);\n            });\n        }\n\n        $exams = $exams->paginate();\n\n        $resource = ExamResource::collection($exams);\n\n        return Inertia::render(\n            'admin/exams/Index',\n            [\n                'response' => $resource\n            ]\n        );\n    }\n\n    /**\n     * Show the form for creating a new resource.\n     */\n    public function create()\n    {\n        return Inertia::render('admin/exams/Create');\n    }\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(ExamRequest $request)\n    {\n        $user = $request->user();\n        $subject_id = $request->input('subject_id');\n        $data = $request->all();\n        $data['examiner'] = $user->id;\n\n        $exam = Exam::create($data);\n\n\n        $topics = $request->get('topics');\n\n        if ($topics) {\n            $exam->topics()->attach($topics);\n        }\n\n        $exam->subjects()->attach($subject_id);\n\n\n        return to_route('admin.exams.edit', $exam);\n    }\n\n    /**\n     * Show the form for editing the specified resource.\n     */\n    public function edit(Exam $exam)\n    {\n        return Inertia::render('admin/exams/Edit', ['exam' => new ExamResource($exam)]);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\App\\Exam  $exam\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update(ExamRequest $request, Exam $exam)\n    {\n        $exam->fill($request->all());\n        $exam->save();\n        $exam->subjects()->detach();\n        $exam->subjects()->attach($request->subject_id);\n\n        $topics = $request->get('topics');\n\n        if ($topics) {\n            $exam->topics()->attach($topics);\n        }\n\n        return to_route('admin.exams.edit', $exam);\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param  \\App\\Exam  $exam\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroy(Exam $exam)\n    {\n        $exam->subjects()->detach();\n        $exam->questions()->delete();\n        $exam->topics()->detach();\n        $exam->delete();\n\n        return to_route('admin.exams.index');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/LessonController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\nuse Inertia\\Inertia;\nuse App\\Models\\Course;\nuse App\\Models\\Lesson;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\CourseResource;\nuse App\\Http\\Resources\\LessonResource;\n\nclass LessonController extends Controller\n{\n    /**\n     * Display a listing of the resource.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function index(Request $request, Course $course)\n    {\n        $courseId = $request->get('course_id');\n        // $course = Course::find($courseId);\n        $lessons = $course->lessons()->orderBy('position')->get();\n\n        $resource = LessonResource::collection($lessons);\n\n        return Inertia::render(\n            'admin/courses/Lessons', \n            [\n                'course' => new CourseResource($course),\n                'response' => $resource,\n            ]\n        );\n\n    }\n\n        /**\n     * Show the form for creating a new resource.\n     */\n    public function create()\n    {\n        return Inertia::render('admin/courses/CreateLesson');\n    }\n\n\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(Request $request, Course $course)\n    {\n        $user = $request->user();\n        $courseId = $request->get('course_id');\n        $topics = $request->get('topics');\n\n        $data = $request->all();\n        $data['created_by'] = $user->id;\n        $data['updated_by'] = $user->id;\n        $lesson = Lesson::create($data);\n\n        if ($topics) {\n            $lesson->topics()->attach($topics);\n        }\n\n        if ($request->section) {\n            $lesson->sections()->attach($request->section, [\n                'course_id' => $courseId,\n            ]);\n\n            $lesson->load(['sectionable']);\n        }\n\n        if ($request->has('object')) {\n            $lesson->setLessonObject();\n        }\n        \n\n        return to_route('admin.lessons.edit', [$course, $lesson] );\n    }\n\n\n    /**\n     * Show the form for editing the specified resource.\n     */\n    public function edit(Course $course, Lesson $lesson)\n    {\n        return Inertia::render('admin/courses/CreateLesson', [ \n            'course' => new CourseResource($course),\n            'lesson' => new LessonResource($$lesson)\n        ]);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\App\\Lesson  $lesson\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update(Request $request, Course $course, Lesson $lesson)\n    {\n        $courseId = $request->get('course_id');\n        $topics = $request->get('topics');\n        \n        $lesson->update($request->all());\n\n        if ($topics) {\n            $lesson->topics()->attach($topics);\n        }\n\n        if ($request->section) {\n            $lesson->sections()->attach($request->section, [\n                'course_id' => $courseId,\n            ]);\n\n            $lesson->load(['sectionable']);\n        }\n        \n        if ($request->has('object')) {\n            $lesson->setLessonObject();\n        }\n        \n        return to_route('admin.lessons.edit', [$course, $lesson] );\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param  \\App\\Lesson  $lesson\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroy(Course $course, Lesson $lesson)\n    {\n        $lesson->delete();\n\n        return to_route('admin.lessons.index', [$course] );\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/QuestionController.php",
    "content": "<?php\nnamespace App\\Http\\Controllers\\Admin;\n\nuse App\\Models\\Exam;\nuse Inertia\\Inertia;\nuse App\\Models\\Question;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\QuestionResource;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\nuse App\\Http\\Requests\\QuestionRequest as Request;\nuse App\\Http\\Resources\\ExamResource;\n\nclass QuestionController extends Controller\n{\n    /**\n     * Display a listing of the resource.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function index(Exam $exam)\n    {\n        $questions = $exam->questions;\n        \n        $resource = QuestionResource::collection($questions);\n\n        return Inertia::render(\n            'admin/exams/Questions',\n            [\n                'exam' => new ExamResource($exam),\n                'questions' => $resource\n            ]\n        );\n    }\n\n    /**\n     * Show the form for creating a new resource.\n     */\n    public function create(Exam $exam)\n    {\n        return Inertia::render('admin/exams/CreateQuestion', [\n            'exam' => new ExamResource($exam)\n        ]);\n    }\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(Request $request, Exam $exam)\n    {\n        $user = $request->user();\n\n        $question = $exam->questions()->create([\n            'created_by'    => $user->id,\n            'qtype'         => $request->qtype,\n            'question'      => $request->question,\n            'options'       => $request->options,\n            'answers'       => $request->answers,\n            'hint'          => $request->hint,\n            'mark'          => $request->mark,\n            'nmark'         => $request->nmark,\n            'explanation'   => $request->explanation\n        ]);\n       \n        return to_route('admin.questions.edit', [$exam, $question]);\n    }\n\n    /**\n     * Show the form for editing the specified resource.\n     */\n    public function edit(Exam $exam, Question $question)\n    {\n        return Inertia::render('admin/exams/CreateQuestion', [\n            'exam' => new ExamResource($exam),\n            'question' => new QuestionResource($question)\n        ]);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\App\\Question  $question\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update(Request $request, Exam $exam, Question $question)\n    {\n        $question->update( $request->all() );\n        \n        $resource = New JsonResource($question);\n\n        return to_route('admin.questions.edit', [$exam, $question]);\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param  \\App\\Question  $question\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroy(Exam $exam, Question $question)\n    {\n        $question->delete();\n        return to_route('admin.questions.index', [$exam]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/RolesController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\nuse App\\Models\\Role;\nuse App\\Models\\User;\nuse Inertia\\Inertia;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\RoleResource;\nuse Spatie\\Permission\\Models\\Permission;\n\nclass RolesController extends Controller\n{\n    public function __construct()\n    {\n        $this->authorizeResource(Role::class);\n    }\n    /**\n     * Display a listing of the resource.\n     */\n    public function index()\n    {\n        return Inertia::render(\n            'admin/roles/Index', \n            [\n                'response' => RoleResource::collection(\n                    Role::with('permissions')->withCount(['users', 'permissions'])->paginate()\n                ),\n                'app_roles' => Role::appRoles()\n            ]\n        );\n    }\n\n    /**        \n     * Show the form for creating a new resource.\n     */\n    public function create()\n    {\n        return Inertia::render('admin/roles/Create', [\n            'permissions' => Permission::all(['id', 'name'])->toArray(),\n        ]);\n    }\n\n    /**\n     * Store a newly created resource in storage.\n     */\n    public function store(Request $request)\n    {\n        $request->validate([\n            'name'          => 'required|string',\n            'permissions'   => ['nullable', 'array'],\n            'permissions.*' => ['integer', 'exists:permissions,id'],\n        ]);\n\n        $role = Role::create(['name' => $request->name]);\n\n        if ($request->filled('permissions')) {\n            $role->syncPermissions($request->permissions);\n        }\n\n        return to_route('admin.roles.edit', $role)\n            ->with('success', \"Role '{$role->name}' created successfully.\");\n    }\n\n    /**\n     * Display the specified resource.\n     */\n    public function show(User $user)\n    {\n        //\n    }\n\n    /**\n     * Show the form for editing the specified resource.\n     */\n    public function edit(Role $role)\n    {\n        return Inertia::render('admin/roles/Edit', [\n            'role'        => new RoleResource($role->load('permissions')),\n            'permissions' => Permission::all(['id', 'name'])->toArray(),\n        ]);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     */\n    public function update(Request $request, Role $role)\n    {\n        $request->validate([\n            'name'          => 'required|string',\n            'permissions'   => ['nullable', 'array'],\n            'permissions.*' => ['integer', 'exists:permissions,id'],\n        ]);\n\n        $role->update(['name' => $request->name]);\n        $role->syncPermissions($request->permissions ?? []);\n\n        return to_route('admin.roles.edit', $role)\n            ->with('success', \"Role '{$role->name}' updated successfully.\");\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     */\n    public function destroy(Role $role)\n    {\n        if(collect([Role::SUPERADMIN, Role::ADMIN])->contains($role->name)){\n            // exception not possible\n        }\n\n        $role->delete();\n\n        return to_route('admin.roles.index');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/SectionController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\nuse App\\Models\\Exam;\nuse Inertia\\Inertia;\nuse App\\Models\\Course;\nuse App\\Models\\Lesson;\nuse App\\Models\\Section;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\CourseResource;\nuse App\\Http\\Resources\\SectionResource;\n\nclass SectionController extends Controller\n{\n    /**\n     * Display a listing of the resource.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function index(Course $course, Request $request)\n    {\n        $sections = $course->sections()->with(['lessons', 'exams'])->get();\n\n        return Inertia::render(\n            'admin/courses/Sections', \n            [\n                'course' =>  new CourseResource($course),\n                'sections' => SectionResource::collection($sections),\n            ]\n        );\n    }\n\n\n\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(Course $course, Request $request)\n    {\n        $section = $course->sections()->create($request->all());\n        \n        return to_route('admin.sections.index', $course);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param  \\App\\Models\\Section  $section\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update(Course $course, Section $section, Request $request)\n    {\n        $section->title = $request->title;\n        $section->description = $request->description;\n        $section->save();\n\n        return to_route('admin.sections.index', $course);\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param  \\App\\Models\\Section  $Section\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroy(Course $course, Section $section)\n    {\n        $section->delete();\n\n        return to_route('admin.sections.index', $course);\n    }\n\n    public function attachExam (Request $request, Section $section) { \n        $exam = Exam::find($request->exam_id);\n        $section->exams()->attach($exam, ['course_id' => $section->course_id]);\n\n        return to_route('admin.sections.index', $section->course_id);\n    }\n\n    public function attachLession (Request $request, Section $section) {\n        $lesson = Lesson::find($request->lesson_id);\n        $section->lessons()->attach($lesson, ['course_id' => $section->course_id]);\n\n        return to_route('admin.sections.index', $section->course_id);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/ServerInfoController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\nuse Inertia\\Inertia;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Response;\nuse App\\Http\\Controllers\\Controller;\n\nclass ServerInfoController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('auth');\n        // $this->middleware('role:super.admin');\n\n        try {\n            ob_start('ob_gzhandler');\n        } catch (\\Exception $e) {\n            //\n        }\n    }\n\n    public function index(Request $request)\n    {\n        ob_start();\n        phpinfo();\n        $pinfo = ob_get_contents();\n        ob_end_clean();\n        // $pinfo = preg_replace('%^.*<body>(.*)</body>.*$%ms', '$1', $pinfo);\n\n        return Inertia::render('admin/ServerInfo', [\n            'info'  => $pinfo,\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/SubjectController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\nuse Inertia\\Inertia;\nuse App\\Models\\Subject;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Storage;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\SubjectResource;\n\nclass SubjectController extends Controller\n{\n    public function __construct()\n    {\n        $this->authorizeResource(Subject::class);\n    }\n    /**\n     * Display a listing of the resource.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function index(Request $request)\n    {\n        $search = $request->get('s');\n\n        $subjects = Subject::query()\n            ->where('parent', 0)\n            ->withCount(['courses', 'exams'])\n            ->with(['children' => fn ($q) => $q->withCount(['courses', 'exams'])->latest()])\n            ->latest();\n\n        if ($search) {\n            $subjects = $subjects->where('title', 'ilike', \"%$search%\");\n        }\n\n        $subjects = $subjects->paginate();\n\n        $resource = SubjectResource::collection($subjects);\n\n        return Inertia::render(\n            'admin/subjects/Index',\n            [\n                'response' => $resource,\n                'filters'  => ['search' => $search ?? ''],\n            ]\n        );\n    }\n\n    /**\n     * Show the form for creating a new resource.\n     */\n    public function create()\n    {\n        return Inertia::render('admin/subjects/Create', [\n            'parentSubjects' => Subject::where('parent', 0)->orderBy('title')->get(['id', 'title']),\n        ]);\n    }\n\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(Request $request)\n    {\n        $request->validate([\n            'title'       => 'required|string|max:255',\n            'description' => 'nullable|string',\n            'icon'        => 'nullable|string|max:100',\n            'image'       => 'nullable|image|max:2048',\n            'parent'      => 'nullable|integer|exists:subjects,id',\n        ]);\n\n        $data = $request->only(['title', 'description', 'icon']);\n        $data['slug']   = $request->slug ?: Str::slug($request->title);\n        $data['parent'] = $request->input('parent', 0);\n\n        if ($request->hasFile('image')) {\n            $data['image'] = $request->file('image')->store('subjects', 'public');\n        }\n\n        $subject = Subject::create($data);\n\n        return to_route('admin.subjects.edit', $subject)->with('success', 'Subject created successfully.');\n    }\n\n    /**\n     * Show the form for editing the specified resource.\n     */\n    public function edit(Subject $subject)\n    {\n        return Inertia::render('admin/subjects/Edit', [\n            'subject'        => new SubjectResource($subject->loadCount('children')),\n            'parentSubjects' => Subject::where('parent', 0)\n                ->where('id', '!=', $subject->id)\n                ->orderBy('title')\n                ->get(['id', 'title']),\n        ]);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\App\\Subject  $subject\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update(Request $request, Subject $subject)\n    {\n        $request->validate([\n            'title'       => 'required|string|max:255',\n            'description' => 'nullable|string',\n            'icon'        => 'nullable|string|max:100',\n            'image'       => 'nullable|image|max:2048',\n            'parent'      => 'nullable|integer|exists:subjects,id',\n        ]);\n\n        $subject->title       = $request->title;\n        $subject->slug        = $request->slug ?: Str::slug($request->title);\n        $subject->description = $request->description;\n        $subject->icon        = $request->icon;\n        $subject->parent      = $request->input('parent', 0);\n\n        if ($request->hasFile('image')) {\n            // Delete old image\n            if ($subject->image) {\n                Storage::disk('public')->delete($subject->image);\n            }\n            $subject->image = $request->file('image')->store('subjects', 'public');\n        }\n\n        $subject->save();\n\n        return to_route('admin.subjects.edit', $subject)->with('success', 'Subject updated successfully.');\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param  \\App\\Subject  $subject\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroy(Subject $subject)\n    {\n        $subject->delete();\n\n        return to_route('admin.subjects.index');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/TopicsController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\n\nuse Inertia\\Inertia;\nuse App\\Models\\Topic;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Requests\\TopicRequest;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\TopicResource;\n\nclass TopicsController extends Controller\n{\n    public function __construct()\n    {\n        $this->authorizeResource(Topic::class);\n    }\n    \n    /**\n     * Display a listing of the resource.\n     */\n    public function index(Request $request)\n    {\n        $search = $request->get('s');\n\n        $topics = Topic::query();\n\n        $topics = $topics->withCount(['courses', 'exams']);\n\n        if($search) {\n            $topics = $topics->where('title', 'ilike', \"%$search%\");\n        }\n\n        $topics = $topics->paginate();\n        \n        $resource = TopicResource::collection($topics);\n        return Inertia::render(\n            'admin/topics/Index', \n            [\n                'response' => $resource,\n                'filters'  => ['search' => $search ?? ''],\n            ]\n        );\n    }\n\n    /**\n     * Show the form for creating a new resource.\n     */\n    public function create()\n    {\n        return Inertia::render('admin/topics/Create');\n    }\n\n    /**\n     * Store a newly created resource in storage.\n     */\n    public function store(TopicRequest $request)\n    {\n        $topic = Topic::create( $request->all() );\n\n        return to_route('admin.topics.edit', $topic);\n    }\n\n\n    /**\n     * Show the form for editing the specified resource.\n     */\n    public function edit(Topic $topic)\n    {\n        return Inertia::render('admin/topics/Edit', [ 'topic' => new TopicResource($topic) ]);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\App\\Topic  $topic\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update(TopicRequest $request, Topic $topic)\n    {\n        $topic->title = $request->title;\n        $topic->description = $request->description;\n        $topic->save();\n\n        return to_route('admin.topics.edit', $topic);\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     */\n    public function destroy(Topic $topic)\n    {\n        $topic->delete();\n\n        return to_route('admin.topics.index');\n    }\n\n    public function bulkDelete(Request $request)\n    {\n        $this->authorize('delete', Topic::class);\n\n        $request->validate([\n            'ids'   => ['required', 'array'],\n            'ids.*' => ['integer', 'exists:topics,id'],\n        ]);\n\n        Topic::whereIn('id', $request->ids)->delete();\n\n        return back()->with('success', 'Selected topics deleted.');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Admin/UsersController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Admin;\n\nuse App\\Models\\User;\nuse App\\Models\\Role;\nuse Inertia\\Inertia;\nuse App\\Http\\Requests\\Admin\\UserRequest;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Resources\\UserResource;\nuse App\\Http\\Resources\\RoleResource;\nuse Illuminate\\Http\\Request;\n\nclass UsersController extends Controller\n{\n    public function __construct()\n    {\n        $this->authorizeResource(User::class);\n    }\n    /**\n     * Display a listing of the resource.\n     */\n    public function index(Request $request)\n    {\n        $query = User::with('roles')\n            ->when($request->filled('search'), function ($q) use ($request) {\n                $search = '%' . $request->search . '%';\n                $q->where(function ($q2) use ($search) {\n                    $q2->where('name', 'ilike', $search)\n                       ->orWhere('email', 'ilike', $search)\n                       ->orWhere('firstname', 'ilike', $search)\n                       ->orWhere('lastname', 'ilike', $search);\n                });\n            })\n            ->when($request->filled('role'), function ($q) use ($request) {\n                $q->whereHas('roles', fn ($q2) => $q2->where('name', $request->role));\n            });\n\n        return Inertia::render('admin/users/Index', [\n            'response' => UserResource::collection($query->paginate()->withQueryString()),\n            'roles'    => RoleResource::collection(Role::all()),\n            'filters'  => $request->only(['search', 'role']),\n        ]);\n    }\n\n    /**        \n     * Show the form for creating a new resource.\n     */\n    public function create()\n    {\n        return Inertia::render('admin/users/Create');\n    }\n\n    /**\n     * Store a newly created resource in storage.\n     */\n    public function store(UserRequest $request)\n    {\n        $validated = $request->validated();\n\n        $data = $request->only([\n            'firstname',\n            'lastname',\n            'name',\n            'email',\n            'password',\n            'role',\n            'avatar'\n        ]);\n\n        $user = User::create($data);\n\n        return Inertia::render('admin/users/Edit', [ 'user' => new UserResource($user) ]);\n    }\n\n    /**\n     * Display the specified resource.\n     */\n    public function show(User $user)\n    {\n        //\n    }\n\n    /**\n     * Show the form for editing the specified resource.\n     */\n    public function edit(User $user)\n    {\n        return Inertia::render('admin/users/Edit', [ 'user' => new UserResource($user) ]);\n    }\n\n    /**\n     * Update the specified resource in storage.\n     */\n    public function update(UserRequest $request, User $user)\n    {\n        $validated = $request->validated();\n\n        $data = $request->only([\n            'firstname',\n            'lastname',\n            'name',\n            'email',\n            'password',\n            'role',\n            'avatar',\n            'permissions',\n            'status'\n        ]);\n\n        $user = $user->update($data);\n        \n        return Inertia::render('admin/users/Edit', [ 'user' => new UserResource($user) ]);\n\n        \n    }\n\n    /**\n     * Sync roles for a user.\n     */\n    public function syncRoles(Request $request, User $user)\n    {\n        $this->authorize('update', $user);\n\n        $request->validate([\n            'roles'   => ['nullable', 'array'],\n            'roles.*' => ['integer', 'exists:roles,id'],\n        ]);\n\n        $user->syncRoles($request->roles ?? []);\n\n        return back()->with('success', \"Roles updated for {$user->name}.\");\n    }\n\n    /**\n     * Delete multiple users at once.\n     */\n    public function bulkDelete(Request $request)\n    {\n        $this->authorize('delete', User::class);\n\n        $request->validate([\n            'ids'   => ['required', 'array'],\n            'ids.*' => ['integer', 'exists:users,id'],\n        ]);\n\n        $authId = auth()->id();\n        User::whereIn('id', $request->ids)\n            ->where('id', '!=', $authId)\n            ->delete();\n\n        return back()->with('success', 'Selected users deleted.');\n    }\n\n    /**\n     * Sync roles for multiple users at once.\n     */\n    public function bulkSyncRoles(Request $request)\n    {\n        $this->authorize('update', User::class);\n\n        $request->validate([\n            'ids'     => ['required', 'array'],\n            'ids.*'   => ['integer', 'exists:users,id'],\n            'roles'   => ['nullable', 'array'],\n            'roles.*' => ['integer', 'exists:roles,id'],\n        ]);\n\n        User::whereIn('id', $request->ids)->each(\n            fn (User $user) => $user->syncRoles($request->roles ?? [])\n        );\n\n        return back()->with('success', 'Roles synced for selected users.');\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     */\n    public function destroy(User $user)\n    {\n        if ($user->is(auth()->user())) {\n            return $this->errorUnauthorized('You can\\'t delete for yourself and other Administrators!');\n        }\n\n        $user->delete();\n\n        return to_route('admin.users.index');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/AuthenticatedSessionController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Http\\Requests\\Auth\\LoginRequest;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Route;\nuse Inertia\\Inertia;\nuse Inertia\\Response;\n\nclass AuthenticatedSessionController extends Controller\n{\n    /**\n     * Display the login view.\n     */\n    public function create(): Response\n    {\n        return Inertia::render('Auth/Login', [\n            'canResetPassword' => Route::has('password.request'),\n            'status' => session('status'),\n        ]);\n    }\n\n    /**\n     * Handle an incoming authentication request.\n     */\n    public function store(LoginRequest $request): RedirectResponse\n    {\n        $request->authenticate();\n\n        $request->session()->regenerate();\n\n        return redirect()->intended(route('admin.dashboard', absolute: false));\n    }\n\n    /**\n     * Destroy an authenticated session.\n     */\n    public function destroy(Request $request): RedirectResponse\n    {\n        Auth::guard('web')->logout();\n\n        $request->session()->invalidate();\n\n        $request->session()->regenerateToken();\n\n        return redirect('/');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/ConfirmablePasswordController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Validation\\ValidationException;\nuse Inertia\\Inertia;\nuse Inertia\\Response;\n\nclass ConfirmablePasswordController extends Controller\n{\n    /**\n     * Show the confirm password view.\n     */\n    public function show(): Response\n    {\n        return Inertia::render('Auth/ConfirmPassword');\n    }\n\n    /**\n     * Confirm the user's password.\n     */\n    public function store(Request $request): RedirectResponse\n    {\n        if (! Auth::guard('web')->validate([\n            'email' => $request->user()->email,\n            'password' => $request->password,\n        ])) {\n            throw ValidationException::withMessages([\n                'password' => __('auth.password'),\n            ]);\n        }\n\n        $request->session()->put('auth.password_confirmed_at', time());\n\n        return redirect()->intended(route('admin.dashboard', absolute: false));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/EmailVerificationNotificationController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\n\nclass EmailVerificationNotificationController extends Controller\n{\n    /**\n     * Send a new email verification notification.\n     */\n    public function store(Request $request): RedirectResponse\n    {\n        if ($request->user()->hasVerifiedEmail()) {\n            return redirect()->intended(route('admin.dashboard', absolute: false));\n        }\n\n        $request->user()->sendEmailVerificationNotification();\n\n        return back()->with('status', 'verification-link-sent');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/EmailVerificationPromptController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Inertia\\Inertia;\nuse Inertia\\Response;\n\nclass EmailVerificationPromptController extends Controller\n{\n    /**\n     * Display the email verification prompt.\n     */\n    public function __invoke(Request $request): RedirectResponse|Response\n    {\n        return $request->user()->hasVerifiedEmail()\n                    ? redirect()->intended(route('admin.dashboard', absolute: false))\n                    : Inertia::render('Auth/VerifyEmail', ['status' => session('status')]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/NewPasswordController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Auth\\Events\\PasswordReset;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Hash;\nuse Illuminate\\Support\\Facades\\Password;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Validation\\Rules;\nuse Illuminate\\Validation\\ValidationException;\nuse Inertia\\Inertia;\nuse Inertia\\Response;\n\nclass NewPasswordController extends Controller\n{\n    /**\n     * Display the password reset view.\n     */\n    public function create(Request $request): Response\n    {\n        return Inertia::render('Auth/ResetPassword', [\n            'email' => $request->email,\n            'token' => $request->route('token'),\n        ]);\n    }\n\n    /**\n     * Handle an incoming new password request.\n     *\n     * @throws \\Illuminate\\Validation\\ValidationException\n     */\n    public function store(Request $request): RedirectResponse\n    {\n        $request->validate([\n            'token' => 'required',\n            'email' => 'required|email',\n            'password' => ['required', 'confirmed', Rules\\Password::defaults()],\n        ]);\n\n        // Here we will attempt to reset the user's password. If it is successful we\n        // will update the password on an actual user model and persist it to the\n        // database. Otherwise we will parse the error and return the response.\n        $status = Password::reset(\n            $request->only('email', 'password', 'password_confirmation', 'token'),\n            function ($user) use ($request) {\n                $user->forceFill([\n                    'password' => Hash::make($request->password),\n                    'remember_token' => Str::random(60),\n                ])->save();\n\n                event(new PasswordReset($user));\n            }\n        );\n\n        // If the password was successfully reset, we will redirect the user back to\n        // the application's home authenticated view. If there is an error we can\n        // redirect them back to where they came from with their error message.\n        if ($status == Password::PASSWORD_RESET) {\n            return redirect()->route('login')->with('status', __($status));\n        }\n\n        throw ValidationException::withMessages([\n            'email' => [trans($status)],\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/PasswordController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Hash;\nuse Illuminate\\Validation\\Rules\\Password;\n\nclass PasswordController extends Controller\n{\n    /**\n     * Update the user's password.\n     */\n    public function update(Request $request): RedirectResponse\n    {\n        $validated = $request->validate([\n            'current_password' => ['required', 'current_password'],\n            'password' => ['required', Password::defaults(), 'confirmed'],\n        ]);\n\n        $request->user()->update([\n            'password' => Hash::make($validated['password']),\n        ]);\n\n        return back();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/PasswordResetLinkController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Password;\nuse Illuminate\\Validation\\ValidationException;\nuse Inertia\\Inertia;\nuse Inertia\\Response;\n\nclass PasswordResetLinkController extends Controller\n{\n    /**\n     * Display the password reset link request view.\n     */\n    public function create(): Response\n    {\n        return Inertia::render('Auth/ForgotPassword', [\n            'status' => session('status'),\n        ]);\n    }\n\n    /**\n     * Handle an incoming password reset link request.\n     *\n     * @throws \\Illuminate\\Validation\\ValidationException\n     */\n    public function store(Request $request): RedirectResponse\n    {\n        $request->validate([\n            'email' => 'required|email',\n        ]);\n\n        // We will send the password reset link to this user. Once we have attempted\n        // to send the link, we will examine the response then see the message we\n        // need to show to the user. Finally, we'll send out a proper response.\n        $status = Password::sendResetLink(\n            $request->only('email')\n        );\n\n        if ($status == Password::RESET_LINK_SENT) {\n            return back()->with('status', __($status));\n        }\n\n        throw ValidationException::withMessages([\n            'email' => [trans($status)],\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/RegisteredUserController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Events\\Registered;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Hash;\nuse Illuminate\\Validation\\Rules;\nuse Inertia\\Inertia;\nuse Inertia\\Response;\n\nclass RegisteredUserController extends Controller\n{\n    /**\n     * Display the registration view.\n     */\n    public function create(): Response\n    {\n        return Inertia::render('Auth/Register');\n    }\n\n    /**\n     * Handle an incoming registration request.\n     *\n     * @throws \\Illuminate\\Validation\\ValidationException\n     */\n    public function store(Request $request): RedirectResponse\n    {\n        $request->validate([\n            'name' => 'required|string|max:255',\n            'email' => 'required|string|lowercase|email|max:255|unique:'.User::class,\n            'password' => ['required', 'confirmed', Rules\\Password::defaults()],\n        ]);\n\n        $user = User::create([\n            'name' => $request->name,\n            'email' => $request->email,\n            'password' => Hash::make($request->password),\n        ]);\n\n        event(new Registered($user));\n\n        Auth::login($user);\n\n        return redirect(route('admin.dashboard', absolute: false));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/SocialiteController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse Abraham\\TwitterOAuth\\TwitterOAuth;\nuse App\\Exceptions\\SocialProviderDeniedException;\nuse App\\Http\\Controllers\\Controller;\nuse App\\Models\\SocialiteProvider;\nuse App\\Traits\\SocialiteProvidersTrait;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Response;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Facades\\Config;\nuse Illuminate\\Support\\Facades\\Crypt;\nuse Illuminate\\Support\\Facades\\Log;\nuse Laravel\\Socialite\\Facades\\Socialite;\n\nclass SocialiteController extends Controller\n{\n    use SocialiteProvidersTrait;\n\n    private $providerSettings;\n    private $providerConfigs;\n\n    public function __construct()\n    {\n        $this->setupProviders();\n\n        try {\n            ob_start('ob_gzhandler');\n        } catch (\\Exception $e) {\n            //\n        }\n    }\n\n    public function guard($guard = 'web')\n    {\n        return Auth::guard($guard);\n    }\n\n    /**\n     * Get a list of enabled socialite logins.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function loginsEnabled(Request $request)\n    {\n        return response()->json([\n            'logins' => $this->loginsList(),\n        ]);\n    }\n\n    /**\n     * Gets the social redirect.\n     *\n     * @param  string  $provider  The provider\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function getSocialRedirect(Request $request, string $provider)\n    {\n        $providerKey = Config::get('services.'.$provider);\n\n        if (empty($providerKey)) {\n            abort(419);\n        }\n\n        $url = null;\n        $token = null;\n        $state = null;\n        $user = null;\n        $scopes = [];\n        $with = [];\n\n        if (auth('sanctum')->check()) {\n            $user = auth('sanctum')->user();\n        }\n\n        if ($user) {\n            $token = $user->createToken($provider.'-user-token')->plainTextToken;\n            $state = Crypt::encrypt($token);\n        } else {\n            $state = Crypt::encrypt(config('app.key'));\n        }\n\n        $with = ['state' => $state];\n\n        // https://developers.facebook.com/docs/instagram-basic-display-api/guides/getting-access-tokens-and-permissions/\n        if ($provider == 'instagram') {\n            $scopes = ['user_profile'];\n            $with += ['response_type' => 'code'];\n        }\n\n        // https://docs.snap.com/snap-kit/login-kit/Tutorials/web#understand-scopes\n        if ($provider == 'snapchat') {\n            $scopes = [\n                'https://auth.snapchat.com/oauth2/api/user.display_name',\n                'https://auth.snapchat.com/oauth2/api/user.external_id',\n                'https://auth.snapchat.com/oauth2/api/user.bitmoji.avatar',\n            ];\n            $with += ['response_type' => 'code'];\n        }\n\n        if ($provider == 'tiktok') {\n            $scopes = [\n                'user.info.basic',\n            ];\n            $with += ['response_type' => 'code'];\n        }\n\n        if ($provider == 'twitter') {\n            $url = $this->twitterUserAuthenticationUrl($state);\n        } else {\n            $url = Socialite::driver($provider)\n                        ->stateless()\n                        ->with($with)\n                        ->scopes($scopes)\n                        ->redirect()\n                        ->getTargetUrl();\n        }\n\n        if ($provider == 'stackexchange') {\n            $url = $this->cacheStatePutKeyInUrl($url, $state);\n        }\n\n        return response()->json([\n            'url' => $url,\n        ]);\n    }\n\n    /**\n     * Gets the social handle information from the provider.\n     *\n     * @param  string  $provider  The provider\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function handleSocialCallback(Request $request, string $provider)\n    {\n        $denied = $request->denied ? $request->denied : null;\n        if ($denied != null || $denied != '') {\n            throw new SocialProviderDeniedException;\n        }\n\n        if ($provider == 'twitter') {\n            $socialUser = $this->twitterUserAuthentication($request);\n            $state = $request->state ? Crypt::decrypt(Cache::pull($request->state)) : null;\n        } elseif ($provider == 'stackexchange') {\n            $socialUser = Socialite::driver($provider)->stateless()->user();\n            $state = $request->state ? Crypt::decrypt(Cache::pull($request->state)) : null;\n        } else {\n            $socialUser = Socialite::driver($provider)->stateless()->user();\n            $state = $request->state ? Crypt::decrypt($request->state) : null;\n        }\n\n        $userData = $this->findOrCreateUser($provider, $socialUser, $state);\n\n        $user = $userData['user'];\n        $token = $userData['token'];\n\n        if ($user && $token) {\n            auth()->login($user);\n        } else {\n            $token = 'cannot_add';\n        }\n\n        return view('socialite/callback', [\n            'token'         => $token,\n            'token_type'    => 'bearer',\n        ]);\n    }\n\n    /**\n     * Get Twitter Oauth1.0 Url built with identifier if user is present.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return array\n     */\n    public function twitterUserAuthenticationUrl($state = null)\n    {\n        $consumerKey = config('services.twitter.client_id');\n        $consumerSecret = config('services.twitter.client_secret');\n        $consumerRedirect = config('services.twitter.redirect');\n\n        $connection = new TwitterOAuth($consumerKey, $consumerSecret);\n\n        $tempId = $this->generateTempId();\n        $requestToken = $connection->oauth('oauth/request_token', [\n            'oauth_callback' => $consumerRedirect.'?state='.$tempId,\n        ]);\n\n        $this->tempStoreStateInCache($tempId, $state);\n\n        $url = $connection->url('oauth/authorize', [\n            'oauth_token' => $requestToken['oauth_token'],\n        ]);\n\n        return $url;\n    }\n\n    /**\n     * Get Twitter user credentials from Oauth1.0.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return array\n     */\n    public function twitterUserAuthentication(Request $request)\n    {\n        $consumerKey = config('services.twitter.client_id');\n        $consumerSecret = config('services.twitter.client_secret');\n        $consumerRedirect = config('services.twitter.redirect');\n\n        $connection = new TwitterOAuth($consumerKey, $consumerSecret, $request->oauth_token);\n\n        $access_token = $connection->oauth('oauth/access_token', [\n            'oauth_verifier'    => $request->oauth_verifier,\n            'oauth_token'       => $request->oauth_token,\n        ]);\n\n        $connection = new TwitterOAuth($consumerKey, $consumerSecret, $access_token['oauth_token'], $access_token['oauth_token_secret']);\n\n        return $connection->get('account/verify_credentials', [\n            'include_email'     => true,\n            'skip_status'       => true,\n            'include_entities'  => false,\n        ]);\n    }\n\n    /**\n     * Revoke a social media login provider for\n     * a user from the app and from the provider.\n     *\n     * @param  \\App\\Models\\SocialiteProvider  $provider\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function revokeSocialProvider(SocialiteProvider $provider, Request $request)\n    {\n        $user = auth('sanctum')->user();\n\n        if ($provider->user_id != $user->id) {\n            abort(403);\n        }\n\n        $provider->delete();\n\n        return response()->json([\n            'status'    => 'success',\n            'provider'  => $provider,\n            'user'      => $user,\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Auth/VerifyEmailController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Auth;\n\nuse App\\Http\\Controllers\\Controller;\nuse Illuminate\\Auth\\Events\\Verified;\nuse Illuminate\\Foundation\\Auth\\EmailVerificationRequest;\nuse Illuminate\\Http\\RedirectResponse;\n\nclass VerifyEmailController extends Controller\n{\n    /**\n     * Mark the authenticated user's email address as verified.\n     */\n    public function __invoke(EmailVerificationRequest $request): RedirectResponse\n    {\n        if ($request->user()->hasVerifiedEmail()) {\n            return redirect()->intended(route('admin.dashboard', absolute: false).'?verified=1');\n        }\n\n        if ($request->user()->markEmailAsVerified()) {\n            event(new Verified($request->user()));\n        }\n\n        return redirect()->intended(route('admin.dashboard', absolute: false).'?verified=1');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Controller.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Foundation\\Auth\\Access\\AuthorizesRequests;\nuse Illuminate\\Foundation\\Validation\\ValidatesRequests;\nuse Illuminate\\Routing\\Controller as BaseController;\n\nabstract class Controller extends BaseController\n{\n    use AuthorizesRequests, ValidatesRequests;\n}\n"
  },
  {
    "path": "app/Http/Controllers/CourseController.php",
    "content": "<?php\n\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Http\\Resources\\CourseResource;\nuse App\\Models\\Course;\nuse Auth;\nuse Illuminate\\Http\\Request;\nuse Inertia\\Inertia;\n\nclass CourseController extends Controller\n{\n\n\n    /**\n     * Show the application dashboard.\n     *\n     * @return \\Illuminate\\Contracts\\Support\\Renderable\n     */\n    public function show(Request $request, Course $course)\n    {\n        $course->loadCount(['lessons', 'exams', 'sections', 'students']);\n        $course->load(['subjects', 'topics', 'teachers']);\n\n        return Inertia::render('Course/Course', [\n            'course' => new CourseResource($course)\n        ]);\n    }\n\n    public function subscribe(Request $request, Course $course)\n    {\n        $user = $request->user();\n\n        $enrolled =  $user->enrolledCourses->firstWhere('id', $course->id);\n\n\n        if($enrolled) {\n            return response()->json([],200);\n        }\n\n        $user->enrolledCourses()->attach($course);\n\n        $lessons = $course->lessons->pluck('id');\n\n        $user->enrolledLessons()->attach($lessons);\n\n        return response()->json([],200);\n    }\n}"
  },
  {
    "path": "app/Http/Controllers/DownloadController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\File;\nuse Illuminate\\Http\\Request;\nuse App\\Response\\DownloadResponse;\n\nclass DownloadController extends Controller\n{\n    /**\n     * @var Request\n     */\n    private $request;\n\n    /**\n     * @var File\n     */\n    private $file;\n    /**\n     * download response.\n     *\n     * @var DownloadResponse\n     */\n    private $downloadResponse;\n\n    public function __construct(Request $request, File $file, DownloadResponse $downloadResponse)\n    {\n        $this->request = $request;\n        $this->file = $file;\n\n        $this->downloadResponse = $downloadResponse;\n    }\n\n    public function download(Request $request)\n    {\n        $ids = $request->get('ids');\n\n        if (sizeof($ids) > 1) {\n            return $this->downloadResponse->multipleDownload($ids);\n        } else {\n            return $this->downloadResponse->singleDownload($ids[0]);\n        }\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/HomeController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Http\\Resources\\CourseResource;\nuse App\\Http\\Resources\\SubjectResource;\nuse App\\Models\\Course;\nuse App\\Models\\Subject;\nuse Illuminate\\Http\\Request;\nuse Inertia\\Inertia;\n\nclass HomeController extends Controller\n{\n    /**\n     * Show the application dashboard.\n     *\n     * @return \\Illuminate\\Contracts\\Support\\Renderable\n     */\n    public function __invoke(Request $request)\n    {\n        $subjects = Subject::withCount(['courses', 'exams'])\n            ->with(['courses', 'exams'])\n            ->whereHas('courses')\n            ->get();\n\n        $featuredCourses = Course::with(['teachers', 'subjects'])\n            ->withCount(['lessons', 'students'])\n            ->latest()\n            ->limit(8)\n            ->get();\n\n        return Inertia::render('Home/Home', [\n            'subjects'        => SubjectResource::collection($subjects),\n            'featuredCourses' => CourseResource::collection($featuredCourses),\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/InstructorController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Actions\\GetInstratorCousesAction;\nuse App\\Models\\User;\nuse Inertia\\Inertia;\nuse Illuminate\\Http\\Request;\n\nclass InstructorController extends Controller\n{\n\n\n    /**\n     * Show the application dashboard.\n     *\n     * @return \\Illuminate\\Contracts\\Support\\Renderable\n     */\n    public function courses(Request $request)\n    {\n        if ($request->user)\n        {\n            $user = User::where('name', $request->user)->first();\n        }else {\n            $user = $request->user();\n        }\n        \n        if(!$user) {\n            return to_route('home');\n        }\n\n        return Inertia::render('Instructor/Courses', [\n            'courses' => GetInstratorCousesAction::getCourses($user),\n            'canModify' => $request->user()->id == $user->id\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/LearningController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Actions\\CourseWithSections;\nuse Auth;\nuse Inertia\\Inertia;\nuse App\\Models\\Course;\nuse Illuminate\\Http\\Request;\nuse App\\Actions\\GetEnrolledCousesAction;\nuse App\\Http\\Resources\\CourseResource;\nuse App\\Http\\Resources\\ExamResource;\nuse App\\Http\\Resources\\LessonResource;\nuse App\\Models\\Exam;\nuse App\\Models\\Lesson;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass LearningController extends Controller\n{\n\n\n    /**\n     * Show the application dashboard.\n     *\n     * @return \\Illuminate\\Contracts\\Support\\Renderable\n     */\n    public function myCourses(Request $request)\n    {\n        $user = $request->user();\n\n        return Inertia::render('Learning/Courses', [\n            'courses' => GetEnrolledCousesAction::getCourses($user),\n            'canModify' => $request->user()->id == $user->id\n        ]);\n    }\n\n    public function startCourse(Course $course)\n    {\n        $last = DB::table('course_students')->where('course_id', $course->id)->first()->last_lesson;\n\n        if (!$last) {\n            $course = CourseWithSections::getCourses($course);\n            $firstResource = $course->sections?->first()?->resources?->first();\n\n            if ($firstResource) {\n                if (is_a($firstResource, Lesson::class)) {\n                    $type = 'lesson';\n                    $slug = $firstResource->slug;\n                } else {\n                    $type = 'exam';\n                    $slug = $firstResource->slug;\n                }\n            }\n\n            return to_route('start.resource', [$course->slug, $type, $slug]);\n        }\n\n    }\n\n    public function singleResource(Course $course, $type, $slug)\n    {\n        if ($type == 'lesson') {\n            $resource = new LessonResource(Lesson::where('slug', $slug)->first()) ;\n        } else {\n            $resource = new ExamResource(Exam::where('slug', $slug)->first()) ;\n        }\n        \n        return Inertia::render('Learning/SingleResource', [\n            'course' => CourseWithSections::getCourses($course),\n            'resource' => $resource\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/ProfileController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Http\\Requests\\ProfileUpdateRequest;\nuse Illuminate\\Contracts\\Auth\\MustVerifyEmail;\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Redirect;\nuse Inertia\\Inertia;\nuse Inertia\\Response;\n\nclass ProfileController extends Controller\n{\n    /**\n     * Display the user's profile form.\n     */\n    public function edit(Request $request): Response\n    {\n        return Inertia::render('Profile/Edit', [\n            'mustVerifyEmail' => $request->user() instanceof MustVerifyEmail,\n            'status' => session('status'),\n        ]);\n    }\n\n    /**\n     * Update the user's profile information.\n     */\n    public function update(ProfileUpdateRequest $request): RedirectResponse\n    {\n        $request->user()->fill($request->validated());\n\n        if ($request->user()->isDirty('email')) {\n            $request->user()->email_verified_at = null;\n        }\n\n        $request->user()->save();\n\n        return Redirect::route('profile.edit');\n    }\n\n    /**\n     * Delete the user's account.\n     */\n    public function destroy(Request $request): RedirectResponse\n    {\n        $request->validate([\n            'password' => ['required', 'current_password'],\n        ]);\n\n        $user = $request->user();\n\n        Auth::logout();\n\n        $user->delete();\n\n        $request->session()->invalidate();\n        $request->session()->regenerateToken();\n\n        return Redirect::to('/');\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/UploadController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\File;\nuse App\\Response\\FileContentResponseCreator;\n\nclass UploadController extends Controller\n{\n    /**\n     * Create a new controller instance.\n     */\n    public function __invoke(FileContentResponseCreator $fileResponse, $id)\n    {\n        $entry = File::where('file_name', $id)->first();\n\n        return $fileResponse->create($entry);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/HandleInertiaRequests.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Illuminate\\Http\\Request;\nuse Inertia\\Middleware;\n\nclass HandleInertiaRequests extends Middleware\n{\n    /**\n     * The root template that is loaded on the first page visit.\n     *\n     * @var string\n     */\n    protected $rootView = 'app';\n\n    /**\n     * Determine the current asset version.\n     */\n    public function version(Request $request): string|null\n    {\n        return parent::version($request);\n    }\n\n    /**\n     * Define the props that are shared by default.\n     *\n     * @return array<string, mixed>\n     */\n    public function share(Request $request): array\n    {\n        return [\n            ...parent::share($request),\n            'auth' => [\n                'user' => $request->user(),\n            ],\n            'appEnv' => app()->environment(),\n            'flash' => [\n                'success' => $request->session()->get('success'),\n                'error'   => $request->session()->get('error'),\n            ],\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/Admin/StoreCoursesRequest.php",
    "content": "<?php\nnamespace App\\Http\\Requests\\Admin;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass StoreCoursesRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'teachers.*' => 'exists:users,id',\n            'title' => 'required',\n            'start_date' => 'date_format:'.config('app.date_format'),\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/Admin/UpdateCoursesRequest.php",
    "content": "<?php\nnamespace App\\Http\\Requests\\Admin;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass UpdateCoursesRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            \n            'teachers.*' => 'exists:users,id',\n            'title' => 'required',\n            'start_date' => 'date_format:'.config('app.date_format'),\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/Admin/UserRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests\\Admin;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass UserRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     */\n    public function authorize(): bool\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array<string, \\Illuminate\\Contracts\\Validation\\ValidationRule|array<mixed>|string>\n     */\n    public function rules(): array\n    {\n        return [\n            //\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/Auth/LoginRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests\\Auth;\n\nuse Illuminate\\Auth\\Events\\Lockout;\nuse Illuminate\\Foundation\\Http\\FormRequest;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\RateLimiter;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Validation\\ValidationException;\n\nclass LoginRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     */\n    public function authorize(): bool\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array<string, \\Illuminate\\Contracts\\Validation\\Rule|array|string>\n     */\n    public function rules(): array\n    {\n        return [\n            'email' => ['required', 'string', 'email'],\n            'password' => ['required', 'string'],\n        ];\n    }\n\n    /**\n     * Attempt to authenticate the request's credentials.\n     *\n     * @throws \\Illuminate\\Validation\\ValidationException\n     */\n    public function authenticate(): void\n    {\n        $this->ensureIsNotRateLimited();\n\n        if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {\n            RateLimiter::hit($this->throttleKey());\n\n            throw ValidationException::withMessages([\n                'email' => trans('auth.failed'),\n            ]);\n        }\n\n        RateLimiter::clear($this->throttleKey());\n    }\n\n    /**\n     * Ensure the login request is not rate limited.\n     *\n     * @throws \\Illuminate\\Validation\\ValidationException\n     */\n    public function ensureIsNotRateLimited(): void\n    {\n        if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {\n            return;\n        }\n\n        event(new Lockout($this));\n\n        $seconds = RateLimiter::availableIn($this->throttleKey());\n\n        throw ValidationException::withMessages([\n            'email' => trans('auth.throttle', [\n                'seconds' => $seconds,\n                'minutes' => ceil($seconds / 60),\n            ]),\n        ]);\n    }\n\n    /**\n     * Get the rate limiting throttle key for the request.\n     */\n    public function throttleKey(): string\n    {\n        return Str::transliterate(Str::lower($this->string('email')).'|'.$this->ip());\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/ExamRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass ExamRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'title' => 'required|min:5|max:255'\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/ProfileUpdateRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse App\\Models\\User;\nuse Illuminate\\Foundation\\Http\\FormRequest;\nuse Illuminate\\Validation\\Rule;\n\nclass ProfileUpdateRequest extends FormRequest\n{\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array<string, \\Illuminate\\Contracts\\Validation\\Rule|array|string>\n     */\n    public function rules(): array\n    {\n        return [\n            'name' => ['required', 'string', 'max:255'],\n            'email' => ['required', 'string', 'lowercase', 'email', 'max:255', Rule::unique(User::class)->ignore($this->user()->id)],\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/QuestionRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass QuestionRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'question' => 'required',\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/SettingRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass SettingRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return false;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'key' => 'required',\n            'value' => 'required',\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/SubjectRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass SubjectRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'title' => 'required'\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/TopicRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass TopicRequest extends FormRequest\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        return [\n            'title' => 'required'\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/CourseResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\Course */\nclass CourseResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'title' => $this->title,\n            'subtitle' => $this->subtitle,\n            'slug' => $this->slug,\n            'description' => $this->description,\n            'requirements' => $this->requirements,\n            'price' => $this->price,\n            'discount' => $this->discount,\n            'status' => $this->status,\n            'thumbnail' => $this->thumbnail,\n            'start_date' => $this->start_date,\n            'features' => $this->features,\n            'permalink' => $this->permalink,\n            'rating' => $this->rating,\n            'certified' => $this->certified,\n            'created_at' => $this->created_at,\n            'updated_at' => $this->updated_at,\n            'teachers' => UserResource::collection($this->whenLoaded('teachers')),\n            'students' => UserResource::collection($this->whenLoaded('students')),\n            'sections' => SectionResource::collection($this->whenLoaded('sections')),\n            'lessons' => LessonResource::collection($this->whenLoaded('lessons')),\n            'exams' => ExamResource::collection($this->whenLoaded('exams')),\n            'topics' => TopicResource::collection($this->whenLoaded('topics')),\n            'subjects' => SubjectResource::collection($this->whenLoaded('subjects')),\n            'lessons_count' => $this->whenCounted('lessons'),\n            'students_count' => $this->whenCounted('students'),\n            'sections_count' => $this->whenCounted('sections'),\n            'exams_count' => $this->whenCounted('exams'),\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/CourseStudentsResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\User */\nclass CourseStudentsResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'name' => $this->name,\n            'full_name' => $this->full_name,\n            'avatar' => $this->avatar,\n            'rating' => $this->pivot->rating,\n            'progress' => $this->pivot->progress\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/ExamResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\Exam */\nclass ExamResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'title' => $this->title,\n            'description' => $this->description,\n            'permalink' => $this->permalink,\n            'status' => $this->status,\n            'price' => $this->price,\n            'duration' => $this->duration,\n            'pass_mark' => $this->pass_mark,\n            'meta' => $this->meta,\n            'number_of_questions' => $this->number_of_questions,\n            'random_questions' => (boolean) $this->random_questions,\n            'certification' => (boolean) $this->certification,\n            'difficulty' => $this->difficulty,\n            'created_at' => $this->created_at,\n            'updated_at' => $this->updated_at,\n            'subjects' => SubjectResource::collection($this->whenLoaded('subjects')),\n            'courses' => CourseResource::collection($this->whenLoaded('courses')),\n            'questions' => QuestionResource::collection($this->whenLoaded('questions')),\n            'examiner' => new UserResource($this->whenLoaded('examiner')),\n            'topics' => TopicResource::collection($this->whenLoaded('topics')),\n            'results' => ResultResource::collection($this->whenLoaded('results')),\n            'pivot' => $this->when($this->pivot, [\n                'sectionable_type' => $this->pivot->sectionable_type,\n                'order' => $this->pivot->order\n            ])\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/FileResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\File */\nclass FileResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'name' => $this->name,\n            'description' => $this->description,\n            'path' => $this->path,\n            'file_name' => $this->file_name,\n            'extension' => $this->extension,\n            'mime' => $this->mime,\n            'type' => $this->type,\n            'public_path' => $this->public_path,\n            'parent_id' => $this->parent_id,\n            'uploaded_by' => $this->uploaded_by,\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/LessonResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\Lesson */\nclass LessonResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n\n        $lesson =  [\n            'id' => $this->id,\n            'title' => $this->title,\n            'slug' => $this->slug,\n            'thumbnail' => $this->thumbnail,\n            'type' => $this->type,\n            'object' => $this->object,\n            'short_text' => $this->short_text,\n            'full_text' => $this->full_text,\n            'position' => $this->position,\n            'status' => $this->status,\n            'created_at' => $this->created_at,\n            'updated_at' => $this->updated_at,\n            'courses' => CourseResource::collection($this->whenLoaded('courses')),\n            'students' => UserResource::collection($this->whenLoaded('students')),\n            'sections' => SectionResource::collection($this->whenLoaded('sections')),\n        ];\n\n        if ($this->pivot) {\n            $lesson['pivot'] = [\n                'sectionable_type' => $this->pivot->sectionable_type,\n                'order' => $this->pivot->order\n            ];\n        }\n\n        return $lesson;\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/QuestionResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\Question */\nclass QuestionResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'qtype' => $this->qtype,\n            'question' => $this->question,\n            'options' => $this->options,\n            'answers' => $this->answers,\n            'hint' => $this->hint,\n            'mark' => $this->mark,\n            'nmark' => $this->nmark,\n            'explanation' => $this->explanation,\n            'created_at' => $this->created_at,\n            'updated_at' => $this->updated_at,\n            'topics' => TopicResource::collection($this->whenLoaded('topics')),\n            'exam' => new ExamResource($this->whenLoaded('exam')),\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/ResultResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\Result */\nclass ResultResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'answers' => $this->answers,\n            'obtain_mark' => $this->obtain_mark,\n            'is_pass' => $this->is_pass,\n            'time_taken' => $this->time_taken,\n            'created_at' => $this->created_at,\n            'updated_at' => $this->updated_at,\n            'examinee' => new UserResource($this->whenLoaded('examinee')),\n            'exam' => new ExamResource($this->whenLoaded('exam')),\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/RoleResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\Role */\nclass RoleResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'name' => $this->name,\n            'guard_name' => $this->guard_name,\n            'permissions' => $this->permissions->toArray(),\n            'users_count' => $this->users_count ?? 0,\n            'permissions_count' => $this->permissions_count ?? 0,\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/SectionResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse App\\Models\\Lesson;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Resources\\ExamResource;\nuse App\\Http\\Resources\\LessonResource;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\Section */\nclass SectionResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'title' => $this->title,\n            'description' => $this->description,\n            'created_at' => $this->created_at,\n            'updated_at' => $this->updated_at,\n            'lessons' => LessonResource::collection($this->whenLoaded('lessons')),\n            'exams' => ExamResource::collection($this->whenLoaded('exams')),\n            'resources' => $this->transform($this->resources, function($resources){\n                return $resources->map(function($resource) {\n                    if (is_a($resource, Lesson::class)) {\n                        return new LessonResource($resource);\n                    } else {\n                        return new ExamResource($resource);\n                    }\n                });\n            })\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/SubjectResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\Subject */\nclass SubjectResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'title' => $this->title,\n            'slug' => $this->slug,\n            'description' => $this->description,\n            'icon' => $this->icon,\n            'image' => $this->image,\n            'image_url' => $this->image_url,\n            'parent' => $this->parent,\n            'children_count' => $this->resource->children_count ?? 0,\n            'created_at' => $this->created_at,\n            'updated_at' => $this->updated_at,\n            'courses_count' => $this->when($this->courses_count, $this->courses_count),\n            'exams_count' => $this->when($this->exams_count, $this->exams_count),\n            'courses' => CourseResource::collection($this->whenLoaded('courses')),\n            'exams' => CourseResource::collection($this->whenLoaded('exams')),\n            'children' => SubjectResource::collection($this->whenLoaded('children')),\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/TopicResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\Topic */\nclass TopicResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'title' => $this->title,\n            'description' => $this->description,\n            'created_at' => $this->created_at,\n            'updated_at' => $this->updated_at,\n            'courses_count' => $this->when($this->courses_count, $this->courses_count),\n            'exams_count' => $this->when($this->exams_count, $this->exams_count),\n            'courses' => CourseResource::collection($this->whenLoaded('courses')),\n            'exams' => CourseResource::collection($this->whenLoaded('exams')),\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Resources/UserResource.php",
    "content": "<?php\n\nnamespace App\\Http\\Resources;\n\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\n\n/** @mixin \\App\\Models\\User */\nclass UserResource extends JsonResource\n{\n    /**\n     * Transform the resource into an array.\n     *\n     * @return array<string, mixed>\n     */\n    public function toArray(Request $request): array\n    {\n        return [\n            'id' => $this->id,\n            'name' => $this->name,\n            'firstname' => $this->firstname,\n            'lastname' => $this->lastname,\n            'full_name' => $this->full_name,\n            'email' => $this->email,\n            'avatar' => $this->avatar,\n            'email_verified_at' => $this->email_verified_at?->format('Y-m-d H:i:s'),\n            'created_at' => $this->created_at->format('Y-m-d H:i:s'),\n            'updated_at' => $this->updated_at->format('Y-m-d H:i:s'),\n            'deleted_at' => $this->deleted_at?->format('Y-m-d H:i:s'),\n            'roles' => RoleResource::collection($this->whenLoaded('roles')),\n            'results' => ResultResource::collection($this->whenLoaded('results')),\n            'instructCourses' => CourseResource::collection($this->whenLoaded('instructCourses')),\n            'enrolledCourses' => CourseResource::collection($this->whenLoaded('enrolledCourses')),\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Jobs/ResizedImage.php",
    "content": "<?php\n\nnamespace App\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\nuse Intervention\\Image\\Facades\\Image;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Http\\File as FileAdapdar;\nuse App\\Models\\File;\n\nclass ResizedImage implements ShouldQueue\n{\n    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;\n\n    /**\n     * App\\File object.\n     *\n     * @var App\\Models\\File;\n     */\n    protected $file;\n\n    /**\n     * Create a new job instance.\n     */\n    public function __construct(File $file)\n    {\n        $this->file = $file;\n    }\n\n    /**\n     * Execute the job.\n     */\n    public function handle()\n    {\n        // we cant anything without image\n        if ($this->file->type !== 'image') {\n            return;\n        }\n\n        // get sizes of images\n        $meta = $this->file->meta;\n        $sizes = $meta['sizes'];\n        // there are not any sizes;\n        if (!is_array($sizes)) {\n            return;\n        }\n\n        /*\n         * is file in cloude then,\n         * Download from cloud to local then resize it.\n         */\n\n        if ($this->file->driver == config('filesystems.cloud')) {\n            if (!Storage::disk(config('filesystems.cloud'))->exists($this->file->getStoragePath())) {\n                throw new Exception();\n            }\n            $s3file = Storage::disk(config('filesystems.cloud'))->get($this->file->getStoragePath());\n            Storage::disk('local')->put(\"{$this->file->file_name}/{$this->file->name}\", $s3file);\n        }\n\n        $path = storage_path(\"app/uploads/{$this->file->file_name}\");\n        $file = new FileAdapdar(\"{$path}/{$this->file->name}\");\n        $public = 'public';\n\n        foreach ($sizes as $key => $value) {\n            // already we resized this size\n            if ($value == true) {\n                continue;\n            }\n\n            // Image not resized let resize it\n            $rs = explode('x', $key); // [150, 50]\n\n            //  create Intervention images\n            $image = Image::make($file)->resize($rs[0], $rs[1]);\n\n            $localFile = \"{$path}/{$key}-{$this->file->name}\";\n            $image->save($localFile);\n\n            if ($this->file->driver == config('filesystems.cloud')) {\n                Storage::disk(config('filesystems.cloud'))->putFileAs($this->file->file_name, new FileAdapdar($localFile), \"{$key}-{$this->file->name}\", $public);\n            }\n\n            $sizes[$key] = true;\n        }\n\n        // save meta values;\n        $meta['sizes'] = $sizes;\n        $this->file->meta = $meta;\n        if ($this->file->isDirty()) {\n            $this->file->save();\n        }\n\n        if ($this->file->driver == config('filesystems.cloud')) {\n            Storage::deleteDirectory($path);\n        }\n    }\n}\n"
  },
  {
    "path": "app/Jobs/UploadToCloud.php",
    "content": "<?php\n\nnamespace App\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Queue\\SerializesModels;\nuse Illuminate\\Queue\\InteractsWithQueue;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Http\\File as FileAdapdar;\nuse App\\Models\\File;\n\nclass UploadToCloud implements ShouldQueue\n{\n    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;\n    /**\n     * App\\File object.\n     *\n     * @var App\\Models\\File;\n     */\n    protected $file;\n\n    /**\n     * Create a new job instance.\n     */\n    public function __construct(File $file)\n    {\n        $this->file = $file;\n    }\n\n    /**\n     * Execute the job.\n     */\n    public function handle()\n    {\n        $disk = config('filesystems.cloud');\n        // is already uploaded\n        if ($this->file->driver == $disk) {\n            return;\n        }\n\n        $path = storage_path('app/uploads/');\n        $public = 'public';\n\n        $localfiles = Storage::disk('local')->allFiles($this->file->file_name);\n\n        foreach ($localfiles as $lfile) {\n            Storage::disk($disk)->putFileAs($this->file->file_name, new FileAdapdar(\"{$path}/{$lfile}\"), $this->file->name, $public);\n        }\n        // save to path;\n        $this->file->updatePublicPaths($disk);\n\n        // wait 5 second to delete directorr so all local request is complete and new request to cloud\n        sleep(5);\n        Storage::disk('local')->deleteDirectory($this->file->file_name);\n    }\n}\n"
  },
  {
    "path": "app/Models/Course.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Models\\Exam;\nuse Illuminate\\Support\\Carbon;\nuse App\\Models\\Traits\\Fileable;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\n\n/**\n * @property int $id\n * @property string $title\n * @property string $subtitle\n * @property string $slug\n * @property string $description\n * @property string $features\n * @property string $requirements\n * @property string $thumbnail\n * @property int $price\n * @property int $discount\n * @property int $status\n * @property int $created_by\n * @property int $updated_by\n * @property bool $certified\n * @property Carbon $start_date\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property Collection<User> $teachers\n * @property Collection<User> $students\n * @property Collection<Sections> $sections\n * @property Collection<Lesson> $lessons\n * @property Collection<Lesson> $publishedLessons\n * @property Collection<Exam> $exams\n * @property Collection<Topic> $topics\n * @property Collection<Subject> $subjects\n */\n\nclass Course extends Model\n{\n    use SoftDeletes, Fileable, HasFactory;\n\n    protected $fillable = [\n        'title',\n        'subtitle',\n        'slug',\n        'description',\n        'requirements',\n        'price',\n        'discount',\n        'thumbnail',\n        'start_date',\n        'status',\n        'features',\n        'certified',\n        'created_by',\n        'updated_by'\n    ];\n    /*\n    |--------------------------------------------------------------------------\n    | ACCESORS Variables\n    |--------------------------------------------------------------------------\n    */\n    protected $with = [\n        'thumbnail'\n    ];\n\n    protected $appends = [\n        'permalink',\n    ];\n\n    protected $casts = [\n        'features' => 'array'\n    ];\n\n    /*\n    |--------------------------------------------------------------------------\n    | Booting\n    |--------------------------------------------------------------------------\n    */\n\n\n\n\n    /*\n    |--------------------------------------------------------------------------\n    | ACCESORS\n    |--------------------------------------------------------------------------\n    */\n    public function getRatingAttribute()\n    {\n        return number_format(DB::table('course_students')->where('course_id', $this->attributes['id'])->average('rating'), 2);\n    }\n\n    public function getPermalinkAttribute()\n    {\n        return route('course.show', ['course' => $this->slug]);\n    }\n    /**\n     * Set attribute to money format\n     * @param $input\n     */\n    public function setPriceAttribute($input)\n    {\n        $this->attributes['price'] = $input ? $input : null;\n    }\n    /*\n    |--------------------------------------------------------------------------\n    | Scopes\n    |--------------------------------------------------------------------------\n    */\n    public function scopeOfTeacher($query)\n    {\n\n        return $query->whereHas('teachers', function ($q) {\n            $q->where('user_id', Auth::user()->id);\n        });\n    }\n\n    /*\n    |--------------------------------------------------------------------------\n    | RELATIONS\n    |--------------------------------------------------------------------------\n    */\n    public function teachers()\n    {\n        return $this->belongsToMany(User::class, 'course_teachers');\n    }\n\n    public function students()\n    {\n        return $this->belongsToMany(User::class, 'course_students')->withTimestamps()->withPivot(['rating', 'progress']);\n    }\n\n    public function sections()\n    {\n        return $this->hasMany(Section::class);\n    }\n\n    public function lessons()\n    {\n        return $this->belongsToMany(Lesson::class, 'sectionables', 'course_id', 'sectionable_id')->wherePivot('sectionable_type', Lesson::class);\n    }\n\n    public function publishedLessons()\n    {\n        return $this->hasMany(Lesson::class)->orderBy('position')->where('status', 1);\n    }\n\n    public function exams()\n    {\n        return $this->belongsToMany(Exam::class, 'sectionables', 'course_id', 'sectionable_id')->wherePivot('sectionable_type', Exam::class);\n    }\n\n    public function topics()\n    {\n        return $this->morphToMany(Topic::class, 'topicable');\n    }\n\n    public function subjects()\n    {\n        return $this->morphToMany(Subject::class, 'subjectables');\n    }\n\n\n\n    public function thumbnail()\n    {\n        return $this->belongsTo(File::class, 'thumbnail');\n    }\n    /*\n    |--------------------------------------------------------------------------\n    | FUNCTIONS\n    |--------------------------------------------------------------------------\n    */\n}\n"
  },
  {
    "path": "app/Models/Exam.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Models\\User;\nuse App\\Models\\Course;\nuse App\\Models\\Result;\nuse App\\Models\\Subject;\nuse App\\Models\\Question;\nuse Illuminate\\Support\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\n\n/**\n * @property int $id\n * @property string $title\n * @property string $description\n * @property int $status\n * @property int $duration\n * @property int $price\n * @property int $pass_mark\n * @property array $meta\n * @property int $number_of_questions\n * @property bool $random_questions\n * @property bool $certification\n * @property bool $difficulty\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property Carbon $deleted_at\n * @property Collection<Course> $courses\n * @property Collection<Exam> $exams\n * @property User $examiner\n */\n\nclass Exam extends Model\n{\n    use SoftDeletes, HasFactory;\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array<int, string>\n     */\n    protected $fillable = [\n        'title',\n        'description',\n        'examiner',\n        'price',\n        'status',\n        'duration',\n        'pass_mark',\n        'meta',\n        'number_of_questions',\n        'random_questions',\n        'certification',\n        'difficulty',\n    ];\n\n    protected $casts = [\n        'meta' => 'array',\n    ];\n\n\n    public function subjects()\n    {\n        return $this->morphToMany(Subject::class, 'subjectables');\n    }\n\n    public function courses()\n    {\n        return $this->belongsToMany(Course::class, 'sectionables', 'sectionable_id', 'course_id')->wherePivot('sectionable_type', Exam::class);\n    }\n\n    public function questions()\n    {\n        return $this->hasMany(Question::class);\n    }\n    public function topics()\n    {\n        return $this->morphToMany(Topic::class, 'topicable');\n    }\n\n    public function results()\n    {\n        return $this->hasMany(Result::class, 'exam_id', 'id');\n    }\n\n    public function examiner()\n    {\n        return $this->belongsTo(User::class, 'examiner');\n    }\n\n    public static function calculateTotalMark($marks)\n    {\n        $count = 0;\n        foreach ($marks as $mark) {\n            $count = $count + $mark->mark;\n        }\n        return $count;\n    }\n\n    public function sectionable()\n    {\n        return $this->morphOne(Sectionable::class, 'sectionable');\n    }\n}\n"
  },
  {
    "path": "app/Models/File.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Models\\User;\nuse App\\Jobs\\ResizedImage;\nuse Illuminate\\Support\\Carbon;\nuse App\\Models\\Traits\\HashesId;\nuse App\\Observers\\FileObserver;\nuse App\\Models\\Traits\\FileStorage;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\n\n/**\n * @property int $id\n * @property string $name\n * @property string $description\n * @property string $path\n * @property string $file_name\n * @property string $extension\n * @property string $mime\n * @property string $type\n * @property string $public_path\n * @property string $driver_data\n * @property string $driver\n * @property int $parent_id\n * @property int $uploaded_by\n * @property array $meta\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property File $children\n * @property File $parent\n * @property User $uploader\n * @property Collection<Exam> $exams\n */\n\nclass File extends Model\n{\n    use HashesId, FileStorage, SoftDeletes;\n\n    protected $fillable = [\n        'name',\n        'description',\n        'path',\n        'file_name',\n        'extension',\n        'mime',\n        'type',\n        'public_path',\n        'parent_id',\n        'driver',\n        'driver_data',\n        'uploaded_by',\n        'meta',\n    ];\n\n    protected $casts = [\n        'id' => 'integer',\n        'file_size' => 'integer',\n        'user_id' => 'integer',\n        'parent_id' => 'integer',\n        'meta' => 'array',\n        'permissions' => 'array',\n    ];\n\n    /**\n     * The attributes that should be hidden for arrays.\n     *\n     * @var array<int, string>\n     */\n    protected $hidden = [\n        'meta',\n        'file_name'\n    ];\n\n    /**\n     * the accessor that should append with response.\n     *\n     * @var array<int, string>\n     */\n    protected $appends = [\n        'sizes',\n        'hash'\n    ];\n\n    /*\n    |--------------------------------------------------------------------------\n    | Booting\n    |--------------------------------------------------------------------------\n    */\n    public static function boot()\n    {\n        parent::boot();\n        File::observe(FileObserver::class);\n    }\n    /*\n    |--------------------------------------------------------------------------\n    | ACCESORS Variables\n    |--------------------------------------------------------------------------\n    */\n\n\n    /*\n    |--------------------------------------------------------------------------\n    | ACCESORS & Mutation\n    |--------------------------------------------------------------------------\n    */\n    public function getSizesAttribute()\n    {\n        if ($this->type == 'image') {\n            return $this->getImageSizes();\n        }\n\n        return [];\n    }\n\n\n    /*\n    |--------------------------------------------------------------------------\n    | Scopes\n    |--------------------------------------------------------------------------\n    */\n\n\n    /*\n    |--------------------------------------------------------------------------\n    | RELATIONS\n    |--------------------------------------------------------------------------\n    */\n\n    /**\n     * @return \\Illuminate\\Database\\Eloquent\\Relations\\HasMany\n     */\n    public function children()\n    {\n        return $this->hasMany(static::class, 'folder_id');\n    }\n\n    /**\n     * @return \\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\n     */\n    public function parent()\n    {\n        return $this->belongsTo(static::class, 'folder_id');\n    }\n\n    public function uploader()\n    {\n        return $this->hasOne(User::class, 'id', 'uploaded_by');\n    }\n\n\n\n\n    /*\n    |--------------------------------------------------------------------------\n    | FUNCTIONS\n    |--------------------------------------------------------------------------\n    */\n\n    public function setPermission($permission, $value)\n    {\n        $meta = $this->meta;\n        $permissions = $meta['permissions'];\n        $permissions[$permission] = $value;\n        $meta['permissions'] = $permissions;\n        $this->meta = $meta;\n        return $this;\n    }\n\n    public function getPermission($permission = null)\n    {\n        $permissions = $this->meta['permissions'];\n\n        if ($permission !== null) {\n            if (array_key_exists($permission, $permissions)) {\n                return $permissions[$permission];\n            } else {\n                return false;\n            }\n        }\n        return $permissions;\n    }\n\n    public function hasPermission($permission)\n    {\n        return $this->getPermission($permission) === true;\n    }\n\n    public function setImageSize($size)\n    {\n        $sizes = $this->meta['sizes'];\n        $sizes[$size] = false;\n\n        $this->meta['sizes'] = $sizes;\n        return $this;\n    }\n\n    public function getImageSizes()\n    {\n        return $this->meta['sizes'];\n    }\n\n    public function updatePublicPaths($driver = null)\n    {\n        if ($this->driver !== $driver) {\n            $this->driver = $driver;\n        }\n\n        if ($this->hasPermission('public')) {\n            $this->public_path = Storage::disk($this->driver)->url($this->getStoragePath());\n        } else {\n            $this->public_path = Storage::disk('local')->url($this->getStoragePath());\n        }\n        $this->save();\n    }\n\n    public function getStoragePath($prefix = null)\n    {\n        return \"$this->file_name/$this->name\";\n    }\n\n    /**\n     * set the image resize attribute;.\n     *\n     * @param array $sizes\n     */\n    public function setImageSizes(array $sizes)\n    {\n        $meta = $this->meta;\n        $exiting = $meta['sizes'];\n        $hasnew = false;\n        foreach ($sizes as $size) {\n            if (is_array($size) && is_array($exiting) && array_key_exists(implode('x', $size), $exiting)) {\n                continue;\n            }\n\n            $exiting[implode('x', $size)] = false;\n            $hasnew = true;\n        }\n\n        if ($hasnew) {\n            $meta['sizes'] = $exiting;\n            $this->meta = $meta;\n            $this->save();\n            ResizedImage::dispatch($this);\n        }\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "app/Models/Lesson.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse Auth;\nuse App\\Models\\File;\nuse Illuminate\\Support\\Carbon;\nuse App\\Models\\Traits\\Fileable;\nuse App\\Models\\Traits\\Topicable;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\n\n/**\n * @property int $id\n * @property string $title\n * @property string $slug\n * @property string $thumbnail\n * @property int $type\n * @property array $object\n * @property string $short_text\n * @property string $full_text\n * @property int $position\n * @property int $status\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property Carbon $deleted_at\n * @property int $created_by\n * @property int $updated_by\n * @property Collection<Course> $courses\n * @property Collection<User> $students\n * @property Collection<Section> $sections\n * @property Sectionable $sectionable\n * @property File $objectFile\n */\n\nclass Lesson extends Model\n{\n    use Topicable, Fileable, SoftDeletes, HasFactory;\n\n    protected $fillable = [\n        'title',\n        'slug',\n        'thumbnail',\n        'short_text',\n        'full_text',\n        'position',\n        'type',\n        'object',\n        'status',\n        'created_by',\n        'updated_by'\n    ];\n\n    /*\n    |--------------------------------------------------------------------------\n    | ACCESORS Variables\n    |--------------------------------------------------------------------------\n    */\n    // protected $casts = [\n    //     'object' => 'array'\n    // ];\n\n    /**\n     * The attributes that should be hidden for arrays.\n     *\n     * @var array<int, string>\n     */\n    protected $hidden = ['object', 'full_text'];\n\n    public static $types = [\n        'text' => 1,\n        'video'   => 2,\n        'audio' => 3,\n        'pdf' => 4\n    ];\n\n    public static $statuses = [\n        'free' => 1,\n        'subscriber' => 2,\n        'paid' => 3,\n    ];\n\n    /*\n    |--------------------------------------------------------------------------\n    | ACCESORS\n    |--------------------------------------------------------------------------\n    */\n\n\n    public function getTypeAttribute($value)\n    {\n        $key = array_search($value, self::$types);\n\n        if ($key) {\n            return ucfirst($key);\n        }\n    }\n\n    public function setTypeAttribute($value)\n    {\n        $value = strtolower($value);\n        $key = array_search($value, self::$types);\n\n        if ($key) {\n            $this->attributes['type'] = $value;\n        } else {\n            $this->attributes['type'] = self::$types[$value];\n        }\n    }\n\n    public function getStatusAttribute($value)\n    {\n        $key = array_search($value, self::$statuses);\n\n        if ($key) {\n            return ucfirst($key);\n        }\n    }\n\n    public function setStatusAttribute($value)\n    {\n        $value = strtolower($value);\n        $key = array_search($value, self::$statuses);\n\n        if ($key) {\n            $this->attributes['status'] = $value;\n        } else {\n            $this->attributes['status'] = self::$statuses[$value];\n        }\n    }\n\n    public function getObjectAttribute($value)\n    {\n        return $this->files->where('id', $value)->first();\n    }\n\n    /*\n    |--------------------------------------------------------------------------\n    | Scopes\n    |--------------------------------------------------------------------------\n    */\n    public function scopePublished($query)\n    {\n        return $query->where('status', 1);\n    }\n\n    /*\n    |--------------------------------------------------------------------------\n    | RELATIONS\n    |--------------------------------------------------------------------------\n    */\n    public function courses()\n    {\n        return $this->belongsToMany(Course::class, 'sectionables', 'sectionable_id', 'course_id')->wherePivot('sectionable_type', Lesson::class);\n    }\n\n    public function students()\n    {\n        return $this->belongsToMany(User::class, 'lesson_student')->withTimestamps();\n    }\n\n    public function sectionable()\n    {\n        return $this->morphOne(Sectionable::class, 'sectionable');\n    }\n\n    public function sections()\n    {\n        return $this->morphToMany(Section::class, 'sectionable');\n    }\n\n    public function objectFile()\n    {\n        return $this->belongsTo(File::class, 'object');\n    }\n\n    /*\n    |--------------------------------------------------------------------------\n    | OVERWRITE FUNCTIONS\n    |--------------------------------------------------------------------------\n    */\n    /*\n    |--------------------------------------------------------------------------\n    | FUNCTIONS\n    |--------------------------------------------------------------------------\n    */\n\n    public function setLessonObject(File $file = null)\n    {\n        if ($file && $file->id !== $this->object) {\n            $this->object = $file->id;\n            $this->save();\n        } else {\n            $file = File::find($this->object);\n        }\n\n        if (!$file) {\n            return;\n        }\n\n        $this->files()->sync($file);\n\n        $file->setPermission('public', false)->setPermission('lesson', true)->save();\n    }\n}\n"
  },
  {
    "path": "app/Models/Question.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Models\\Exam;\nuse App\\Models\\Topic;\nuse Illuminate\\Support\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\n\n/**\n * @property int $id\n * @property string $hint\n * @property string $question\n * @property array $options\n * @property array $answers\n * @property string $explanation\n * @property int $mark\n * @property int $nmark\n * @property int $qtype\n * @property int $created_by\n * @property int $exam_id\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property Carbon $deleted_at\n * @property Collection<Topic> $topics\n * @property Exam $exam\n */\n\nclass Question extends Model\n{\n    use SoftDeletes, HasFactory;\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array<int, string>\n     */\n    protected $fillable = [\n        'qtype', 'question', 'options', 'answers', 'hint', 'mark', 'nmark', 'explanation', 'created_by'\n    ];\n\n    protected $casts = [\n        'answers' => 'array',\n        'options' => 'array'\n    ];\n\n    /*\n    |--------------------------------------------------------------------------\n    | ACCESORS Variables\n    |--------------------------------------------------------------------------\n    */\n    public static $qtypes = [\n        'Objective' => 0,\n        'TrueFalse'   => 1,\n    ];\n\n    /*\n    |--------------------------------------------------------------------------\n    | ACCESORS\n    |--------------------------------------------------------------------------\n    */\n\n    public function getQtypeAttribute($value)\n    {\n        $key = array_search($value, self::$qtypes);\n\n        if ($key) {\n            return ucfirst($key);\n        }\n    }\n\n    public function setQtypeAttribute($value)\n    {\n        $key = array_search($value, self::$qtypes);\n\n        if ($key) {\n            $this->attributes['qtype'] = $value;\n        } else {\n            $this->attributes['qtype'] = self::$qtypes[$value];\n        }\n    }\n\n    public function topics()\n    {\n        return $this->morphToMany(Topic::class, 'topicable');\n    }\n\n    public function exam()\n    {\n        return $this->belongsTo(Exam::class);\n    }\n\n    public function setAnswerAttribute($value)\n    {\n        $this->attributes['answers'] = json_encode($value);\n    }\n}\n"
  },
  {
    "path": "app/Models/Result.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Models\\Exam;\nuse App\\Models\\User;\nuse Illuminate\\Support\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\n\n/**\n * @property int $id\n * @property int $examinee\n * @property int $exam_id\n * @property array $answers\n * @property float $obtain_mark\n * @property float $time_taken\n * @property boolean $is_pass\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property Collection<Course> $courses\n * @property Exam $exam\n * @property User $examinee\n */\n\nclass Result extends Model\n{\n    use HasFactory;\n\n    protected $fillable = ['answers', 'obtain'];\n\n    protected $casts = [\n        'answers' => 'array',\n        'is_pass' => 'bool'\n    ];\n\n    public function exam()\n    {\n        return $this->belongsTo(Exam::class, 'exam_id');\n    }\n\n    public function examinee()\n    {\n        return $this->belongsTo(User::class, 'examinee');\n    }\n\n    public static function calculateMark($answer)\n    {\n        $count = 0;\n        if (!empty($answer)) {\n            foreach ($answer as $resultKey => $resultValue) {\n                $question = Question::where('id', $resultKey)->first();\n                if (!empty($question)) {\n                    foreach ($question->answers as $key => $value) {\n                        if ($resultValue == $value) {\n                            $count = $count + $question->mark;\n                        }\n                    }\n                }\n            }\n        }\n        return $count;\n    }\n}\n"
  },
  {
    "path": "app/Models/Role.php",
    "content": "<?php\nnamespace App\\Models;\n\nuse Illuminate\\Support\\Carbon;\nuse Illuminate\\Support\\Collection;\nuse Spatie\\Permission\\Models\\Role as ModelsRole;\n\n/**\n * @property int $id\n * @property string $name\n * @property string $guard_name\n * @property int $course_id\n * @property Carbon $created_at\n * @property Carbon $updated_at\n */\n\nclass Role extends ModelsRole\n{\n    const SUPERADMIN = 'superadmin';\n    const ADMIN = 'admin';\n\n    public static function appRoles(): Collection\n    {\n        return collect([Role::SUPERADMIN, Role::ADMIN]);\n    }\n\n    public function modifiable(): bool\n    {\n        return ! $this->appRoles()->include($this->name);\n    }\n}"
  },
  {
    "path": "app/Models/Section.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse Illuminate\\Support\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\n\n/**\n * @property int $id\n * @property string $title\n * @property string $description\n * @property int $course_id\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property Collection<Sectionable> $sectionables\n * @property Collection<Lesson> $lessons\n * @property Exam<Lesson> $exams\n */\n\nclass Section extends Model\n{\n    use HasFactory;\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array<int, string>\n     */\n    protected $fillable = [\n        'title', 'description', 'course_id'\n    ];\n\n    public function sectionables()\n    {\n        return $this->hasMany(Sectionable::class, 'section_id')->orderBy('order', 'asc');\n    }\n\n\n    public function lessons()\n    {\n        return $this->morphedByMany(Lesson::class, 'sectionable')->orderBy('order', 'asc')->withPivot(['order']);\n    }\n\n    public function exams()\n    {\n        return $this->morphedByMany(Exam::class, 'sectionable')->orderBy('order', 'asc')->withPivot(['order']);\n    }\n}\n"
  },
  {
    "path": "app/Models/Sectionable.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse Illuminate\\Support\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\n\n/**\n * @property int $id\n * @property int $section_id\n * @property int $sectionable_id\n * @property string $sectionable_type\n * @property int $order\n * @property int $course_id\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property Collection<Section> $sectionable\n * @property Section $section\n */\n\nclass Sectionable extends Model\n{\n    use HasFactory;\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array<int, string>\n     */\n    protected $guarded = [];\n\n\n    public function sectionable()\n    {\n        return $this->morphTo();\n    }\n\n    public function section()\n    {\n        return $this->belongsTo(Section::class, 'section_id');\n    }\n}\n"
  },
  {
    "path": "app/Models/Setting.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\n/**\n * @property int $id\n * @property int $resource_id\n * @property string $resource_type\n * @property string $key\n * @property string $value\n */\nclass Setting extends Model\n{\n    //\n}\n"
  },
  {
    "path": "app/Models/SocialiteProvider.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Models\\User;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass SocialiteProvider extends Model\n{\n    use HasFactory;\n\n    /**\n     * The table associated with the model.\n     *\n     * @var string\n     */\n    protected $table = 'socialite_providers';\n\n    /**\n     * Indicates if the model should be timestamped.\n     *\n     * @var bool\n     */\n    public $timestamps = true;\n\n    /**\n     * The attributes that are not mass assignable.\n     *\n     * @var array<int, string>\n     */\n    protected $guarded = [\n        'id',\n    ];\n\n    /**\n     * The attributes that should be hidden for arrays.\n     *\n     * @var array<int, string>\n     */\n    protected $hidden = [\n        'access_token',\n        'refresh_token',\n    ];\n\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array<int, string>\n     */\n    protected $fillable = [\n        'user_id',\n        'provider',\n        'provider_user_id',\n        'access_token',\n        'refresh_token',\n        'avatar',\n    ];\n\n    /**\n     * The attributes that should be cast to native types.\n     *\n     * @var array<int, string>\n     */\n    protected $casts = [\n        'id'                => 'integer',\n        'user_id'           => 'integer',\n        'provider'          => 'string',\n        'provider_user_id'  => 'string',\n        'access_token'      => 'string',\n        'refresh_token'     => 'string',\n        'avatar'            => 'string',\n        'created_at'        => 'datetime',\n        'updated_at'        => 'datetime',\n    ];\n\n    /**\n     * Get the user that owns the socialite provider.\n     *\n     * @return \\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\n     */\n    public function user()\n    {\n        return $this->belongsTo(User::class);\n    }\n}\n"
  },
  {
    "path": "app/Models/Subject.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse App\\Models\\Exam;\nuse Illuminate\\Support\\Carbon;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\n\n/**\n * @property int $id\n * @property int $parent\n * @property string $title\n * @property string $slug\n * @property string $description\n * @property string|null $icon\n * @property string|null $image\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property Collection<Course> $courses\n * @property Collection<Exam> $exams\n */\nclass Subject extends Model\n{\n    use HasFactory;\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array<int, string>\n     */\n    protected $fillable = [\n        'title', 'slug', 'description', 'icon', 'image'\n    ];\n\n    protected $appends = ['image_url'];\n\n    public function getImageUrlAttribute(): ?string\n    {\n        if (! $this->image) {\n            return null;\n        }\n        return Storage::disk('public')->url($this->image);\n    }\n\n    /**\n     * Get all of the courses that are assigned this tag.\n     */\n    public function courses()\n    {\n        return $this->morphedByMany(Course::class, 'subjectables');\n    }\n\n    /**\n     * Get all of the exams that are assigned this tag.\n     */\n    public function exams()\n    {\n        return $this->morphedByMany(Exam::class, 'subjectables');\n    }\n\n    /**\n     * Get child subjects.\n     */\n    public function children()\n    {\n        return $this->hasMany(Subject::class, 'parent');\n    }\n}\n\n"
  },
  {
    "path": "app/Models/Topic.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse Carbon\\Carbon;\nuse App\\Models\\Exam;\nuse App\\Models\\Course;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\n\n/**\n * @property int $id\n * @property string $title\n * @property string $description\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property Collection<Course> $courses\n * @property Collection<Exam> $exams\n */\n\nclass Topic extends Model\n{\n    use HasFactory;\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array<int, string>\n     */\n    protected $fillable = [\n        'title', 'description',\n    ];\n\n    /**\n     * Get all of the courses that are assigned this tag.\n     */\n    public function courses()\n    {\n        return $this->morphedByMany(Course::class, 'topicable');\n    }\n\n    /**\n     * Get all of the exams that are assigned this tag.\n     */\n    public function exams()\n    {\n        return $this->morphedByMany(Exam::class, 'topicable');\n    }\n}\n"
  },
  {
    "path": "app/Models/Traits/FileStorage.php",
    "content": "<?php\n\nnamespace App\\Models\\Traits;\n\n\nuse Intervention\\Image\\Facades\\Image;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Http\\UploadedFile;\nuse App\\Models\\File;\n\n\ntrait FileStorage\n{\n    \n\n    /**\n     * @param File    $entry\n     * @param UploadedFile $contents\n     */\n    public function storeUpload(UploadedFile $file, $public = 'public', $disk = null, $file_name = null)\n    {\n        if (!$disk) {\n            $disk = config('filesystems.default');\n        }\n\n        if (!$file_name) {\n            $file_name = $this->hash;\n        }\n\n        Storage::disk($disk)->putFileAs($this->file_name, $file, $file_name, $public);\n\n        $entry->updatePublicPaths($disk);\n    }\n\n    /**\n     * @param File    $entry\n     * @param UploadedFile $contents\n     */\n    public function storePublicUpload(UploadedFile $file, $file_name = null)\n    {\n        $this->moveFile($file, 'public', 'public', $file_name);\n    }\n\n    /**\n     * @param File    $entry\n     * @param UploadedFile $contents\n     */\n    public function storeLocalUpload(UploadedFile $file, $file_name = null)\n    {\n        $this->moveFile($file, 'public', 'local', $file_name);\n    }\n}\n"
  },
  {
    "path": "app/Models/Traits/Fileable.php",
    "content": "<?php\n\nnamespace App\\Models\\Traits;\n\nuse App\\Models\\File;\n\ntrait Fileable\n{\n    public function files()\n    {\n        return $this->morphToMany(File::class, 'fileable');\n    }\n}\n"
  },
  {
    "path": "app/Models/Traits/HashesId.php",
    "content": "<?php\n\nnamespace App\\Models\\Traits;\n\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Database\\Eloquent\\Builder;\n\ntrait HashesId\n{\n    public function getHashAttribute()\n    {\n        return trim(base64_encode(str_pad($this->getOriginal('id').'|', 10, 'padding')), '=');\n    }\n\n    public function scopeWhereHash(Builder $query, $value)\n    {\n        $id = $this->decodeHash($value);\n\n        return $query->where('id', $id);\n    }\n\n    public function decodeHash($hash)\n    {\n        if ((int) $hash !== 0) {\n            return $hash;\n        }\n\n        return (int) explode('|', base64_decode($hash))[0];\n    }\n}\n"
  },
  {
    "path": "app/Models/Traits/Topicable.php",
    "content": "<?php\n\nnamespace App\\Models\\Traits;\n\nuse App\\Models\\Topic;\n\ntrait Topicable\n{\n    /**\n     * Return polymorphic relationship with json casted meta.\n     */\n    public function topics()\n    {\n        return $this->morphToMany(Topic::class, 'topicable');\n    }\n}\n"
  },
  {
    "path": "app/Models/User.php",
    "content": "<?php\n\nnamespace App\\Models;\n\nuse Carbon\\Carbon;\nuse App\\Models\\Result;\nuse App\\Pivots\\StudentCasting;\nuse Laravel\\Sanctum\\HasApiTokens;\nuse Spatie\\Permission\\Traits\\HasRoles;\nuse Illuminate\\Notifications\\Notifiable;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\nuse Illuminate\\Contracts\\Auth\\MustVerifyEmail;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Foundation\\Auth\\User as Authenticatable;\n\n/**\n * @property int $id\n * @property string $name\n * @property string $email\n * @property string $firstname\n * @property string $lastname\n * @property Carbon $email_verified_at\n * @property string $password\n * @property Carbon $last_loged_in\n * @property STDClass $avatar\n * @property string $ip\n * @property string $fullName\n * @property Carbon $created_at\n * @property Carbon $updated_at\n * @property ?Carbon $deleted_at\n * @property Collection<Role> $roles\n * @property Collection<Result> $results\n * @property Collection<Course> $instructCourses\n * @property Collection<Course> $enrolledCourses\n * @property Collection<Lesson> $enrolledLessons\n */\n\nclass User extends Authenticatable\n{\n    use Notifiable, HasRoles, SoftDeletes, HasApiTokens, HasFactory, Notifiable;\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array<int, string>\n     */\n    protected $fillable = [\n        'firstname', 'lastname', 'name', 'email', 'password', 'avatar'\n    ];\n\n    /**\n     * The attributes that should be hidden for arrays.\n     *\n     * @var array<int, string>\n     */\n    protected $hidden = [\n        'password', 'remember_token',\n    ];\n\n    /**\n     * The attributes that should be append for arrays.\n     *\n     * @var array<int, string>\n     */\n    protected $appends = [\n        'full_name'\n    ];\n\n    /**\n     * Get the attributes that should be cast.\n     *\n     * @return array<string, string>\n     */\n    protected function casts(): array\n    {\n        return [\n            'email_verified_at' => 'datetime:Y-m-d',\n            'password' => 'hashed',\n            'created_at' => 'datetime:Y-m-d',\n            'updated_at' => 'datetime:Y-m-d',\n            'deleted_at' => 'datetime:Y-m-d h:i:s'\n        ];\n    }\n\n    /** --------------------Attributes--------------------------- */\n    public function getFullNameAttribute()\n    {\n        return \"$this->firstname $this->lastname\";\n    }\n\n    public function getAvatarAttribute($value)\n    {\n        if (!is_array($value)) {\n            $value = json_decode($value);\n        }\n\n        if (empty($value) && empty($value->avatar)) {\n            $value = new \\STDClass();\n            $value->avatar = $this->get_gravatar($this->email, 200);\n        }\n\n        return $value;\n    }\n\n    /** --------------------Relations--------------------------- */\n\n    public function results()\n    {\n        return $this->hasMany(Result::class, 'examinee');\n    }\n\n    public function instructCourses()\n    {\n        return $this->belongsToMany(Course::class, 'course_teachers');\n    }\n\n    public function enrolledCourses()\n    {\n        return $this->belongsToMany(Course::class, 'course_students')->using(StudentCasting::class)->withPivot(['rating', 'progress', 'created_at', 'updated_at']);\n    }\n\n    public function enrolledLessons()\n    {\n        return $this->belongsToMany(Lesson::class, 'lesson_student')->using(StudentCasting::class)->withPivot(['status', 'created_at', 'updated_at']);\n    }\n\n    /** --------------------Methods--------------------------- */\n\n    protected function get_gravatar($email, $s = 40, $d = 'mp', $r = 'g', $img = false, $atts = array())\n    {\n        $url = 'https://www.gravatar.com/avatar/';\n        $url .= md5(strtolower(trim($email)));\n        $url .= \"?s=$s&d=$d&r=$r\";\n        if ($img) {\n            $url = '<img src=\"' . $url . '\"';\n            foreach ($atts as $key => $val) {\n                $url .= ' ' . $key . '=\"' . $val . '\"';\n            }\n            $url .= ' />';\n        }\n        return $url;\n    }\n\n    public function isSuperAdmin(): bool\n    {\n        return $this->hasRole(Role::SUPERADMIN);\n    }\n\n    public function isAdmin(): bool\n    {\n        return $this->hasAnyRole(Role::SUPERADMIN, Role::ADMIN);\n    }\n}\n"
  },
  {
    "path": "app/Observers/FileObserver.php",
    "content": "<?php\n\nnamespace App\\Observers;\n\nuse App\\Models\\File;\nuse Illuminate\\Support\\Facades\\Auth;\n\nclass FileObserver\n{\n    /**\n     * Handle the file \"created\" event.\n     *\n     * @param App\\Models\\File $file\n     */\n    public function created(File $file)\n    {\n        $id = Auth::id();\n        $file->uplaoded_by = $id;\n    }\n\n    /**\n     * Handle the file \"updated\" event.\n     *\n     * @param App\\Models\\File $file\n     */\n    public function updated(File $file)\n    {\n    }\n\n    /**\n     * Handle the File \"deleted\" event.\n     *\n     * @param App\\Models\\File $file\n     */\n    public function deleting(File $file)\n    {\n        $id = Auth::id();\n        $file->deleted_by = $id;\n    }\n\n    /**\n     * Handle the file \"deleted\" event.\n     *\n     * @param App\\Models\\File $file\n     */\n    public function deleted(File $file)\n    {\n    }\n\n    /**\n     * Handle the file \"restored\" event.\n     *\n     * @param App\\Models\\File $file\n     */\n    public function restored(File $file)\n    {\n    }\n\n    /**\n     * Handle the file \"force deleted\" event.\n     *\n     * @param App\\Models\\File $file\n     */\n    public function forceDeleted(File $file)\n    {\n    }\n}\n"
  },
  {
    "path": "app/Pivots/StudentCasting.php",
    "content": "<?php\n\nnamespace App\\Pivots;\n\nuse Illuminate\\Database\\Eloquent\\Relations\\MorphPivot;\n\nclass StudentCasting extends MorphPivot\n{\n    /**\n     * Indicates if the model should be timestamped.\n     *\n     * @var bool\n     */\n    public $timestamps = true;\n}\n"
  },
  {
    "path": "app/Policies/CoursePolicy.php",
    "content": "<?php\n\nnamespace App\\Policies;\n\nuse App\\Models\\Course;\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Access\\HandlesAuthorization;\nuse Illuminate\\Auth\\Access\\Response;\n\nclass CoursePolicy\n{\n    use HandlesAuthorization;\n\n    public function before(User $user)\n    {\n        if ($user->isAdmin()) {\n            return true;\n        }\n    }\n\n    /**\n     * Determine whether the user can view any models.\n     */\n    public function viewAny(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can view the model.\n     */\n    public function view(User $user, Course $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can create models.\n     */\n    public function create(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can update the model.\n     */\n    public function update(User $user, Course $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can delete the model.\n     */\n    public function delete(User $user, Course $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can restore the model.\n     */\n    public function restore(User $user, Course $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can permanently delete the model.\n     */\n    public function forceDelete(User $user, Course $model): bool\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "app/Policies/ExamPolicy.php",
    "content": "<?php\n\nnamespace App\\Policies;\n\nuse App\\Models\\Exam;\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Access\\HandlesAuthorization;\nuse Illuminate\\Auth\\Access\\Response;\n\nclass ExamPolicy\n{\n    use HandlesAuthorization;\n\n    public function before(User $user)\n    {\n        if ($user->isAdmin()) {\n            return true;\n        }\n    }\n\n    /**\n     * Determine whether the user can view any models.\n     */\n    public function viewAny(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can view the model.\n     */\n    public function view(User $user, Exam $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can create models.\n     */\n    public function create(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can update the model.\n     */\n    public function update(User $user, Exam $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can delete the model.\n     */\n    public function delete(User $user, Exam $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can restore the model.\n     */\n    public function restore(User $user, Exam $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can permanently delete the model.\n     */\n    public function forceDelete(User $user, Exam $model): bool\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "app/Policies/RolePolicy.php",
    "content": "<?php\n\nnamespace App\\Policies;\n\nuse App\\Models\\Role;\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Access\\HandlesAuthorization;\nuse Illuminate\\Auth\\Access\\Response;\n\nclass RolePolicy\n{\n    use HandlesAuthorization;\n\n    public function before(User $user)\n    {\n        if ($user->isAdmin()) {\n            return true;\n        }\n    }\n\n    /**\n     * Determine whether the user can view any models.\n     */\n    public function viewAny(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can view the model.\n     */\n    public function view(User $user, Role $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can create models.\n     */\n    public function create(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can update the model.\n     */\n    public function update(User $user, Role $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can delete the model.\n     */\n    public function delete(User $user, Role $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can restore the model.\n     */\n    public function restore(User $user, Role $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can permanently delete the model.\n     */\n    public function forceDelete(User $user, Role $model): bool\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "app/Policies/SubjectPolicy.php",
    "content": "<?php\n\nnamespace App\\Policies;\n\nuse App\\Models\\Subject;\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Access\\HandlesAuthorization;\nuse Illuminate\\Auth\\Access\\Response;\n\nclass SubjectPolicy\n{\n    use HandlesAuthorization;\n\n    public function before(User $user)\n    {\n        if ($user->isAdmin()) {\n            return true;\n        }\n    }\n\n    /**\n     * Determine whether the user can view any models.\n     */\n    public function viewAny(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can view the model.\n     */\n    public function view(User $user, Subject $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can create models.\n     */\n    public function create(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can update the model.\n     */\n    public function update(User $user, Subject $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can delete the model.\n     */\n    public function delete(User $user, Subject $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can restore the model.\n     */\n    public function restore(User $user, Subject $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can permanently delete the model.\n     */\n    public function forceDelete(User $user, Subject $model): bool\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "app/Policies/TopicPolicy.php",
    "content": "<?php\n\nnamespace App\\Policies;\n\nuse App\\Models\\Topic;\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Access\\HandlesAuthorization;\nuse Illuminate\\Auth\\Access\\Response;\n\nclass TopicPolicy\n{\n    use HandlesAuthorization;\n\n    public function before(User $user)\n    {\n        if ($user->isAdmin()) {\n            return true;\n        }\n    }\n\n    /**\n     * Determine whether the user can view any models.\n     */\n    public function viewAny(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can view the model.\n     */\n    public function view(User $user, Topic $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can create models.\n     */\n    public function create(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can update the model.\n     */\n    public function update(User $user, Topic $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can delete the model.\n     */\n    public function delete(User $user, Topic $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can restore the model.\n     */\n    public function restore(User $user, Topic $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can permanently delete the model.\n     */\n    public function forceDelete(User $user, Topic $model): bool\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "app/Policies/UserPolicy.php",
    "content": "<?php\n\nnamespace App\\Policies;\n\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Access\\HandlesAuthorization;\nuse Illuminate\\Auth\\Access\\Response;\n\nclass UserPolicy\n{\n    use HandlesAuthorization;\n\n    public function before(User $user)\n    {\n        if ($user->isAdmin()) {\n            return true;\n        }\n    }\n\n    /**\n     * Determine whether the user can view any models.\n     */\n    public function viewAny(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can view the model.\n     */\n    public function view(User $user, User $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can create models.\n     */\n    public function create(User $user): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can update the model.\n     */\n    public function update(User $user, User $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can delete the model.\n     */\n    public function delete(User $user, User $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can restore the model.\n     */\n    public function restore(User $user, User $model): bool\n    {\n        return false;\n    }\n\n    /**\n     * Determine whether the user can permanently delete the model.\n     */\n    public function forceDelete(User $user, User $model): bool\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "app/Providers/AppServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\nuse Illuminate\\Support\\ServiceProvider;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    /**\n     * Register any application services.\n     */\n    public function register(): void\n    {\n        //\n    }\n\n    /**\n     * Bootstrap any application services.\n     */\n    public function boot(): void\n    {\n        //\n        JsonResource::withoutWrapping();\n    }\n}\n"
  },
  {
    "path": "app/Response/AudioVideoResponse.php",
    "content": "<?php\n\nnamespace App\\Response;\n\nuse Storage;\nuse App\\Models\\File;\n\nclass AudioVideoResponse\n{\n    /**\n     * Stream specified video/audio file.\n     *\n     * @param File $upload\n     *\n     * @return mixed\n     */\n    public function create(File $upload)\n    {\n        $disk = Storage::disk($upload->driver);\n        $size = $disk->size($upload->getStoragePath());\n        $time = date('r', $disk->lastModified($upload->getStoragePath()));\n        $fm = $disk->getDriver()->readStream($upload->getStoragePath());\n        $begin = 0;\n        $end = $size - 1;\n\n        if (isset($_SERVER['HTTP_RANGE'])) {\n            if (preg_match('/bytes=\\h*(\\d+)-(\\d*)[\\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) {\n                $begin = intval($matches[1]);\n                if (!empty($matches[2])) {\n                    $end = intval($matches[2]);\n                }\n            }\n        }\n\n        if (isset($_SERVER['HTTP_RANGE'])) {\n            header('HTTP/1.1 206 Partial Content');\n        } else {\n            header('HTTP/1.1 200 OK');\n        }\n\n        header(\"Content-Type: $upload->mime\");\n        header('Cache-Control: public, must-revalidate, max-age=0');\n        header('Pragma: no-cache');\n        header('Accept-Ranges: bytes');\n        header('Content-Length:'.(($end - $begin) + 1));\n        if (isset($_SERVER['HTTP_RANGE'])) {\n            header(\"Content-Range: bytes $begin-$end/$size\");\n        }\n        header(\"Content-Disposition: inline; filename=$upload->file_name\");\n        header('Content-Transfer-Encoding: binary');\n        header(\"Last-Modified: $time\");\n\n        $cur = $begin;\n        fseek($fm, $begin, 0);\n\n        while (!feof($fm) && $cur <= $end && (connection_status() == 0)) {\n            echo fread($fm, min(1024 * 16, ($end - $cur) + 1));\n            $cur += 1024 * 16;\n        }\n    }\n}\n"
  },
  {
    "path": "app/Response/DownloadResponse.php",
    "content": "<?php\n\nnamespace App\\Response;\n\nuse Response;\nuse App\\Models\\File;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Facades\\Storage;\n\n// use Chumper\\Zipper\\Zipper;\n\nclass DownloadResponse\n{\n    // private $zipper;\n\n    private $file;\n\n    public function __construct(File $file)\n    {\n        $this->file = $file;\n        // $this->zipper = $zipper;\n    }\n\n    /**\n     * Return download or preview response for given file.\n     *\n     * @param File $upload\n     *\n     * @return mixed\n     */\n    public function singleDownload($id)\n    {\n        $upload = $this->file->whereHash($id)->firstOrFail();\n\n        if ($upload->type == 'folder') {\n            return $this->folderDownload($upload);\n        }\n\n        $headers = [\n            'Content-Type' => $upload->mime,\n        ];\n\n        $filename = Str::slug(Str::before($upload->name, '.'), '-');\n\n        $filename = \"$filename.$upload->extension\";\n\n        $filepath = Storage::drive('uploads_local')->path($upload->getStoragePath());\n\n        return response()->download($filepath, $filename, $headers);\n    }\n\n    public function folderDownload($upload)\n    {\n        $zip_name = Str::random(10);\n        $zip_name = config('app.name').'-'.$zip_name;\n\n        $this->zipper->make(storage_path(\"public/$zip_name.zip\"));\n\n        $this->fileRecussive($upload);\n        $this->zipper->close();\n\n        $headers = [\n            'Content-Type' => 'application/zip',\n        ];\n\n        return response()->download(storage_path(\"public/$zip_name.zip\"), \"$zip_name.zip\", $headers)->deleteFileAfterSend(true);\n    }\n\n    public function fileRecussive($file, $folderName = '')\n    {\n        if ($file->type == 'folder') {\n            $folderName = \"$folderName/$file->name\";\n\n            foreach ($this->file->where('parent_id', $file->id)->cursor() as $chield) {\n                $this->fileRecussive($chield, $folderName);\n            }\n        } else {\n            $filename = Str::slug(Str::before($file->name, '.'), '-');\n            $filename = \"$filename.$file->extension\";\n\n            $this->zipper->folder($folderName)->addString($filename, Storage::drive('uploads_local')->get($file->getStoragePath()));\n        }\n    }\n\n    public function multipleDownload($ids)\n    {\n        $zip_name = Str::random(10);\n        $zip_name = config('app.name').'-'.$zip_name;\n\n        $this->zipper->make(storage_path(\"public/$zip_name.zip\"));\n\n        if (is_array($ids)) {\n            foreach ($this->file->whereIn('id', $ids)->cursor() as $chield) {\n                $this->fileRecussive($chield);\n            }\n        }\n\n        $this->zipper->close();\n\n        $headers = [\n            'Content-Type' => 'application/zip',\n        ];\n\n        return response()->download(storage_path(\"public/$zip_name.zip\"), \"$zip_name.zip\", $headers)->deleteFileAfterSend(true);\n    }\n}\n"
  },
  {
    "path": "app/Response/FileBuilder.php",
    "content": "<?php\nnamespace App\\Response;\n\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Http\\UploadedFile;\nuse Illuminate\\Support\\Facades\\Auth;\n\nclass FileBuilder\n{\n    /**\n     * @param UploadedFile $file\n     * @param array        $extra\n     *\n     * @return array\n     */\n    public function getFileData(UploadedFile $file, $extra)\n    {\n        // TODO: move mime/extension/type guessing into separate class\n        $originalMime = $file->getMimeType();\n\n        if ($originalMime === 'application/octet-stream') {\n            $originalMime = $file->getClientMimeType();\n        }\n\n        $file_name = Arr::get($extra, 'file_name') ? Arr::get($extra, 'file_name') : Str::random(36);\n        $data = [\n            'name' => Arr::get($extra, 'name', $file->getClientOriginalName()),\n            'file_name' => $file_name,\n            'mime' => $originalMime,\n            // 'type' => $this->getTypeFromMime($originalMime),\n            // 'extension' => $this->getExtension($file, $originalMime),\n            'path' => Arr::get($extra, 'path'),\n            'parent_id' => Arr::get($extra, 'parent_id'),\n            'public_path' => Arr::get($extra, 'public_path'),\n            'uploaded_by' => Arr::get($extra, 'uploaded_by', Auth::user()->id),\n            'driver' => Arr::get($extra, 'driver', config('filesystems.default')),\n            'driver_data' => Arr::get($extra, 'driver_data'),\n            'meta' => Arr::get($extra, 'meta'),\n        ];\n\n        return $data;\n    }\n}\n"
  },
  {
    "path": "app/Response/FileContentResponseCreator.php",
    "content": "<?php\n\nnamespace App\\Response;\n\nuse App\\Models\\File;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Support\\Facades\\Response;\n\nclass FileContentResponseCreator\n{\n    /**\n     * ImageResponse service instance.\n     *\n     * @var ImageResponse\n     */\n    private $imageResponse;\n\n    /**\n     * AudioVideoResponse service instance.\n     *\n     * @var AudioVideoResponse\n     */\n    private $audioVideoResponse;\n\n    /**\n     * FileContentResponse constructor.\n     *\n     * @param ImageResponse      $imageResponse\n     * @param AudioVideoResponse $audioVideoResponse\n     */\n    public function __construct(ImageResponse $imageResponse, AudioVideoResponse $audioVideoResponse)\n    {\n        $this->imageResponse = $imageResponse;\n        $this->audioVideoResponse = $audioVideoResponse;\n    }\n\n    /**\n     * Return download or preview response for given file.\n     *\n     * @param File $upload\n     *\n     * @return mixed\n     */\n    public function create(File $upload)\n    {\n        if (!Storage::drive($upload->driver)->exists($upload->getStoragePath())) {\n            abort(404);\n        }\n\n        list($mime, $type) = $this->getTypeFromModel($upload);\n\n        if ($type === 'image') {\n            return $this->imageResponse->create($upload);\n        } elseif ($this->shouldStream($mime, $type)) {\n            return $this->audioVideoResponse->create($upload);\n        } else {\n            return $this->createBasicResponse($upload);\n        }\n    }\n\n    /**\n     * Create a basic response for specified upload content.\n     *\n     * @param File $upload\n     *\n     * @return Response\n     */\n    private function createBasicResponse(File $upload)\n    {\n        return response(Storage::drive($upload->driver)->get($upload->getStoragePath()), 200, ['Content-Type' => $upload->mime]);\n    }\n\n    /**\n     * Extract file type from model.\n     *\n     * @param File $fileModel\n     *\n     * @return array\n     */\n    private function getTypeFromModel(File $fileModel)\n    {\n        $mime = $fileModel->mime;\n        $type = explode('/', $mime)[0];\n\n        return array($mime, $type);\n    }\n\n    /**\n     * Should file with given mime be streamed.\n     *\n     * @param string $mime\n     * @param string $type\n     *\n     * @return bool\n     */\n    private function shouldStream($mime, $type)\n    {\n        return $type === 'video' || $type === 'audio' || $mime === 'application/ogg';\n    }\n}\n"
  },
  {
    "path": "app/Response/ImageResponse.php",
    "content": "<?php\n\nnamespace App\\Response;\n\nuse Storage;\nuse App\\Models\\File;\nuse Symfony\\Component\\HttpFoundation\\Response;\n\nclass ImageResponse\n{\n    /**\n     * Create response for previewing specified image.\n     * Optionally resize image to specified size.\n     *\n     * @param File $upload\n     *\n     * @return Response\n     */\n    public function create(File $upload)\n    {\n        $content = Storage::drive($upload->driver)->get($upload->getStoragePath());\n\n        return response($content, 200, ['Content-Type' => $upload->mime]);\n    }\n}\n"
  },
  {
    "path": "app/Traits/AppSettingsTrait.php",
    "content": "<?php\n\nnamespace App\\Traits;\n\nuse App\\Models\\Setting;\nuse Illuminate\\Support\\Facades\\Artisan;\n\ntrait AppSettingsTrait\n{\n    /**\n     * Process the settings for additional app needs.\n     *\n     * @param  \\App\\Models\\Setting  $setting\n     * @return \\App\\Models\\Setting\n     */\n    public function processSettingForAdditionalAppChanges(Setting $setting)\n    {\n        if ($setting->key == 'enableSentryMonitoring') {\n            $this->setEnv('SENTRY_IO_ENABLED', $setting->val, config('services.sentry.enabled'));\n            putenv('SENTRY_IO_ENABLED='.$setting->val);\n            config(['services.sentry.enabled' => $setting->val]);\n        }\n        if ($setting->key == 'sentryIoDSN') {\n            $this->setEnv('SENTRY_LARAVEL_DSN', $setting->val, config('sentry.dsn'));\n            putenv('SENTRY_LARAVEL_DSN='.$setting->val);\n            config(['sentry.dsn' => $setting->val]);\n        }\n        if ($setting->key == 'enableSentryMonitoringFeedbakForm') {\n            $this->setEnv('SENTRY_IO_USER_FEEDBACK_ENABLED', $setting->val, config('services.sentry.feedback-enabled'));\n            putenv('SENTRY_IO_USER_FEEDBACK_ENABLED='.$setting->val);\n            config(['services.sentry.feedback-enabled' => $setting->val]);\n        }\n\n        if ($setting->key == 'appApplePrivateKey') {\n            $this->setEnv('APPLE_PRIVATE_KEY', $setting->val, config('services.apple.private_key'));\n            putenv('APPLE_PRIVATE_KEY='.$setting->val);\n            config(['services.apple.private_key' => $setting->val]);\n        }\n        if ($setting->key == 'appAppleTeamId') {\n            $this->setEnv('APPLE_TEAM_ID', $setting->val, config('services.apple.team_id'));\n            putenv('APPLE_TEAM_ID='.$setting->val);\n            config(['services.apple.team_id' => $setting->val]);\n        }\n        if ($setting->key == 'appAppleKeyId') {\n            $this->setEnv('APPLE_KEY_ID', $setting->val, config('services.apple.key_id'));\n            putenv('APPLE_KEY_ID='.$setting->val);\n            config(['services.apple.key_id' => $setting->val]);\n        }\n        if ($setting->key == 'appAppleId') {\n            $this->setEnv('APPLE_CLIENT_ID', $setting->val, config('services.apple.client_id'));\n            putenv('APPLE_CLIENT_ID='.$setting->val);\n            config(['services.apple.client_id' => $setting->val]);\n        }\n        if ($setting->key == 'appAppleSecret') {\n            $this->setEnv('APPLE_CLIENT_SECRET', $setting->val, config('services.apple.client_secret'));\n            putenv('APPLE_CLIENT_SECRET='.$setting->val);\n            config(['services.apple.client_secret' => $setting->val]);\n        }\n        if ($setting->key == 'appAppleRedirect') {\n            $this->setEnv('APPLE_REDIRECT_URI', $setting->val, config('services.apple.redirect'));\n            putenv('APPLE_REDIRECT_URI='.$setting->val);\n            config(['services.apple.redirect' => $setting->val]);\n        }\n\n        if ($setting->key == 'appStackExchangeSite') {\n            $this->setEnv('STACKEXCHANGE_CLIENT_SITE', $setting->val, config('services.stackexchange.site'));\n            putenv('STACKEXCHANGE_CLIENT_SITE='.$setting->val);\n            config(['services.stackexchange.site' => $setting->val]);\n        }\n        if ($setting->key == 'appStackExchangeKey') {\n            $this->setEnv('STACKEXCHANGE_CLIENT_KEY', $setting->val, config('services.stackexchange.key'));\n            putenv('STACKEXCHANGE_CLIENT_KEY='.$setting->val);\n            config(['services.stackexchange.key' => $setting->val]);\n        }\n        if ($setting->key == 'appStackExchangeId') {\n            $this->setEnv('STACKEXCHANGE_CLIENT_ID', $setting->val, config('services.stackexchange.client_id'));\n            putenv('STACKEXCHANGE_CLIENT_ID='.$setting->val);\n            config(['services.stackexchange.client_id' => $setting->val]);\n        }\n        if ($setting->key == 'appStackExchangeSecret') {\n            $this->setEnv('STACKEXCHANGE_CLIENT_SECRET', $setting->val, config('services.stackexchange.client_secret'));\n            putenv('STACKEXCHANGE_CLIENT_SECRET='.$setting->val);\n            config(['services.stackexchange.client_secret' => $setting->val]);\n        }\n        if ($setting->key == 'appStackExchangeRedirect') {\n            $this->setEnv('STACKEXCHANGE_REDIRECT_URI', $setting->val, config('services.stackexchange.redirect'));\n            putenv('STACKEXCHANGE_REDIRECT_URI='.$setting->val);\n            config(['services.stackexchange.redirect' => $setting->val]);\n        }\n\n        if ($setting->key == 'appGitLabId') {\n            $this->setEnv('GITLAB_CLIENT_ID', $setting->val, config('services.gitlab.client_id'));\n            putenv('GITLAB_CLIENT_ID='.$setting->val);\n            config(['services.gitlab.client_id' => $setting->val]);\n        }\n        if ($setting->key == 'appGitLabSecret') {\n            $this->setEnv('GITLAB_CLIENT_SECRET', $setting->val, config('services.gitlab.client_secret'));\n            putenv('GITLAB_CLIENT_SECRET='.$setting->val);\n            config(['services.gitlab.client_secret' => $setting->val]);\n        }\n        if ($setting->key == 'appGitLabRedirect') {\n            $this->setEnv('GITLAB_REDIRECT_URI', $setting->val, config('services.gitlab.redirect'));\n            putenv('GITLAB_REDIRECT_URI='.$setting->val);\n            config(['services.gitlab.redirect' => $setting->val]);\n        }\n\n        if ($setting->key == 'appRedditId') {\n            $this->setEnv('REDDIT_CLIENT_ID', $setting->val, config('services.reddit.client_id'));\n            putenv('REDDIT_CLIENT_ID='.$setting->val);\n            config(['services.reddit.client_id' => $setting->val]);\n        }\n        if ($setting->key == 'appRedditSecret') {\n            $this->setEnv('REDDIT_CLIENT_SECRET', $setting->val, config('services.reddit.client_secret'));\n            putenv('REDDIT_CLIENT_SECRET='.$setting->val);\n            config(['services.reddit.client_secret' => $setting->val]);\n        }\n        if ($setting->key == 'appRedditResponseType') {\n            $this->setEnv('REDDIT_RESPONSE_TYPE', $setting->val, config('services.reddit.response_type'));\n            putenv('REDDIT_RESPONSE_TYPE='.$setting->val);\n            config(['services.reddit.response_type' => $setting->val]);\n        }\n        if ($setting->key == 'appRedditState') {\n            $this->setEnv('REDDIT_STATE', $setting->val, config('services.reddit.state'));\n            putenv('REDDIT_STATE='.$setting->val);\n            config(['services.reddit.state' => $setting->val]);\n        }\n        if ($setting->key == 'appRedditRedirect') {\n            $this->setEnv('REDDIT_REDIRECT_URI', $setting->val, config('services.reddit.redirect'));\n            putenv('REDDIT_REDIRECT_URI='.$setting->val);\n            config(['services.reddit.redirect' => $setting->val]);\n        }\n\n        if ($setting->key == 'appSnapchatId') {\n            $this->setEnv('SNAPCHAT_CLIENT_ID', $setting->val, config('services.snapchat.client_id'));\n            putenv('SNAPCHAT_CLIENT_ID='.$setting->val);\n            config(['services.snapchat.client_id' => $setting->val]);\n        }\n        if ($setting->key == 'appSnapchatSecret') {\n            $this->setEnv('SNAPCHAT_CLIENT_SECRET', $setting->val, config('services.snapchat.client_secret'));\n            putenv('SNAPCHAT_CLIENT_SECRET='.$setting->val);\n            config(['services.snapchat.client_secret' => $setting->val]);\n        }\n        if ($setting->key == 'appSnapchatRedirect') {\n            $this->setEnv('SNAPCHAT_REDIRECT_URI', $setting->val, config('services.snapchat.redirect'));\n            putenv('SNAPCHAT_REDIRECT_URI='.$setting->val);\n            config(['services.snapchat.redirect' => $setting->val]);\n        }\n\n        if ($setting->key == 'appMeetupId') {\n            $this->setEnv('MEETUP_CLIENT_ID', $setting->val, config('services.meetup.client_id'));\n            putenv('MEETUP_CLIENT_ID='.$setting->val);\n            config(['services.meetup.client_id' => $setting->val]);\n        }\n        if ($setting->key == 'appMeetupSecret') {\n            $this->setEnv('MEETUP_CLIENT_SECRET', $setting->val, config('services.meetup.client_secret'));\n            putenv('MEETUP_CLIENT_SECRET='.$setting->val);\n            config(['services.meetup.client_secret' => $setting->val]);\n        }\n        if ($setting->key == 'appMeetupRedirect') {\n            $this->setEnv('MEETUP_REDIRECT_URI', $setting->val, config('services.meetup.redirect'));\n            putenv('MEETUP_REDIRECT_URI='.$setting->val);\n            config(['services.meetup.redirect' => $setting->val]);\n        }\n\n        if ($setting->key == 'appAtlassianId') {\n            $this->setEnv('ATLASSIAN_CLIENT_ID', $setting->val, config('services.atlassian.client_id'));\n            putenv('ATLASSIAN_CLIENT_ID='.$setting->val);\n            config(['services.atlassian.client_id' => $setting->val]);\n        }\n        if ($setting->key == 'appAtlassianSecret') {\n            $this->setEnv('ATLASSIAN_CLIENT_SECRET', $setting->val, config('services.atlassian.client_secret'));\n            putenv('ATLASSIAN_CLIENT_SECRET='.$setting->val);\n            config(['services.atlassian.client_secret' => $setting->val]);\n        }\n        if ($setting->key == 'appAtlassianRedirect') {\n            $this->setEnv('ATLASSIAN_REDIRECT_URI', $setting->val, config('services.atlassian.redirect'));\n            putenv('ATLASSIAN_REDIRECT_URI='.$setting->val);\n            config(['services.atlassian.redirect' => $setting->val]);\n        }\n        if ($setting->key == 'appName') {\n            $this->setEnv('APP_NAME', \"'\".$setting->val.\"'\", \"'\".config('app.name').\"'\");\n            putenv('APP_NAME='.$setting->val);\n            config(['app.name' => $setting->val]);\n        }\n        if ($setting->key == 'author') {\n            $this->setEnv('APP_AUTHOR', \"'\".$setting->val.\"'\", \"'\".config('settings.author').\"'\");\n            putenv('APP_AUTHOR='.$setting->val);\n            config(['settings.author' => $setting->val]);\n        }\n        if ($setting->key == 'description') {\n            $this->setEnv('APP_DESC', \"'\".$setting->val.\"'\", \"'\".config('settings.description').\"'\");\n            putenv('APP_DESC='.$setting->val);\n            config(['settings.description' => $setting->val]);\n        }\n        if ($setting->key == 'keywords') {\n            $this->setEnv('APP_KEYWORDS', \"'\".$setting->val.\"'\", \"'\".config('settings.keywords').\"'\");\n            putenv('APP_KEYWORDS='.$setting->val);\n            config(['settings.keywords' => $setting->val]);\n        }\n        if ($setting->key == 'enableKonamiAsteroids') {\n            $this->setEnv('KONAMI_ASTEROIDS_ENABLED', $setting->val, config('settings.enableKonamiAsteroids'));\n            putenv('KONAMI_ASTEROIDS_ENABLED='.$setting->val);\n            config(['settings.enableKonamiAsteroids' => $setting->val]);\n        }\n        if ($setting->key == 'enableKonamiToasty') {\n            $this->setEnv('KONAMI_TOASTY_ENABLED', $setting->val, config('settings.enableKonamiToasty'));\n            putenv('KONAMI_TOASTY_ENABLED='.$setting->val);\n            config(['settings.enableKonamiToasty' => $setting->val]);\n        }\n\n        Artisan::call('config:cache');\n\n        // NEW_PROVIDER_PLUG :: Put New Provider HERE\n    }\n\n    /**\n     * Set .env variables directly to the file.\n     *\n     * @param  string  $key\n     * @param  string|null  $value\n     * @param  string|null  $configed\n     */\n    public function setEnv(string $key, $value, $configed = null)\n    {\n        $term = $configed != null ? $configed : env($key);\n        $path = app()->environmentFilePath();\n        $escaped = preg_quote('='.$term, '/');\n\n        file_put_contents($path, preg_replace(\n            \"/^{$key}{$escaped}/m\",\n            \"{$key}={$value}\",\n            file_get_contents($path)\n        ));\n\n        if (file_exists(\\App::getCachedConfigPath())) {\n            \\Artisan::call('config:cache');\n        }\n    }\n}\n"
  },
  {
    "path": "app/Traits/SocialiteProvidersTrait.php",
    "content": "<?php\n\nnamespace App\\Traits;\n\nuse Carbon\\Carbon;\nuse App\\Models\\User;\nuse App\\Models\\Setting;\nuse Illuminate\\Support\\Str;\nuse App\\Models\\SocialiteProvider;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Auth\\Events\\Registered;\nuse Illuminate\\Support\\Facades\\Config;\nuse Laravel\\Sanctum\\PersonalAccessToken;\nuse Laravel\\Socialite\\Facades\\Socialite;\nuse App\\Exceptions\\SocialProviderDeniedException;\nuse Illuminate\\Foundation\\Auth\\AuthenticatesUsers;\nuse Laravel\\Socialite\\Contracts\\User as SocialiteUser;\n\ntrait SocialiteProvidersTrait\n{\n    private $providerSettings;\n    private $providerConfigs;\n\n    public function __construct()\n    {\n        $this->setupProviders();\n    }\n\n    /**\n     * Set the private vars and the apps config dynamically.\n     */\n    protected function setupProviders()\n    {\n        $this->setProviderSettings();\n        $this->setProviderConfigs();\n        $this->setAppProvidersConfigs();\n    }\n\n    /**\n     * Set the private var $providerSettings.\n     */\n    protected function setProviderSettings()\n    {\n        $this->providerSettings = Setting::where('group', 'auth')\n                                ->where(function ($query) {\n                                    $query->where('key', 'enableFbLogin')\n                                            ->orWhere('key', 'appFbId')\n                                            ->orWhere('key', 'appFbSecret')\n                                            ->orWhere('key', 'appFbRedirect')\n\n                                            ->orWhere('key', 'enableTwitterLogin')\n                                            ->orWhere('key', 'appTwitterId')\n                                            ->orWhere('key', 'appTwitterSecret')\n                                            ->orWhere('key', 'appTwitterRedirect')\n\n                                            ->orWhere('key', 'enableGoogleLogin')\n                                            ->orWhere('key', 'appGoogleId')\n                                            ->orWhere('key', 'appGoogleSecret')\n                                            ->orWhere('key', 'appGoogleRedirect')\n\n                                            ->orWhere('key', 'enableGitHubLogin')\n                                            ->orWhere('key', 'appGitHubId')\n                                            ->orWhere('key', 'appGitHubSecret')\n                                            ->orWhere('key', 'appGitHubRedirect')\n\n                                            ->orWhere('key', 'enableTwitchLogin')\n                                            ->orWhere('key', 'appTwitchId')\n                                            ->orWhere('key', 'appTwitchSecret')\n                                            ->orWhere('key', 'appTwitchRedirect')\n\n                                            ->orWhere('key', 'enableInstagramLogin')\n                                            ->orWhere('key', 'appInstagramId')\n                                            ->orWhere('key', 'appInstagramSecret')\n                                            ->orWhere('key', 'appInstagramRedirect')\n\n                                            ->orWhere('key', 'enableYouTubeLogin')\n                                            ->orWhere('key', 'appYouTubeId')\n                                            ->orWhere('key', 'appYouTubeSecret')\n                                            ->orWhere('key', 'appYouTubeRedirect')\n\n                                            ->orWhere('key', 'enableLinkedInLogin')\n                                            ->orWhere('key', 'appLinkedInId')\n                                            ->orWhere('key', 'appLinkedInSecret')\n                                            ->orWhere('key', 'appLinkedInRedirect')\n\n                                            ->orWhere('key', 'enableAppleLogin')\n                                            ->orWhere('key', 'appAppleId')\n                                            ->orWhere('key', 'appAppleSecret')\n                                            ->orWhere('key', 'appAppleRedirect')\n                                            ->orWhere('key', 'appApplePrivateKey')\n                                            ->orWhere('key', 'appAppleTeamId')\n                                            ->orWhere('key', 'appAppleKeyId')\n\n                                            ->orWhere('key', 'enableMicrosoftLogin')\n                                            ->orWhere('key', 'appMicrosoftId')\n                                            ->orWhere('key', 'appMicrosoftSecret')\n                                            ->orWhere('key', 'appMicrosoftRedirect')\n\n                                            ->orWhere('key', 'enableTikTokLogin')\n                                            ->orWhere('key', 'appTikTokId')\n                                            ->orWhere('key', 'appTikTokSecret')\n                                            ->orWhere('key', 'appTikTokRedirect')\n\n                                            ->orWhere('key', 'enableZoHoLogin')\n                                            ->orWhere('key', 'appZoHoId')\n                                            ->orWhere('key', 'appZoHoSecret')\n                                            ->orWhere('key', 'appZoHoRedirect')\n\n                                            ->orWhere('key', 'enableStackExchangeLogin')\n                                            ->orWhere('key', 'appStackExchangeId')\n                                            ->orWhere('key', 'appStackExchangeKey')\n                                            ->orWhere('key', 'appStackExchangeSite')\n                                            ->orWhere('key', 'appStackExchangeSecret')\n                                            ->orWhere('key', 'appStackExchangeRedirect')\n\n                                            ->orWhere('key', 'enableGitLabLogin')\n                                            ->orWhere('key', 'appGitLabId')\n                                            ->orWhere('key', 'appGitLabSecret')\n                                            ->orWhere('key', 'appGitLabRedirect')\n\n                                            ->orWhere('key', 'enableRedditLogin')\n                                            ->orWhere('key', 'appRedditId')\n                                            ->orWhere('key', 'appRedditSecret')\n                                            ->orWhere('key', 'appRedditResponseType')\n                                            ->orWhere('key', 'appRedditState')\n                                            ->orWhere('key', 'appRedditRedirect')\n\n                                            ->orWhere('key', 'enableSnapchatLogin')\n                                            ->orWhere('key', 'appSnapchatId')\n                                            ->orWhere('key', 'appSnapchatSecret')\n                                            ->orWhere('key', 'appSnapchatRedirect')\n\n                                            ->orWhere('key', 'enableMeetupLogin')\n                                            ->orWhere('key', 'appMeetupId')\n                                            ->orWhere('key', 'appMeetupSecret')\n                                            ->orWhere('key', 'appMeetupRedirect')\n\n                                            ->orWhere('key', 'enableAtlassianLogin')\n                                            ->orWhere('key', 'appAtlassianId')\n                                            ->orWhere('key', 'appAtlassianSecret')\n                                            ->orWhere('key', 'appAtlassianRedirect');\n                                    // NEW_PROVIDER_PLUG :: Put New Provider HERE\n                                })->get();\n    }\n\n    /**\n     * Set the private var $providerConfigs.\n     */\n    protected function setProviderConfigs()\n    {\n        $appGitHubId = $this->providerSettings->where('key', 'appGitHubId')->first();\n        $appGitHubId = $appGitHubId ? $appGitHubId->val : null;\n        $appGitHubSecret = $this->providerSettings->where('key', 'appGitHubSecret')->first();\n        $appGitHubSecret = $appGitHubSecret ? $appGitHubSecret->val : null;\n        $appGitHubRedirect = $this->providerSettings->where('key', 'appGitHubRedirect')->first();\n        $appGitHubRedirect = $appGitHubRedirect ? $appGitHubRedirect->val : null;\n\n        $appFbId = $this->providerSettings->where('key', 'appFbId')->first();\n        $appFbId = $appFbId ? $appFbId->val : null;\n        $appFbSecret = $this->providerSettings->where('key', 'appFbSecret')->first();\n        $appFbSecret = $appFbSecret ? $appFbSecret->val : null;\n        $appFbRedirect = $this->providerSettings->where('key', 'appFbRedirect')->first();\n        $appFbRedirect = $appFbRedirect ? $appFbRedirect->val : null;\n\n        $appTwitterId = $this->providerSettings->where('key', 'appTwitterId')->first();\n        $appTwitterId = $appTwitterId ? $appTwitterId->val : null;\n        $appTwitterSecret = $this->providerSettings->where('key', 'appTwitterSecret')->first();\n        $appTwitterSecret = $appTwitterSecret ? $appTwitterSecret->val : null;\n        $appTwitterRedirect = $this->providerSettings->where('key', 'appTwitterRedirect')->first();\n        $appTwitterRedirect = $appTwitterRedirect ? $appTwitterRedirect->val : null;\n\n        $appGoogleId = $this->providerSettings->where('key', 'appGoogleId')->first();\n        $appGoogleId = $appGoogleId ? $appGoogleId->val : null;\n        $appGoogleSecret = $this->providerSettings->where('key', 'appGoogleSecret')->first();\n        $appGoogleSecret = $appGoogleSecret ? $appGoogleSecret->val : null;\n        $appGoogleRedirect = $this->providerSettings->where('key', 'appGoogleRedirect')->first();\n        $appGoogleRedirect = $appGoogleRedirect ? $appGoogleRedirect->val : null;\n\n        $appYouTubeId = $this->providerSettings->where('key', 'appYouTubeId')->first();\n        $appYouTubeId = $appYouTubeId ? $appYouTubeId->val : null;\n        $appYouTubeSecret = $this->providerSettings->where('key', 'appYouTubeSecret')->first();\n        $appYouTubeSecret = $appYouTubeSecret ? $appYouTubeSecret->val : null;\n        $appYouTubeRedirect = $this->providerSettings->where('key', 'appYouTubeRedirect')->first();\n        $appYouTubeRedirect = $appYouTubeRedirect ? $appYouTubeRedirect->val : null;\n\n        $appTwitchId = $this->providerSettings->where('key', 'appTwitchId')->first();\n        $appTwitchId = $appTwitchId ? $appTwitchId->val : null;\n        $appTwitchSecret = $this->providerSettings->where('key', 'appTwitchSecret')->first();\n        $appTwitchSecret = $appTwitchSecret ? $appTwitchSecret->val : null;\n        $appTwitchRedirect = $this->providerSettings->where('key', 'appTwitchRedirect')->first();\n        $appTwitchRedirect = $appTwitchRedirect ? $appTwitchRedirect->val : null;\n\n        $appInstagramId = $this->providerSettings->where('key', 'appInstagramId')->first();\n        $appInstagramId = $appInstagramId ? $appInstagramId->val : null;\n        $appInstagramSecret = $this->providerSettings->where('key', 'appInstagramSecret')->first();\n        $appInstagramSecret = $appInstagramSecret ? $appInstagramSecret->val : null;\n        $appInstagramRedirect = $this->providerSettings->where('key', 'appInstagramRedirect')->first();\n        $appInstagramRedirect = $appInstagramRedirect ? $appInstagramRedirect->val : null;\n\n        $appLinkedInId = $this->providerSettings->where('key', 'appLinkedInId')->first();\n        $appLinkedInId = $appLinkedInId ? $appLinkedInId->val : null;\n        $appLinkedInSecret = $this->providerSettings->where('key', 'appLinkedInSecret')->first();\n        $appLinkedInSecret = $appLinkedInSecret ? $appLinkedInSecret->val : null;\n        $appLinkedInRedirect = $this->providerSettings->where('key', 'appLinkedInRedirect')->first();\n        $appLinkedInRedirect = $appLinkedInRedirect ? $appLinkedInRedirect->val : null;\n\n        $appAppleId = $this->providerSettings->where('key', 'appAppleId')->first();\n        $appAppleId = $appAppleId ? $appAppleId->val : null;\n        $appAppleSecret = $this->providerSettings->where('key', 'appAppleSecret')->first();\n        $appAppleSecret = $appAppleSecret ? $appAppleSecret->val : null;\n        $appAppleRedirect = $this->providerSettings->where('key', 'appAppleRedirect')->first();\n        $appAppleRedirect = $appAppleRedirect ? $appAppleRedirect->val : null;\n        $appApplePrivateKey = $this->providerSettings->where('key', 'appApplePrivateKey')->first();\n        $appApplePrivateKey = $appApplePrivateKey ? $appApplePrivateKey->val : null;\n        $appAppleTeamId = $this->providerSettings->where('key', 'appAppleTeamId')->first();\n        $appAppleTeamId = $appAppleTeamId ? $appAppleTeamId->val : null;\n        $appAppleKeyId = $this->providerSettings->where('key', 'appAppleKeyId')->first();\n        $appAppleKeyId = $appAppleKeyId ? $appAppleKeyId->val : null;\n\n        $appMicrosoftId = $this->providerSettings->where('key', 'appMicrosoftId')->first();\n        $appMicrosoftId = $appMicrosoftId ? $appMicrosoftId->val : null;\n        $appMicrosoftSecret = $this->providerSettings->where('key', 'appMicrosoftSecret')->first();\n        $appMicrosoftSecret = $appMicrosoftSecret ? $appMicrosoftSecret->val : null;\n        $appMicrosoftRedirect = $this->providerSettings->where('key', 'appMicrosoftRedirect')->first();\n        $appMicrosoftRedirect = $appMicrosoftRedirect ? $appMicrosoftRedirect->val : null;\n\n        $appTikTokId = $this->providerSettings->where('key', 'appTikTokId')->first();\n        $appTikTokId = $appTikTokId ? $appTikTokId->val : null;\n        $appTikTokSecret = $this->providerSettings->where('key', 'appTikTokSecret')->first();\n        $appTikTokSecret = $appTikTokSecret ? $appTikTokSecret->val : null;\n        $appTikTokRedirect = $this->providerSettings->where('key', 'appTikTokRedirect')->first();\n        $appTikTokRedirect = $appTikTokRedirect ? $appTikTokRedirect->val : null;\n\n        $appZoHoId = $this->providerSettings->where('key', 'appZoHoId')->first();\n        $appZoHoId = $appZoHoId ? $appZoHoId->val : null;\n        $appZoHoSecret = $this->providerSettings->where('key', 'appZoHoSecret')->first();\n        $appZoHoSecret = $appZoHoSecret ? $appZoHoSecret->val : null;\n        $appZoHoRedirect = $this->providerSettings->where('key', 'appZoHoRedirect')->first();\n        $appZoHoRedirect = $appZoHoRedirect ? $appZoHoRedirect->val : null;\n\n        $appStackExchangeId = $this->providerSettings->where('key', 'appStackExchangeId')->first();\n        $appStackExchangeId = $appStackExchangeId ? $appStackExchangeId->val : null;\n        $appStackExchangeKey = $this->providerSettings->where('key', 'appStackExchangeKey')->first();\n        $appStackExchangeKey = $appStackExchangeKey ? $appStackExchangeKey->val : null;\n        $appStackExchangeSite = $this->providerSettings->where('key', 'appStackExchangeSite')->first();\n        $appStackExchangeSite = $appStackExchangeSite ? $appStackExchangeSite->val : null;\n        $appStackExchangeSecret = $this->providerSettings->where('key', 'appStackExchangeSecret')->first();\n        $appStackExchangeSecret = $appStackExchangeSecret ? $appStackExchangeSecret->val : null;\n        $appStackExchangeRedirect = $this->providerSettings->where('key', 'appStackExchangeRedirect')->first();\n        $appStackExchangeRedirect = $appStackExchangeRedirect ? $appStackExchangeRedirect->val : null;\n\n        $appGitLabId = $this->providerSettings->where('key', 'appGitLabId')->first();\n        $appGitLabId = $appGitLabId ? $appGitLabId->val : null;\n        $appGitLabSecret = $this->providerSettings->where('key', 'appGitLabSecret')->first();\n        $appGitLabSecret = $appGitLabSecret ? $appGitLabSecret->val : null;\n        $appGitLabRedirect = $this->providerSettings->where('key', 'appGitLabRedirect')->first();\n        $appGitLabRedirect = $appGitLabRedirect ? $appGitLabRedirect->val : null;\n\n        $appRedditId = $this->providerSettings->where('key', 'appRedditId')->first();\n        $appRedditId = $appRedditId ? $appRedditId->val : null;\n        $appRedditSecret = $this->providerSettings->where('key', 'appRedditSecret')->first();\n        $appRedditSecret = $appRedditSecret ? $appRedditSecret->val : null;\n        $appRedditRedirect = $this->providerSettings->where('key', 'appRedditRedirect')->first();\n        $appRedditRedirect = $appRedditRedirect ? $appRedditRedirect->val : null;\n        $appRedditResponseType = $this->providerSettings->where('key', 'appRedditResponseType')->first();\n        $appRedditResponseType = $appRedditResponseType ? $appRedditResponseType->val : null;\n        $appRedditState = $this->providerSettings->where('key', 'appRedditState')->first();\n        $appRedditState = $appRedditState ? $appRedditState->val : null;\n\n        $appSnapchatId = $this->providerSettings->where('key', 'appSnapchatId')->first();\n        $appSnapchatId = $appSnapchatId ? $appSnapchatId->val : null;\n        $appSnapchatSecret = $this->providerSettings->where('key', 'appSnapchatSecret')->first();\n        $appSnapchatSecret = $appSnapchatSecret ? $appSnapchatSecret->val : null;\n        $appSnapchatRedirect = $this->providerSettings->where('key', 'appSnapchatRedirect')->first();\n        $appSnapchatRedirect = $appSnapchatRedirect ? $appSnapchatRedirect->val : null;\n\n        $appMeetupId = $this->providerSettings->where('key', 'appMeetupId')->first();\n        $appMeetupId = $appMeetupId ? $appMeetupId->val : null;\n        $appMeetupSecret = $this->providerSettings->where('key', 'appMeetupSecret')->first();\n        $appMeetupSecret = $appMeetupSecret ? $appMeetupSecret->val : null;\n        $appMeetupRedirect = $this->providerSettings->where('key', 'appMeetupRedirect')->first();\n        $appMeetupRedirect = $appMeetupRedirect ? $appMeetupRedirect->val : null;\n\n        $appAtlassianId = $this->providerSettings->where('key', 'appAtlassianId')->first();\n        $appAtlassianId = $appAtlassianId ? $appAtlassianId->val : null;\n        $appAtlassianSecret = $this->providerSettings->where('key', 'appAtlassianSecret')->first();\n        $appAtlassianSecret = $appAtlassianSecret ? $appAtlassianSecret->val : null;\n        $appAtlassianRedirect = $this->providerSettings->where('key', 'appAtlassianRedirect')->first();\n        $appAtlassianRedirect = $appAtlassianRedirect ? $appAtlassianRedirect->val : null;\n\n        // NEW_PROVIDER_PLUG :: Put New Provider HERE\n\n        $providerConfigs = [\n            'services.github' => [\n                'client_id'     => $appGitHubId,\n                'client_secret' => $appGitHubSecret,\n                'redirect'      => $appGitHubRedirect,\n            ],\n            'services.facebook' => [\n                'client_id'     => $appFbId,\n                'client_secret' => $appFbSecret,\n                'redirect'      => $appFbRedirect,\n            ],\n            'services.twitter' => [\n                'client_id'     => $appTwitterId,\n                'client_secret' => $appTwitterSecret,\n                'redirect'      => $appTwitterRedirect,\n            ],\n            'services.google' => [\n                'client_id'     => $appGoogleId,\n                'client_secret' => $appGoogleSecret,\n                'redirect'      => $appGoogleRedirect,\n            ],\n            'services.youtube' => [\n                'client_id'     => $appYouTubeId,\n                'client_secret' => $appYouTubeSecret,\n                'redirect'      => $appYouTubeRedirect,\n            ],\n            'services.twitch' => [\n                'client_id'     => $appTwitchId,\n                'client_secret' => $appTwitchSecret,\n                'redirect'      => $appTwitchRedirect,\n            ],\n            'services.instagram' => [\n                'client_id'     => $appInstagramId,\n                'client_secret' => $appInstagramSecret,\n                'redirect'      => $appInstagramRedirect,\n            ],\n            'services.linkedin' => [\n                'client_id'     => $appLinkedInId,\n                'client_secret' => $appLinkedInSecret,\n                'redirect'      => $appLinkedInRedirect,\n            ],\n            'services.apple' => [\n                'client_id'     => $appAppleId,\n                'client_secret' => $appAppleSecret,\n                'redirect'      => $appAppleRedirect,\n                'team_id'       => $appAppleTeamId,\n                'key_id'        => $appAppleKeyId,\n                'private_key'   => $appApplePrivateKey,\n            ],\n            'services.microsoft' => [\n                'client_id'     => $appMicrosoftId,\n                'client_secret' => $appMicrosoftSecret,\n                'redirect'      => $appMicrosoftRedirect,\n            ],\n            'services.tiktok' => [\n                'client_id'     => $appTikTokId,\n                'client_secret' => $appTikTokSecret,\n                'redirect'      => $appTikTokRedirect,\n            ],\n            'services.zoho' => [\n                'client_id'     => $appZoHoId,\n                'client_secret' => $appZoHoSecret,\n                'redirect'      => $appZoHoRedirect,\n            ],\n            'services.stackexchange' => [\n                'client_id'     => $appStackExchangeId,\n                'client_secret' => $appStackExchangeSecret,\n                'redirect'      => $appStackExchangeRedirect,\n                'key'           => $appStackExchangeKey,\n                'site'          => $appStackExchangeSite,\n            ],\n            'services.gitlab' => [\n                'client_id'     => $appGitLabId,\n                'client_secret' => $appGitLabSecret,\n                'redirect'      => $appGitLabRedirect,\n            ],\n            'services.reddit' => [\n                'client_id'     => $appRedditId,\n                'client_secret' => $appRedditSecret,\n                'response_type' => $appRedditResponseType,\n                'state'         => $appRedditState,\n                'redirect'      => $appRedditRedirect,\n            ],\n            'services.snapchat' => [\n                'client_id'     => $appSnapchatId,\n                'client_secret' => $appSnapchatSecret,\n                'redirect'      => $appSnapchatRedirect,\n            ],\n            'services.meetup' => [\n                'client_id'     => $appMeetupId,\n                'client_secret' => $appMeetupSecret,\n                'redirect'      => $appMeetupRedirect,\n            ],\n            'services.atlassian' => [\n                'client_id'     => $appAtlassianId,\n                'client_secret' => $appAtlassianSecret,\n                'redirect'      => $appAtlassianRedirect,\n            ],\n\n            // NEW_PROVIDER_PLUG :: Put New Provider HERE\n        ];\n\n        $this->providerConfigs = $providerConfigs;\n    }\n\n    /**\n     * Set provider configs on the systems config dynamically.\n     */\n    protected function setAppProvidersConfigs()\n    {\n        config($this->providerConfigs);\n    }\n\n    /**\n     * This is the list of logins enabled for the front end of the app.\n     *\n     * @return array\n     */\n    protected function loginsList()\n    {\n        $this->setupProviders();\n        $ps = $this->providerSettings;\n        $enableFbLogin = $ps->firstWhere('key', 'enableFbLogin')->val;\n        $enableTwitterLogin = $ps->firstWhere('key', 'enableTwitterLogin')->val;\n        $enableGoogleLogin = $ps->firstWhere('key', 'enableGoogleLogin')->val;\n        $enableGitHubLogin = $ps->firstWhere('key', 'enableGitHubLogin')->val;\n        $enableTwitchLogin = $ps->firstWhere('key', 'enableTwitchLogin')->val;\n        $enableInstagramLogin = $ps->firstWhere('key', 'enableInstagramLogin')->val;\n        $enableYouTubeLogin = $ps->firstWhere('key', 'enableYouTubeLogin')->val;\n        $enableLinkedInLogin = $ps->firstWhere('key', 'enableLinkedInLogin')->val;\n        $enableAppleLogin = $ps->firstWhere('key', 'enableAppleLogin')->val;\n        $enableMicrosoftLogin = $ps->firstWhere('key', 'enableMicrosoftLogin')->val;\n        $enableTikTokLogin = $ps->firstWhere('key', 'enableTikTokLogin')->val;\n        $enableZoHoLogin = $ps->firstWhere('key', 'enableZoHoLogin')->val;\n        $enableStackExchangeLogin = $ps->firstWhere('key', 'enableStackExchangeLogin')->val;\n        $enableGitLabLogin = $ps->firstWhere('key', 'enableGitLabLogin')->val;\n        $enableRedditLogin = $ps->firstWhere('key', 'enableRedditLogin')->val;\n        $enableSnapchatLogin = $ps->firstWhere('key', 'enableSnapchatLogin')->val;\n        $enableMeetupLogin = $ps->firstWhere('key', 'enableMeetupLogin')->val;\n        $enableAtlassianLogin = $ps->firstWhere('key', 'enableAtlassianLogin')->val;\n\n        // NEW_PROVIDER_PLUG :: Put New Provider HERE\n\n        return [\n            'facebook'          => $enableFbLogin,\n            'twitter'           => $enableTwitterLogin,\n            'google'            => $enableGoogleLogin,\n            'instagram'         => $enableInstagramLogin,\n            'github'            => $enableGitHubLogin,\n            'youtube'           => $enableYouTubeLogin,\n            'linkedin'          => $enableLinkedInLogin,\n            'twitch'            => $enableTwitchLogin,\n            'apple'             => $enableAppleLogin,\n            'microsoft'         => $enableMicrosoftLogin,\n            'tiktok'            => $enableTikTokLogin,\n            'zoho'              => $enableZoHoLogin,\n            'stackexchange'     => $enableStackExchangeLogin,\n            'gitlab'            => $enableGitLabLogin,\n            'reddit'            => $enableRedditLogin,\n            'snapchat'          => $enableSnapchatLogin,\n            'meetup'            => $enableMeetupLogin,\n            'atlassian'         => $enableAtlassianLogin,\n\n            // NEW_PROVIDER_PLUG :: Put New Provider HERE\n        ];\n    }\n\n    /**\n     * Find or create a user.\n     *\n     * @param  string  $provider\n     * @param  SocialiteUser  $user\n     * @return array\n     */\n    protected function findOrCreateUser(string $provider, $user, string $state = null): array\n    {\n        $existingUser = null;\n        $token = null;\n        $email = null;\n\n        if ($provider == 'twitter') {\n            // OK - No error\n            $email = $user->email;\n            $providerId = $user->id;\n        } else {\n            $email = $user->getEmail();\n            $providerId = $user->getId();\n        }\n\n        $oauthProvider = SocialiteProvider::where('provider', $provider)\n            ->where('provider_user_id', $providerId)\n            ->first();\n\n        if ($state && $state != config('app.key')) {\n            $token = PersonalAccessToken::findToken($state);\n            if ($token) {\n                $existingUser = $token->tokenable;\n            }\n            if ($existingUser && $existingUser->id && $oauthProvider && $oauthProvider->user_id && ($existingUser->id != $oauthProvider->user_id)) {\n                return [\n                    'user'  => null,\n                    'token' => null,\n                ];\n            }\n        }\n\n        if ($oauthProvider) {\n            return [\n                'user'  => $oauthProvider->user,\n                'token' => $oauthProvider->user->createToken($provider.'-token')->plainTextToken,\n            ];\n        }\n\n        if (! $existingUser) {\n            $existingUser = User::whereEmail($email)->first();\n        }\n\n        if (! $existingUser) {\n            $existingUser = auth('sanctum')->user();\n        }\n\n        if ($existingUser && $oauthProvider) {\n            if ($provider != 'twitter') {\n                $oauthProvider->update([\n                    'access_token'  => $user->token ? $user->token : null,\n                    'refresh_token' => $user->refreshToken ? $user->refreshToken : null,\n                ]);\n            }\n\n            return [\n                'user'  => $oauthProvider->user,\n                'token' => $oauthProvider->user->createToken($provider.'-token')->plainTextToken,\n            ];\n        }\n\n        $user = $this->updateOrCreateUser($provider, $user, $existingUser);\n        $token = $user->createToken($provider.'-token')->plainTextToken;\n\n        return [\n            'user'  => $user,\n            'token' => $token,\n        ];\n    }\n\n    /**\n     * Create a new user.\n     *\n     * @param  string  $provider\n     * @param  $sUser\n     * @return \\App\\Models\\User | null\n     */\n    protected function updateOrCreateUser(string $provider, $sUser, $existingUser = null): User\n    {\n        $user = null;\n        $pid = null;\n        $email = null;\n        $token = null;\n        $refreshToken = null;\n        $avatar = null;\n        $emailValid = true;\n\n        if ($existingUser) {\n            $user = $existingUser;\n            $email = $user->email;\n            if ($provider == 'twitter') {\n                $pid = $sUser->id;\n                $avatar = $sUser->profile_image_url;\n            } else {\n                $pid = $sUser->getId();\n            }\n        } else {\n            if ($provider == 'twitter') {\n                $pid = $sUser->id;\n                $email = $sUser->email;\n                $name = $sUser->name;\n                $avatar = $sUser->profile_image_url;\n            } else {\n                $pid = $sUser->getId();\n                $name = $sUser->getName();\n                $email = $sUser->getEmail();\n                $avatar = $sUser->getAvatar();\n                $token = $sUser->token;\n                $refreshToken = $sUser->refreshToken;\n            }\n\n            if ($provider == 'reddit') {\n                $name = $sUser->getNickname();\n            }\n\n            if (! $email) {\n                $email = 'email_missing_'.Str::random(20).'@'.Str::random(20).'.example.org';\n                $emailValid = false;\n            }\n\n            $user = User::create([\n                'name'              => $name,\n                'email'             => $email,\n                'password'          => bcrypt(Str::random(50)),\n            ]);\n\n            // $user->attachRole(config('roles.models.role')::whereName('User')->first());\n\n            if ($user->email && $emailValid) {\n                event(new Registered($user));\n                // $user->email_verified_at = Carbon::now();\n            }\n\n            $user->save();\n        }\n\n        $this->addSocialiteProviderToUser($user, [\n            'provider'          => $provider,\n            'provider_user_id'  => $pid,\n            'access_token'      => $token,\n            'refresh_token'     => $refreshToken,\n            'avatar'            => $avatar,\n        ]);\n\n        return $user;\n    }\n\n    /**\n     * Update or Create a Socialite Provider.\n     *\n     * @param  \\App\\Models\\User  $user  [description]\n     * @param  array  $data\n     * @return \\App\\Models\\SocialiteProvider\n     */\n    protected function addSocialiteProviderToUser(User $user, $data): SocialiteProvider\n    {\n        $provider = SocialiteProvider::where('user_id', $user->id)\n                                ->where('provider', $data['provider'])\n                                ->where('provider_user_id', $data['provider_user_id'])->first();\n\n        if ($provider) {\n            return $provider->update([\n                'access_token'      => $data['access_token'],\n                'refresh_token'     => $data['refresh_token'],\n                'avatar'            => $data['avatar'],\n            ]);\n        }\n\n        return $user->socialiteProviders()->create([\n            'provider'          => $data['provider'],\n            'provider_user_id'  => $data['provider_user_id'],\n            'access_token'      => $data['access_token'],\n            'refresh_token'     => $data['refresh_token'],\n            'avatar'            => $data['avatar'],\n        ]);\n    }\n\n    /**\n     * Generate a random string for temp Id.\n     *\n     * @param  int  $depth\n     * @return string\n     */\n    protected function generateTempId($depth = 40)\n    {\n        return Str::random($depth);\n    }\n\n    /**\n     * Cache the current state and modify the url with a random string to be the key for the return user.\n     * Not all providers return the state and this will allow us to do so..\n     *\n     * @param  sting $url\n     * @param  sting $state\n     * @return string\n     */\n    protected function cacheStatePutKeyInUrl($url = null, $state = null)\n    {\n        $tempId = $this->generateTempId();\n        $this->tempStoreStateInCache($tempId, $state);\n\n        return $url.'&state='.$tempId;\n    }\n\n    /**\n     * Cache the state temporarily to pick up on callback.\n     *\n     * @param  string  $tempId\n     * @param  string  $state\n     * @param  int  $seconds\n     * @return void\n     */\n    protected function tempStoreStateInCache($tempId, $state, $seconds = 60)\n    {\n        Cache::put($tempId, $state, $seconds);\n    }\n}\n"
  },
  {
    "path": "artisan",
    "content": "#!/usr/bin/env php\n<?php\n\nuse Symfony\\Component\\Console\\Input\\ArgvInput;\n\ndefine('LARAVEL_START', microtime(true));\n\n// Register the Composer autoloader...\nrequire __DIR__.'/vendor/autoload.php';\n\n// Bootstrap Laravel and handle the command...\n$status = (require_once __DIR__.'/bootstrap/app.php')\n    ->handleCommand(new ArgvInput);\n\nexit($status);\n"
  },
  {
    "path": "bootstrap/app.php",
    "content": "<?php\n\nuse Illuminate\\Foundation\\Application;\nuse Illuminate\\Foundation\\Configuration\\Exceptions;\nuse Illuminate\\Foundation\\Configuration\\Middleware;\n\nreturn Application::configure(basePath: dirname(__DIR__))\n    ->withRouting(\n        web: __DIR__.'/../routes/web.php',\n        commands: __DIR__.'/../routes/console.php',\n        health: '/up',\n    )\n    ->withMiddleware(function (Middleware $middleware) {\n        $middleware->web(append: [\n            \\App\\Http\\Middleware\\HandleInertiaRequests::class,\n            \\Illuminate\\Http\\Middleware\\AddLinkHeadersForPreloadedAssets::class,\n        ]);\n\n        //\n    })\n    ->withExceptions(function (Exceptions $exceptions) {\n        //\n    })->create();\n"
  },
  {
    "path": "bootstrap/cache/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "bootstrap/providers.php",
    "content": "<?php\n\nreturn [\n    App\\Providers\\AppServiceProvider::class,\n];\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"laravel/laravel\",\n    \"type\": \"project\",\n    \"description\": \"The skeleton application for the Laravel framework.\",\n    \"keywords\": [\"laravel\", \"framework\"],\n    \"license\": \"MIT\",\n    \"require\": {\n        \"php\": \"^8.2\",\n        \"inertiajs/inertia-laravel\": \"^1.0\",\n        \"laravel/framework\": \"^11.0\",\n        \"laravel/sanctum\": \"^4.0\",\n        \"laravel/socialite\": \"^5.15\",\n        \"laravel/tinker\": \"^2.9\",\n        \"spatie/laravel-permission\": \"^6.7\",\n        \"tightenco/ziggy\": \"^2.0\"\n    },\n    \"require-dev\": {\n        \"fakerphp/faker\": \"^1.23\",\n        \"larastan/larastan\": \"^2.9\",\n        \"laravel/breeze\": \"^2.0\",\n        \"laravel/pint\": \"^1.13\",\n        \"laravel/sail\": \"^1.26\",\n        \"mockery/mockery\": \"^1.6\",\n        \"nunomaduro/collision\": \"^8.0\",\n        \"phpunit/phpunit\": \"^11.0.1\",\n        \"spatie/laravel-ignition\": \"^2.4\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"App\\\\\": \"app/\",\n            \"Database\\\\Factories\\\\\": \"database/factories/\",\n            \"Database\\\\Seeders\\\\\": \"database/seeders/\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"Tests\\\\\": \"tests/\"\n        }\n    },\n    \"scripts\": {\n        \"post-autoload-dump\": [\n            \"Illuminate\\\\Foundation\\\\ComposerScripts::postAutoloadDump\",\n            \"@php artisan package:discover --ansi\"\n        ],\n        \"post-update-cmd\": [\n            \"@php artisan vendor:publish --tag=laravel-assets --ansi --force\"\n        ],\n        \"post-root-package-install\": [\n            \"@php -r \\\"file_exists('.env') || copy('.env.example', '.env');\\\"\"\n        ],\n        \"post-create-project-cmd\": [\n            \"@php artisan key:generate --ansi\",\n            \"@php -r \\\"file_exists('database/database.sqlite') || touch('database/database.sqlite');\\\"\",\n            \"@php artisan migrate --graceful --ansi\"\n        ],\n        \"phpstan\": [\n            \"./vendor/bin/phpstan analyse --memory-limit=1G\"\n        ]\n    },\n    \"scripts-descriptions\": {\n        \"phpstan\": \"Run PHPStan static analysis against your application.\"\n    },\n    \"extra\": {\n        \"laravel\": {\n            \"dont-discover\": []\n        }\n    },\n    \"config\": {\n        \"optimize-autoloader\": true,\n        \"preferred-install\": \"dist\",\n        \"sort-packages\": true,\n        \"allow-plugins\": {\n            \"pestphp/pest-plugin\": true,\n            \"php-http/discovery\": true\n        }\n    },\n    \"minimum-stability\": \"stable\",\n    \"prefer-stable\": true\n}\n"
  },
  {
    "path": "config/app.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Name\n    |--------------------------------------------------------------------------\n    |\n    | This value is the name of your application, which will be used when the\n    | framework needs to place the application's name in a notification or\n    | other UI elements where an application name needs to be displayed.\n    |\n    */\n\n    'name' => env('APP_NAME', 'Laravel'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Environment\n    |--------------------------------------------------------------------------\n    |\n    | This value determines the \"environment\" your application is currently\n    | running in. This may determine how you prefer to configure various\n    | services the application utilizes. Set this in your \".env\" file.\n    |\n    */\n\n    'env' => env('APP_ENV', 'production'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Debug Mode\n    |--------------------------------------------------------------------------\n    |\n    | When your application is in debug mode, detailed error messages with\n    | stack traces will be shown on every error that occurs within your\n    | application. If disabled, a simple generic error page is shown.\n    |\n    */\n\n    'debug' => (bool) env('APP_DEBUG', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application URL\n    |--------------------------------------------------------------------------\n    |\n    | This URL is used by the console to properly generate URLs when using\n    | the Artisan command line tool. You should set this to the root of\n    | the application so that it's available within Artisan commands.\n    |\n    */\n\n    'url' => env('APP_URL', 'http://localhost'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Timezone\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the default timezone for your application, which\n    | will be used by the PHP date and date-time functions. The timezone\n    | is set to \"UTC\" by default as it is suitable for most use cases.\n    |\n    */\n\n    'timezone' => env('APP_TIMEZONE', 'UTC'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Locale Configuration\n    |--------------------------------------------------------------------------\n    |\n    | The application locale determines the default locale that will be used\n    | by Laravel's translation / localization methods. This option can be\n    | set to any locale for which you plan to have translation strings.\n    |\n    */\n\n    'locale' => env('APP_LOCALE', 'en'),\n\n    'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),\n\n    'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Encryption Key\n    |--------------------------------------------------------------------------\n    |\n    | This key is utilized by Laravel's encryption services and should be set\n    | to a random, 32 character string to ensure that all encrypted values\n    | are secure. You should do this prior to deploying the application.\n    |\n    */\n\n    'cipher' => 'AES-256-CBC',\n\n    'key' => env('APP_KEY'),\n\n    'previous_keys' => [\n        ...array_filter(\n            explode(',', env('APP_PREVIOUS_KEYS', ''))\n        ),\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Maintenance Mode Driver\n    |--------------------------------------------------------------------------\n    |\n    | These configuration options determine the driver used to determine and\n    | manage Laravel's \"maintenance mode\" status. The \"cache\" driver will\n    | allow maintenance mode to be controlled across multiple machines.\n    |\n    | Supported drivers: \"file\", \"cache\"\n    |\n    */\n\n    'maintenance' => [\n        'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),\n        'store' => env('APP_MAINTENANCE_STORE', 'database'),\n    ],\n\n];\n"
  },
  {
    "path": "config/auth.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Defaults\n    |--------------------------------------------------------------------------\n    |\n    | This option defines the default authentication \"guard\" and password\n    | reset \"broker\" for your application. You may change these values\n    | as required, but they're a perfect start for most applications.\n    |\n    */\n\n    'defaults' => [\n        'guard' => env('AUTH_GUARD', 'web'),\n        'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Guards\n    |--------------------------------------------------------------------------\n    |\n    | Next, you may define every authentication guard for your application.\n    | Of course, a great default configuration has been defined for you\n    | which utilizes session storage plus the Eloquent user provider.\n    |\n    | All authentication guards have a user provider, which defines how the\n    | users are actually retrieved out of your database or other storage\n    | system used by the application. Typically, Eloquent is utilized.\n    |\n    | Supported: \"session\"\n    |\n    */\n\n    'guards' => [\n        'web' => [\n            'driver' => 'session',\n            'provider' => 'users',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | User Providers\n    |--------------------------------------------------------------------------\n    |\n    | All authentication guards have a user provider, which defines how the\n    | users are actually retrieved out of your database or other storage\n    | system used by the application. Typically, Eloquent is utilized.\n    |\n    | If you have multiple user tables or models you may configure multiple\n    | providers to represent the model / table. These providers may then\n    | be assigned to any extra authentication guards you have defined.\n    |\n    | Supported: \"database\", \"eloquent\"\n    |\n    */\n\n    'providers' => [\n        'users' => [\n            'driver' => 'eloquent',\n            'model' => env('AUTH_MODEL', App\\Models\\User::class),\n        ],\n\n        // 'users' => [\n        //     'driver' => 'database',\n        //     'table' => 'users',\n        // ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Resetting Passwords\n    |--------------------------------------------------------------------------\n    |\n    | These configuration options specify the behavior of Laravel's password\n    | reset functionality, including the table utilized for token storage\n    | and the user provider that is invoked to actually retrieve users.\n    |\n    | The expiry time is the number of minutes that each reset token will be\n    | considered valid. This security feature keeps tokens short-lived so\n    | they have less time to be guessed. You may change this as needed.\n    |\n    | The throttle setting is the number of seconds a user must wait before\n    | generating more password reset tokens. This prevents the user from\n    | quickly generating a very large amount of password reset tokens.\n    |\n    */\n\n    'passwords' => [\n        'users' => [\n            'provider' => 'users',\n            'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),\n            'expire' => 60,\n            'throttle' => 60,\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Password Confirmation Timeout\n    |--------------------------------------------------------------------------\n    |\n    | Here you may define the amount of seconds before a password confirmation\n    | window expires and users are asked to re-enter their password via the\n    | confirmation screen. By default, the timeout lasts for three hours.\n    |\n    */\n\n    'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),\n\n];\n"
  },
  {
    "path": "config/cache.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Str;\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Cache Store\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default cache store that will be used by the\n    | framework. This connection is utilized if another isn't explicitly\n    | specified when running a cache operation inside the application.\n    |\n    */\n\n    'default' => env('CACHE_STORE', 'database'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Cache Stores\n    |--------------------------------------------------------------------------\n    |\n    | Here you may define all of the cache \"stores\" for your application as\n    | well as their drivers. You may even define multiple stores for the\n    | same cache driver to group types of items stored in your caches.\n    |\n    | Supported drivers: \"array\", \"database\", \"file\", \"memcached\",\n    |                    \"redis\", \"dynamodb\", \"octane\", \"null\"\n    |\n    */\n\n    'stores' => [\n\n        'array' => [\n            'driver' => 'array',\n            'serialize' => false,\n        ],\n\n        'database' => [\n            'driver' => 'database',\n            'table' => env('DB_CACHE_TABLE', 'cache'),\n            'connection' => env('DB_CACHE_CONNECTION'),\n            'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),\n        ],\n\n        'file' => [\n            'driver' => 'file',\n            'path' => storage_path('framework/cache/data'),\n            'lock_path' => storage_path('framework/cache/data'),\n        ],\n\n        'memcached' => [\n            'driver' => 'memcached',\n            'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),\n            'sasl' => [\n                env('MEMCACHED_USERNAME'),\n                env('MEMCACHED_PASSWORD'),\n            ],\n            'options' => [\n                // Memcached::OPT_CONNECT_TIMEOUT => 2000,\n            ],\n            'servers' => [\n                [\n                    'host' => env('MEMCACHED_HOST', '127.0.0.1'),\n                    'port' => env('MEMCACHED_PORT', 11211),\n                    'weight' => 100,\n                ],\n            ],\n        ],\n\n        'redis' => [\n            'driver' => 'redis',\n            'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),\n            'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),\n        ],\n\n        'dynamodb' => [\n            'driver' => 'dynamodb',\n            'key' => env('AWS_ACCESS_KEY_ID'),\n            'secret' => env('AWS_SECRET_ACCESS_KEY'),\n            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),\n            'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),\n            'endpoint' => env('DYNAMODB_ENDPOINT'),\n        ],\n\n        'octane' => [\n            'driver' => 'octane',\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Cache Key Prefix\n    |--------------------------------------------------------------------------\n    |\n    | When utilizing the APC, database, memcached, Redis, and DynamoDB cache\n    | stores, there might be other applications using the same cache. For\n    | that reason, you may prefix every cache key to avoid collisions.\n    |\n    */\n\n    'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'),\n\n];\n"
  },
  {
    "path": "config/database.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Str;\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Database Connection Name\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify which of the database connections below you wish\n    | to use as your default connection for database operations. This is\n    | the connection which will be utilized unless another connection\n    | is explicitly specified when you execute a query / statement.\n    |\n    */\n\n    'default' => env('DB_CONNECTION', 'sqlite'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Database Connections\n    |--------------------------------------------------------------------------\n    |\n    | Below are all of the database connections defined for your application.\n    | An example configuration is provided for each database system which\n    | is supported by Laravel. You're free to add / remove connections.\n    |\n    */\n\n    'connections' => [\n\n        'sqlite' => [\n            'driver' => 'sqlite',\n            'url' => env('DB_URL'),\n            'database' => env('DB_DATABASE', database_path('database.sqlite')),\n            'prefix' => '',\n            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),\n        ],\n\n        'mysql' => [\n            'driver' => 'mysql',\n            'url' => env('DB_URL'),\n            'host' => env('DB_HOST', '127.0.0.1'),\n            'port' => env('DB_PORT', '3306'),\n            'database' => env('DB_DATABASE', 'laravel'),\n            'username' => env('DB_USERNAME', 'root'),\n            'password' => env('DB_PASSWORD', ''),\n            'unix_socket' => env('DB_SOCKET', ''),\n            'charset' => env('DB_CHARSET', 'utf8mb4'),\n            'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),\n            'prefix' => '',\n            'prefix_indexes' => true,\n            'strict' => true,\n            'engine' => null,\n            'options' => extension_loaded('pdo_mysql') ? array_filter([\n                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),\n            ]) : [],\n        ],\n\n        'mariadb' => [\n            'driver' => 'mariadb',\n            'url' => env('DB_URL'),\n            'host' => env('DB_HOST', '127.0.0.1'),\n            'port' => env('DB_PORT', '3306'),\n            'database' => env('DB_DATABASE', 'laravel'),\n            'username' => env('DB_USERNAME', 'root'),\n            'password' => env('DB_PASSWORD', ''),\n            'unix_socket' => env('DB_SOCKET', ''),\n            'charset' => env('DB_CHARSET', 'utf8mb4'),\n            'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),\n            'prefix' => '',\n            'prefix_indexes' => true,\n            'strict' => true,\n            'engine' => null,\n            'options' => extension_loaded('pdo_mysql') ? array_filter([\n                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),\n            ]) : [],\n        ],\n\n        'pgsql' => [\n            'driver' => 'pgsql',\n            'url' => env('DB_URL'),\n            'host' => env('DB_HOST', '127.0.0.1'),\n            'port' => env('DB_PORT', '5432'),\n            'database' => env('DB_DATABASE', 'laravel'),\n            'username' => env('DB_USERNAME', 'root'),\n            'password' => env('DB_PASSWORD', ''),\n            'charset' => env('DB_CHARSET', 'utf8'),\n            'prefix' => '',\n            'prefix_indexes' => true,\n            'search_path' => 'public',\n            'sslmode' => 'prefer',\n        ],\n\n        'sqlsrv' => [\n            'driver' => 'sqlsrv',\n            'url' => env('DB_URL'),\n            'host' => env('DB_HOST', 'localhost'),\n            'port' => env('DB_PORT', '1433'),\n            'database' => env('DB_DATABASE', 'laravel'),\n            'username' => env('DB_USERNAME', 'root'),\n            'password' => env('DB_PASSWORD', ''),\n            'charset' => env('DB_CHARSET', 'utf8'),\n            'prefix' => '',\n            'prefix_indexes' => true,\n            // 'encrypt' => env('DB_ENCRYPT', 'yes'),\n            // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Migration Repository Table\n    |--------------------------------------------------------------------------\n    |\n    | This table keeps track of all the migrations that have already run for\n    | your application. Using this information, we can determine which of\n    | the migrations on disk haven't actually been run on the database.\n    |\n    */\n\n    'migrations' => [\n        'table' => 'migrations',\n        'update_date_on_publish' => true,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Redis Databases\n    |--------------------------------------------------------------------------\n    |\n    | Redis is an open source, fast, and advanced key-value store that also\n    | provides a richer body of commands than a typical key-value system\n    | such as Memcached. You may define your connection settings here.\n    |\n    */\n\n    'redis' => [\n\n        'client' => env('REDIS_CLIENT', 'phpredis'),\n\n        'options' => [\n            'cluster' => env('REDIS_CLUSTER', 'redis'),\n            'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),\n        ],\n\n        'default' => [\n            'url' => env('REDIS_URL'),\n            'host' => env('REDIS_HOST', '127.0.0.1'),\n            'username' => env('REDIS_USERNAME'),\n            'password' => env('REDIS_PASSWORD'),\n            'port' => env('REDIS_PORT', '6379'),\n            'database' => env('REDIS_DB', '0'),\n        ],\n\n        'cache' => [\n            'url' => env('REDIS_URL'),\n            'host' => env('REDIS_HOST', '127.0.0.1'),\n            'username' => env('REDIS_USERNAME'),\n            'password' => env('REDIS_PASSWORD'),\n            'port' => env('REDIS_PORT', '6379'),\n            'database' => env('REDIS_CACHE_DB', '1'),\n        ],\n\n    ],\n\n];\n"
  },
  {
    "path": "config/filesystems.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Filesystem Disk\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the default filesystem disk that should be used\n    | by the framework. The \"local\" disk, as well as a variety of cloud\n    | based disks are available to your application for file storage.\n    |\n    */\n\n    'default' => env('FILESYSTEM_DISK', 'local'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Filesystem Disks\n    |--------------------------------------------------------------------------\n    |\n    | Below you may configure as many filesystem disks as necessary, and you\n    | may even configure multiple disks for the same driver. Examples for\n    | most supported storage drivers are configured here for reference.\n    |\n    | Supported Drivers: \"local\", \"ftp\", \"sftp\", \"s3\"\n    |\n    */\n\n    'disks' => [\n\n        'local' => [\n            'driver' => 'local',\n            'root' => storage_path('app'),\n            'throw' => false,\n        ],\n\n        'public' => [\n            'driver' => 'local',\n            'root' => storage_path('app/public'),\n            'url' => env('APP_URL').'/storage',\n            'visibility' => 'public',\n            'throw' => false,\n        ],\n\n        's3' => [\n            'driver' => 's3',\n            'key' => env('AWS_ACCESS_KEY_ID'),\n            'secret' => env('AWS_SECRET_ACCESS_KEY'),\n            'region' => env('AWS_DEFAULT_REGION'),\n            'bucket' => env('AWS_BUCKET'),\n            'url' => env('AWS_URL'),\n            'endpoint' => env('AWS_ENDPOINT'),\n            'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),\n            'throw' => false,\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Symbolic Links\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure the symbolic links that will be created when the\n    | `storage:link` Artisan command is executed. The array keys should be\n    | the locations of the links and the values should be their targets.\n    |\n    */\n\n    'links' => [\n        public_path('storage') => storage_path('app/public'),\n    ],\n\n];\n"
  },
  {
    "path": "config/logging.php",
    "content": "<?php\n\nuse Monolog\\Handler\\NullHandler;\nuse Monolog\\Handler\\StreamHandler;\nuse Monolog\\Handler\\SyslogUdpHandler;\nuse Monolog\\Processor\\PsrLogMessageProcessor;\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Log Channel\n    |--------------------------------------------------------------------------\n    |\n    | This option defines the default log channel that is utilized to write\n    | messages to your logs. The value provided here should match one of\n    | the channels present in the list of \"channels\" configured below.\n    |\n    */\n\n    'default' => env('LOG_CHANNEL', 'stack'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Deprecations Log Channel\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the log channel that should be used to log warnings\n    | regarding deprecated PHP and library features. This allows you to get\n    | your application ready for upcoming major versions of dependencies.\n    |\n    */\n\n    'deprecations' => [\n        'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),\n        'trace' => env('LOG_DEPRECATIONS_TRACE', false),\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Log Channels\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure the log channels for your application. Laravel\n    | utilizes the Monolog PHP logging library, which includes a variety\n    | of powerful log handlers and formatters that you're free to use.\n    |\n    | Available Drivers: \"single\", \"daily\", \"slack\", \"syslog\",\n    |                    \"errorlog\", \"monolog\", \"custom\", \"stack\"\n    |\n    */\n\n    'channels' => [\n\n        'stack' => [\n            'driver' => 'stack',\n            'channels' => explode(',', env('LOG_STACK', 'single')),\n            'ignore_exceptions' => false,\n        ],\n\n        'single' => [\n            'driver' => 'single',\n            'path' => storage_path('logs/laravel.log'),\n            'level' => env('LOG_LEVEL', 'debug'),\n            'replace_placeholders' => true,\n        ],\n\n        'daily' => [\n            'driver' => 'daily',\n            'path' => storage_path('logs/laravel.log'),\n            'level' => env('LOG_LEVEL', 'debug'),\n            'days' => env('LOG_DAILY_DAYS', 14),\n            'replace_placeholders' => true,\n        ],\n\n        'slack' => [\n            'driver' => 'slack',\n            'url' => env('LOG_SLACK_WEBHOOK_URL'),\n            'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),\n            'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),\n            'level' => env('LOG_LEVEL', 'critical'),\n            'replace_placeholders' => true,\n        ],\n\n        'papertrail' => [\n            'driver' => 'monolog',\n            'level' => env('LOG_LEVEL', 'debug'),\n            'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),\n            'handler_with' => [\n                'host' => env('PAPERTRAIL_URL'),\n                'port' => env('PAPERTRAIL_PORT'),\n                'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),\n            ],\n            'processors' => [PsrLogMessageProcessor::class],\n        ],\n\n        'stderr' => [\n            'driver' => 'monolog',\n            'level' => env('LOG_LEVEL', 'debug'),\n            'handler' => StreamHandler::class,\n            'formatter' => env('LOG_STDERR_FORMATTER'),\n            'with' => [\n                'stream' => 'php://stderr',\n            ],\n            'processors' => [PsrLogMessageProcessor::class],\n        ],\n\n        'syslog' => [\n            'driver' => 'syslog',\n            'level' => env('LOG_LEVEL', 'debug'),\n            'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),\n            'replace_placeholders' => true,\n        ],\n\n        'errorlog' => [\n            'driver' => 'errorlog',\n            'level' => env('LOG_LEVEL', 'debug'),\n            'replace_placeholders' => true,\n        ],\n\n        'null' => [\n            'driver' => 'monolog',\n            'handler' => NullHandler::class,\n        ],\n\n        'emergency' => [\n            'path' => storage_path('logs/laravel.log'),\n        ],\n\n    ],\n\n];\n"
  },
  {
    "path": "config/mail.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Mailer\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default mailer that is used to send all email\n    | messages unless another mailer is explicitly specified when sending\n    | the message. All additional mailers can be configured within the\n    | \"mailers\" array. Examples of each type of mailer are provided.\n    |\n    */\n\n    'default' => env('MAIL_MAILER', 'log'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Mailer Configurations\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure all of the mailers used by your application plus\n    | their respective settings. Several examples have been configured for\n    | you and you are free to add your own as your application requires.\n    |\n    | Laravel supports a variety of mail \"transport\" drivers that can be used\n    | when delivering an email. You may specify which one you're using for\n    | your mailers below. You may also add additional mailers if needed.\n    |\n    | Supported: \"smtp\", \"sendmail\", \"mailgun\", \"ses\", \"ses-v2\",\n    |            \"postmark\", \"log\", \"array\", \"failover\", \"roundrobin\"\n    |\n    */\n\n    'mailers' => [\n\n        'smtp' => [\n            'transport' => 'smtp',\n            'url' => env('MAIL_URL'),\n            'host' => env('MAIL_HOST', '127.0.0.1'),\n            'port' => env('MAIL_PORT', 2525),\n            'encryption' => env('MAIL_ENCRYPTION', 'tls'),\n            'username' => env('MAIL_USERNAME'),\n            'password' => env('MAIL_PASSWORD'),\n            'timeout' => null,\n            'local_domain' => env('MAIL_EHLO_DOMAIN'),\n        ],\n\n        'ses' => [\n            'transport' => 'ses',\n        ],\n\n        'postmark' => [\n            'transport' => 'postmark',\n            // 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),\n            // 'client' => [\n            //     'timeout' => 5,\n            // ],\n        ],\n\n        'sendmail' => [\n            'transport' => 'sendmail',\n            'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),\n        ],\n\n        'log' => [\n            'transport' => 'log',\n            'channel' => env('MAIL_LOG_CHANNEL'),\n        ],\n\n        'array' => [\n            'transport' => 'array',\n        ],\n\n        'failover' => [\n            'transport' => 'failover',\n            'mailers' => [\n                'smtp',\n                'log',\n            ],\n        ],\n\n        'roundrobin' => [\n            'transport' => 'roundrobin',\n            'mailers' => [\n                'ses',\n                'postmark',\n            ],\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Global \"From\" Address\n    |--------------------------------------------------------------------------\n    |\n    | You may wish for all emails sent by your application to be sent from\n    | the same address. Here you may specify a name and address that is\n    | used globally for all emails that are sent by your application.\n    |\n    */\n\n    'from' => [\n        'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),\n        'name' => env('MAIL_FROM_NAME', 'Example'),\n    ],\n\n];\n"
  },
  {
    "path": "config/permission.php",
    "content": "<?php\n\nreturn [\n\n    'models' => [\n\n        /*\n         * When using the \"HasPermissions\" trait from this package, we need to know which\n         * Eloquent model should be used to retrieve your permissions. Of course, it\n         * is often just the \"Permission\" model but you may use whatever you like.\n         *\n         * The model you want to use as a Permission model needs to implement the\n         * `Spatie\\Permission\\Contracts\\Permission` contract.\n         */\n\n        'permission' => Spatie\\Permission\\Models\\Permission::class,\n\n        /*\n         * When using the \"HasRoles\" trait from this package, we need to know which\n         * Eloquent model should be used to retrieve your roles. Of course, it\n         * is often just the \"Role\" model but you may use whatever you like.\n         *\n         * The model you want to use as a Role model needs to implement the\n         * `Spatie\\Permission\\Contracts\\Role` contract.\n         */\n\n        'role' => Spatie\\Permission\\Models\\Role::class,\n\n    ],\n\n    'table_names' => [\n\n        /*\n         * When using the \"HasRoles\" trait from this package, we need to know which\n         * table should be used to retrieve your roles. We have chosen a basic\n         * default value but you may easily change it to any table you like.\n         */\n\n        'roles' => 'roles',\n\n        /*\n         * When using the \"HasPermissions\" trait from this package, we need to know which\n         * table should be used to retrieve your permissions. We have chosen a basic\n         * default value but you may easily change it to any table you like.\n         */\n\n        'permissions' => 'permissions',\n\n        /*\n         * When using the \"HasPermissions\" trait from this package, we need to know which\n         * table should be used to retrieve your models permissions. We have chosen a\n         * basic default value but you may easily change it to any table you like.\n         */\n\n        'model_has_permissions' => 'model_has_permissions',\n\n        /*\n         * When using the \"HasRoles\" trait from this package, we need to know which\n         * table should be used to retrieve your models roles. We have chosen a\n         * basic default value but you may easily change it to any table you like.\n         */\n\n        'model_has_roles' => 'model_has_roles',\n\n        /*\n         * When using the \"HasRoles\" trait from this package, we need to know which\n         * table should be used to retrieve your roles permissions. We have chosen a\n         * basic default value but you may easily change it to any table you like.\n         */\n\n        'role_has_permissions' => 'role_has_permissions',\n    ],\n\n    'column_names' => [\n        /*\n         * Change this if you want to name the related pivots other than defaults\n         */\n        'role_pivot_key' => null, //default 'role_id',\n        'permission_pivot_key' => null, //default 'permission_id',\n\n        /*\n         * Change this if you want to name the related model primary key other than\n         * `model_id`.\n         *\n         * For example, this would be nice if your primary keys are all UUIDs. In\n         * that case, name this `model_uuid`.\n         */\n\n        'model_morph_key' => 'model_id',\n\n        /*\n         * Change this if you want to use the teams feature and your related model's\n         * foreign key is other than `team_id`.\n         */\n\n        'team_foreign_key' => 'team_id',\n    ],\n\n    /*\n     * When set to true, the method for checking permissions will be registered on the gate.\n     * Set this to false if you want to implement custom logic for checking permissions.\n     */\n\n    'register_permission_check_method' => true,\n\n    /*\n     * When set to true, Laravel\\Octane\\Events\\OperationTerminated event listener will be registered\n     * this will refresh permissions on every TickTerminated, TaskTerminated and RequestTerminated\n     * NOTE: This should not be needed in most cases, but an Octane/Vapor combination benefited from it.\n     */\n    'register_octane_reset_listener' => false,\n\n    /*\n     * Teams Feature.\n     * When set to true the package implements teams using the 'team_foreign_key'.\n     * If you want the migrations to register the 'team_foreign_key', you must\n     * set this to true before doing the migration.\n     * If you already did the migration then you must make a new migration to also\n     * add 'team_foreign_key' to 'roles', 'model_has_roles', and 'model_has_permissions'\n     * (view the latest version of this package's migration file)\n     */\n\n    'teams' => false,\n\n    /*\n     * Passport Client Credentials Grant\n     * When set to true the package will use Passports Client to check permissions\n     */\n\n    'use_passport_client_credentials' => false,\n\n    /*\n     * When set to true, the required permission names are added to exception messages.\n     * This could be considered an information leak in some contexts, so the default\n     * setting is false here for optimum safety.\n     */\n\n    'display_permission_in_exception' => false,\n\n    /*\n     * When set to true, the required role names are added to exception messages.\n     * This could be considered an information leak in some contexts, so the default\n     * setting is false here for optimum safety.\n     */\n\n    'display_role_in_exception' => false,\n\n    /*\n     * By default wildcard permission lookups are disabled.\n     * See documentation to understand supported syntax.\n     */\n\n    'enable_wildcard_permission' => false,\n\n    /*\n     * The class to use for interpreting wildcard permissions.\n     * If you need to modify delimiters, override the class and specify its name here.\n     */\n    // 'permission.wildcard_permission' => Spatie\\Permission\\WildcardPermission::class,\n\n    /* Cache-specific settings */\n\n    'cache' => [\n\n        /*\n         * By default all permissions are cached for 24 hours to speed up performance.\n         * When permissions or roles are updated the cache is flushed automatically.\n         */\n\n        'expiration_time' => \\DateInterval::createFromDateString('24 hours'),\n\n        /*\n         * The cache key used to store all permissions.\n         */\n\n        'key' => 'spatie.permission.cache',\n\n        /*\n         * You may optionally indicate a specific cache driver to use for permission and\n         * role caching using any of the `store` drivers listed in the cache.php config\n         * file. Using 'default' here means to use the `default` set in cache.php.\n         */\n\n        'store' => 'default',\n    ],\n];\n"
  },
  {
    "path": "config/queue.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Queue Connection Name\n    |--------------------------------------------------------------------------\n    |\n    | Laravel's queue supports a variety of backends via a single, unified\n    | API, giving you convenient access to each backend using identical\n    | syntax for each. The default queue connection is defined below.\n    |\n    */\n\n    'default' => env('QUEUE_CONNECTION', 'database'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Queue Connections\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure the connection options for every queue backend\n    | used by your application. An example configuration is provided for\n    | each backend supported by Laravel. You're also free to add more.\n    |\n    | Drivers: \"sync\", \"database\", \"beanstalkd\", \"sqs\", \"redis\", \"null\"\n    |\n    */\n\n    'connections' => [\n\n        'sync' => [\n            'driver' => 'sync',\n        ],\n\n        'database' => [\n            'driver' => 'database',\n            'connection' => env('DB_QUEUE_CONNECTION'),\n            'table' => env('DB_QUEUE_TABLE', 'jobs'),\n            'queue' => env('DB_QUEUE', 'default'),\n            'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),\n            'after_commit' => false,\n        ],\n\n        'beanstalkd' => [\n            'driver' => 'beanstalkd',\n            'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),\n            'queue' => env('BEANSTALKD_QUEUE', 'default'),\n            'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),\n            'block_for' => 0,\n            'after_commit' => false,\n        ],\n\n        'sqs' => [\n            'driver' => 'sqs',\n            'key' => env('AWS_ACCESS_KEY_ID'),\n            'secret' => env('AWS_SECRET_ACCESS_KEY'),\n            'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),\n            'queue' => env('SQS_QUEUE', 'default'),\n            'suffix' => env('SQS_SUFFIX'),\n            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),\n            'after_commit' => false,\n        ],\n\n        'redis' => [\n            'driver' => 'redis',\n            'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),\n            'queue' => env('REDIS_QUEUE', 'default'),\n            'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),\n            'block_for' => null,\n            'after_commit' => false,\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Job Batching\n    |--------------------------------------------------------------------------\n    |\n    | The following options configure the database and table that store job\n    | batching information. These options can be updated to any database\n    | connection and table which has been defined by your application.\n    |\n    */\n\n    'batching' => [\n        'database' => env('DB_CONNECTION', 'sqlite'),\n        'table' => 'job_batches',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Failed Queue Jobs\n    |--------------------------------------------------------------------------\n    |\n    | These options configure the behavior of failed queue job logging so you\n    | can control how and where failed jobs are stored. Laravel ships with\n    | support for storing failed jobs in a simple file or in a database.\n    |\n    | Supported drivers: \"database-uuids\", \"dynamodb\", \"file\", \"null\"\n    |\n    */\n\n    'failed' => [\n        'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),\n        'database' => env('DB_CONNECTION', 'sqlite'),\n        'table' => 'failed_jobs',\n    ],\n\n];\n"
  },
  {
    "path": "config/services.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Third Party Services\n    |--------------------------------------------------------------------------\n    |\n    | This file is for storing the credentials for third party services such\n    | as Mailgun, Postmark, AWS and more. This file provides the de facto\n    | location for this type of information, allowing packages to have\n    | a conventional file to locate the various service credentials.\n    |\n    */\n\n    'mailgun' => [\n        'domain'   => env('MAILGUN_DOMAIN'),\n        'secret'   => env('MAILGUN_SECRET'),\n        'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),\n    ],\n    'postmark' => [\n        'token' => env('POSTMARK_TOKEN'),\n    ],\n\n    'ses' => [\n        'key' => env('AWS_ACCESS_KEY_ID'),\n        'secret' => env('AWS_SECRET_ACCESS_KEY'),\n        'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),\n    ],\n\n    'slack' => [\n        'notifications' => [\n            'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),\n            'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),\n        ],\n    ],\n    'sentry' => [\n        'enabled'           => env('SENTRY_IO_ENABLED', 0),\n        'feedback-enabled'  => env('SENTRY_IO_USER_FEEDBACK_ENABLED', 0),\n    ],\n    'facebook' => [\n        'enabled'       => env('FACEBOOK_ENABLED', false),\n        'client_id'     => env('FACEBOOK_KEY'),\n        'client_secret' => env('FACEBOOK_SECRET'),\n        'redirect'      => env('FACEBOOK_REDIRECT_URI'),\n    ],\n    'twitter' => [\n        'enabled'       => env('TWITTER_ENABLED', false),\n        'client_id'     => env('TWITTER_CLIENT_ID'),\n        'client_secret' => env('TWITTER_CLIENT_SECRET'),\n        'redirect'      => env('TWITTER_REDIRECT_URI'),\n    ],\n    'instagram' => [\n        'enabled'       => env('INSTAGRAM_ENABLED', false),\n        'client_id'     => env('INSTAGRAMBASIC_CLIENT_ID'),\n        'client_secret' => env('INSTAGRAMBASIC_CLIENT_SECRET'),\n        'redirect'      => env('INSTAGRAMBASIC_REDIRECT_URI'),\n    ],\n    'github' => [\n        'enabled'       => env('GITHUB_ENABLED', false),\n        'client_id'     => env('GITHUB_KEY'),\n        'client_secret' => env('GITHUB_SECRET'),\n        'redirect'      => env('GITHUB_REDIRECT_URI'),\n    ],\n    'youtube' => [\n        'enabled'       => env('YOUTUBE_ENABLED', false),\n        'client_id'     => env('YOUTUBE_KEY'),\n        'client_secret' => env('YOUTUBE_SECRET'),\n        'redirect'      => env('YOUTUBE_REDIRECT_URI'),\n    ],\n    'google' => [\n        'ga'            => env('GOOGLE_ANALYTICS_ID', null),\n        'gaEnabled'     => env('GOOGLE_ANALYTICS_ENABLED', null),\n        'enabled'       => env('GOOGLE_ENABLED', false),\n        'client_id'     => env('GOOGLE_KEY'),\n        'client_secret' => env('GOOGLE_SECRET'),\n        'redirect'      => env('GOOGLEREDIRECT_URI'),\n    ],\n    'linkedin' => [\n        'enabled'       => env('LINKEDIN_ENABLED', false),\n        'client_id'     => env('LINKEDIN_CLIENT_ID'),\n        'client_secret' => env('LINKEDIN_CLIENT_SECRET'),\n        'redirect'      => env('LINKEDIN_REDIRECT_URI'),\n    ],\n    'twitch' => [\n        'enabled'       => env('TWITCH_ENABLED', false),\n        'client_id'     => env('TWITCH_KEY'),\n        'client_secret' => env('TWITCH_SECRET'),\n        'redirect'      => env('TWITCH_REDIRECT_URI'),\n    ],\n    'microsoft' => [\n        'enabled'       => env('MICROSOFT_ENABLED', false),\n        'client_id'     => env('MICROSOFT_CLIENT_ID'),\n        'client_secret' => env('MICROSOFT_CLIENT_SECRET'),\n        'redirect'      => env('MICROSOFT_REDIRECT_URI'),\n    ],\n    'tiktok' => [\n        'enabled'       => env('TIKTOK_ENABLED', false),\n        'client_id'     => env('TIKTOK_KEY'),\n        'client_secret' => env('TIKTOK_SECRET'),\n        'redirect'      => env('TIKTOK_REDIRECT_URI'),\n    ],\n    'apple' => [\n        'enabled'       => env('APPLE_ENABLED', false),\n        'client_id'     => env('APPLE_CLIENT_ID'),\n        'client_secret' => env('APPLE_CLIENT_SECRET'),\n        'team_id'       => env('APPLE_TEAM_ID'),\n        'key_id'        => env('APPLE_KEY_ID'),\n        'private_key'   => env('APPLE_PRIVATE_KEY'),\n        'redirect'      => env('APPLE_REDIRECT_URI'),\n    ],\n    'zoho' => [\n        'enabled'       => env('ZOHO_ENABLED', false),\n        'client_id'     => env('ZOHO_CLIENT_ID'),\n        'client_secret' => env('ZOHO_CLIENT_SECRET'),\n        'redirect'      => env('ZOHO_REDIRECT_URI'),\n    ],\n    'stackexchange' => [\n        'enabled'       => env('STACKEXCHANGE_ENABLED', false),\n        'client_id'     => env('STACKEXCHANGE_CLIENT_ID'),\n        'client_secret' => env('STACKEXCHANGE_CLIENT_SECRET'),\n        'redirect'      => env('STACKEXCHANGE_REDIRECT_URI'),\n        'key'           => env('STACKEXCHANGE_CLIENT_KEY'),\n        'site'          => env('STACKEXCHANGE_CLIENT_SITE', 'stackoverflow'),\n    ],\n    'gitlab' => [\n        'enabled'       => env('GITLAB_ENABLED', false),\n        'client_id'     => env('GITLAB_CLIENT_ID'),\n        'client_secret' => env('GITLAB_CLIENT_SECRET'),\n        'redirect'      => env('GITLAB_REDIRECT_URI'),\n    ],\n    'reddit' => [\n        'enabled'       => env('REDDIT_ENABLED', false),\n        'client_id'     => env('REDDIT_CLIENT_ID'),\n        'client_secret' => env('REDDIT_CLIENT_SECRET'),\n        'response_type' => env('REDDIT_RESPONSE_TYPE', 'code'),\n        'state'         => env('REDDIT_STATE', 'r@nd0m5tr1n6'),\n        'redirect'      => env('REDDIT_REDIRECT_URI'),\n    ],\n    'snapchat' => [\n        'enabled'       => env('SNAPCHAT_ENABLED', false),\n        'client_id'     => env('SNAPCHAT_CLIENT_ID'),\n        'client_secret' => env('SNAPCHAT_CLIENT_SECRET'),\n        'redirect'      => env('SNAPCHAT_REDIRECT_URI'),\n    ],\n    'meetup' => [\n        'enabled'       => env('MEETUP_ENABLED', false),\n        'client_id'     => env('MEETUP_CLIENT_ID'),\n        'client_secret' => env('MEETUP_CLIENT_SECRET'),\n        'redirect'      => env('MEETUP_REDIRECT_URI'),\n    ],\n    'atlassian' => [\n        'enabled'       => env('ATLASSIAN_ENABLED', false),\n        'client_id'     => env('ATLASSIAN_CLIENT_ID'),\n        'client_secret' => env('ATLASSIAN_CLIENT_SECRET'),\n        'redirect'      => env('ATLASSIAN_REDIRECT_URI'),\n    ],\n\n    // NEW_PROVIDER_PLUG :: Put New Provider HERE\n\n    'trello' => [\n        'enabled'       => env('TRELLO_ENABLED', false),\n        'client_id'     => env('TRELLO_CLIENT_ID'),\n        'client_secret' => env('TRELLO_CLIENT_SECRET'),\n        'redirect'      => env('TRELLO_REDIRECT_URI'),\n    ],\n    'zoom' => [\n        'enabled'       => env('ZOOM_ENABLED', false),\n        'client_id'     => env('ZOOM_CLIENT_ID'),\n        'client_secret' => env('ZOOM_CLIENT_SECRET'),\n        'redirect'      => env('ZOOM_REDIRECT_URI'),\n    ],\n    'mailchimp' => [\n        'enabled'       => env('MAILCHIMP_ENABLED', false),\n        'client_id'     => env('MAILCHIMP_CLIENT_ID'),\n        'client_secret' => env('MAILCHIMP_CLIENT_SECRET'),\n        'redirect'      => env('MAILCHIMP_REDIRECT_URI'),\n    ],\n    'disqus' => [\n        'enabled'       => env('DISQUS_ENABLED', false),\n        'client_id'     => env('DISQUS_CLIENT_ID'),\n        'client_secret' => env('DISQUS_CLIENT_SECRET'),\n        'redirect'      => env('DISQUS_REDIRECT_URI'),\n    ],\n\n    'patreon' => [\n        'enabled'       => env('PATREON_ENABLED', false),\n        'client_id'     => env('PATREON_CLIENT_ID'),\n        'client_secret' => env('PATREON_CLIENT_SECRET'),\n        'redirect'      => env('PATREON_REDIRECT_URI'),\n    ],\n    'paypal' => [\n        'enabled'       => env('PAYPAL_ENABLED', false),\n        'client_id'     => env('PAYPAL_CLIENT_ID'),\n        'client_secret' => env('PAYPAL_CLIENT_SECRET'),\n        'redirect'      => env('PAYPAL_REDIRECT_URI'),\n    ],\n    'stripe' => [\n        'enabled'       => env('STRIPE_ENABLED', false),\n        'client_id'     => env('STRIPE_CLIENT_ID'),\n        'client_secret' => env('STRIPE_CLIENT_SECRET'),\n        'redirect'      => env('STRIPE_REDIRECT_URI'),\n    ],\n    'venmo' => [\n        'enabled'       => env('VENMO_ENABLED', false),\n        'client_id'     => env('VENMO_CLIENT_ID'),\n        'client_secret' => env('VENMO_CLIENT_SECRET'),\n        'redirect'      => env('VENMO_REDIRECT_URI'),\n    ],\n    'soundcloud' => [\n        'enabled'       => env('SOUNDCLOUD_ENABLED', false),\n        'client_id'     => env('SOUNDCLOUD_CLIENT_ID'),\n        'client_secret' => env('SOUNDCLOUD_CLIENT_SECRET'),\n        'redirect'      => env('SOUNDCLOUD_REDIRECT_URI'),\n    ],\n    'spotify' => [\n        'enabled'       => env('SPOTIFY_ENABLED', false),\n        'client_id'     => env('SPOTIFY_CLIENT_ID'),\n        'client_secret' => env('SPOTIFY_CLIENT_SECRET'),\n        'redirect'      => env('SPOTIFY_REDIRECT_URI'),\n    ],\n    'arcgis' => [\n        'enabled'       => env('ARCGIS_ENABLED', false),\n        'client_id'     => env('ARCGIS_CLIENT_ID'),\n        'client_secret' => env('ARCGIS_CLIENT_SECRET'),\n        'redirect'      => env('ARCGIS_REDIRECT_URI'),\n    ],\n    'fitbit' => [\n        'enabled'       => env('FITBIT_ENABLED', false),\n        'client_id'     => env('FITBIT_CLIENT_ID'),\n        'client_secret' => env('FITBIT_CLIENT_SECRET'),\n        'redirect'      => env('FITBIT_REDIRECT_URI'),\n    ],\n    'uber' => [\n        'enabled'       => env('UBER_ENABLED', false),\n        'client_id'     => env('UBER_CLIENT_ID'),\n        'client_secret' => env('UBER_CLIENT_SECRET'),\n        'redirect'      => env('UBER_REDIRECT_URI'),\n    ],\n    'amazon' => [\n        'enabled'       => env('AMAZON_ENABLED', false),\n        'client_id'     => env('AMAZON_SIGNIN_CLIENT_ID'),\n        'client_secret' => env('AMAZON_SIGNIN_SECRET'),\n        'redirect'      => env('AMAZON_SIGNIN_REDIRECT_URI'),\n    ],\n    'keycloak' => [\n        'enabled'       => env('KEYCLOAK_ENABLED', false),\n        'client_id'     => env('KEYCLOAK_CLIENT_ID'),\n        'client_secret' => env('KEYCLOAK_CLIENT_SECRET'),\n        'redirect'      => env('KEYCLOAK_REDIRECT_URI'),\n        'base_url'      => env('KEYCLOAK_BASE_URL'),   // Specify your keycloak server URL here\n        'realms'        => env('KEYCLOAK_REALM'),       // Specify your keycloak realm\n    ],\n];\n"
  },
  {
    "path": "config/session.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Str;\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Session Driver\n    |--------------------------------------------------------------------------\n    |\n    | This option determines the default session driver that is utilized for\n    | incoming requests. Laravel supports a variety of storage options to\n    | persist session data. Database storage is a great default choice.\n    |\n    | Supported: \"file\", \"cookie\", \"database\", \"apc\",\n    |            \"memcached\", \"redis\", \"dynamodb\", \"array\"\n    |\n    */\n\n    'driver' => env('SESSION_DRIVER', 'database'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Lifetime\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the number of minutes that you wish the session\n    | to be allowed to remain idle before it expires. If you want them\n    | to expire immediately when the browser is closed then you may\n    | indicate that via the expire_on_close configuration option.\n    |\n    */\n\n    'lifetime' => env('SESSION_LIFETIME', 120),\n\n    'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Encryption\n    |--------------------------------------------------------------------------\n    |\n    | This option allows you to easily specify that all of your session data\n    | should be encrypted before it's stored. All encryption is performed\n    | automatically by Laravel and you may use the session like normal.\n    |\n    */\n\n    'encrypt' => env('SESSION_ENCRYPT', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session File Location\n    |--------------------------------------------------------------------------\n    |\n    | When utilizing the \"file\" session driver, the session files are placed\n    | on disk. The default storage location is defined here; however, you\n    | are free to provide another location where they should be stored.\n    |\n    */\n\n    'files' => storage_path('framework/sessions'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Database Connection\n    |--------------------------------------------------------------------------\n    |\n    | When using the \"database\" or \"redis\" session drivers, you may specify a\n    | connection that should be used to manage these sessions. This should\n    | correspond to a connection in your database configuration options.\n    |\n    */\n\n    'connection' => env('SESSION_CONNECTION'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Database Table\n    |--------------------------------------------------------------------------\n    |\n    | When using the \"database\" session driver, you may specify the table to\n    | be used to store sessions. Of course, a sensible default is defined\n    | for you; however, you're welcome to change this to another table.\n    |\n    */\n\n    'table' => env('SESSION_TABLE', 'sessions'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cache Store\n    |--------------------------------------------------------------------------\n    |\n    | When using one of the framework's cache driven session backends, you may\n    | define the cache store which should be used to store the session data\n    | between requests. This must match one of your defined cache stores.\n    |\n    | Affects: \"apc\", \"dynamodb\", \"memcached\", \"redis\"\n    |\n    */\n\n    'store' => env('SESSION_STORE'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Sweeping Lottery\n    |--------------------------------------------------------------------------\n    |\n    | Some session drivers must manually sweep their storage location to get\n    | rid of old sessions from storage. Here are the chances that it will\n    | happen on a given request. By default, the odds are 2 out of 100.\n    |\n    */\n\n    'lottery' => [2, 100],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cookie Name\n    |--------------------------------------------------------------------------\n    |\n    | Here you may change the name of the session cookie that is created by\n    | the framework. Typically, you should not need to change this value\n    | since doing so does not grant a meaningful security improvement.\n    |\n    */\n\n    'cookie' => env(\n        'SESSION_COOKIE',\n        Str::slug(env('APP_NAME', 'laravel'), '_').'_session'\n    ),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cookie Path\n    |--------------------------------------------------------------------------\n    |\n    | The session cookie path determines the path for which the cookie will\n    | be regarded as available. Typically, this will be the root path of\n    | your application, but you're free to change this when necessary.\n    |\n    */\n\n    'path' => env('SESSION_PATH', '/'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cookie Domain\n    |--------------------------------------------------------------------------\n    |\n    | This value determines the domain and subdomains the session cookie is\n    | available to. By default, the cookie will be available to the root\n    | domain and all subdomains. Typically, this shouldn't be changed.\n    |\n    */\n\n    'domain' => env('SESSION_DOMAIN'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | HTTPS Only Cookies\n    |--------------------------------------------------------------------------\n    |\n    | By setting this option to true, session cookies will only be sent back\n    | to the server if the browser has a HTTPS connection. This will keep\n    | the cookie from being sent to you when it can't be done securely.\n    |\n    */\n\n    'secure' => env('SESSION_SECURE_COOKIE'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | HTTP Access Only\n    |--------------------------------------------------------------------------\n    |\n    | Setting this value to true will prevent JavaScript from accessing the\n    | value of the cookie and the cookie will only be accessible through\n    | the HTTP protocol. It's unlikely you should disable this option.\n    |\n    */\n\n    'http_only' => env('SESSION_HTTP_ONLY', true),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Same-Site Cookies\n    |--------------------------------------------------------------------------\n    |\n    | This option determines how your cookies behave when cross-site requests\n    | take place, and can be used to mitigate CSRF attacks. By default, we\n    | will set this value to \"lax\" to permit secure cross-site requests.\n    |\n    | See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value\n    |\n    | Supported: \"lax\", \"strict\", \"none\", null\n    |\n    */\n\n    'same_site' => env('SESSION_SAME_SITE', 'lax'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Partitioned Cookies\n    |--------------------------------------------------------------------------\n    |\n    | Setting this value to true will tie the cookie to the top-level site for\n    | a cross-site context. Partitioned cookies are accepted by the browser\n    | when flagged \"secure\" and the Same-Site attribute is set to \"none\".\n    |\n    */\n\n    'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),\n\n];\n"
  },
  {
    "path": "database/.gitignore",
    "content": "*.sqlite*\n"
  },
  {
    "path": "database/factories/CourseFactory.php",
    "content": "<?php\n\nnamespace Database\\Factories;\n\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\App\\Models\\Course>\n */\nclass CourseFactory extends Factory\n{\n    /**\n     * Define the model's default state.\n     *\n     * @return array\n     */\n    public function definition()\n    {\n        $name = $this->faker->sentence(6);\n        return [\n            'title' => $name,\n            'slug' => Str::slug($name),\n            'description' => $this->faker->text(),\n            'price' => $this->faker->randomFloat(2, 0, 199),\n            'thumbnail' => $this->faker->imageUrl($width = 640, $height = 480),\n            'status' => 1,\n            'created_by' => rand(1, 5),\n            'updated_by' => rand(1, 5),\n        ];\n    }\n}\n"
  },
  {
    "path": "database/factories/ExamFactory.php",
    "content": "<?php\n\nnamespace Database\\Factories;\n\nuse App\\Models\\Exam;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\App\\Models\\Exam>\n */\nclass ExamFactory extends Factory\n{\n    /**\n     * Define the model's default state.\n     *\n     * @return array\n     */\n    public function definition()\n    {\n        return [\n            'title' => $this->faker->sentence(6),\n            'description' => $this->faker->paragraph(),\n            'examiner' => rand(1, 10),\n            'status' => rand(1, 4),\n            'price' => 100,\n            'duration' => rand(30, 150),\n            'pass_mark' => 20,\n            'number_of_questions' => 10,\n            'certification' => false,\n        ];\n    }\n}\n"
  },
  {
    "path": "database/factories/LessonFactory.php",
    "content": "<?php\n\nnamespace Database\\Factories;\n\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\App\\Models\\Lesson>\n */\nclass LessonFactory extends Factory\n{\n    /**\n     * Define the model's default state.\n     *\n     * @return array\n     */\n    public function definition()\n    {\n        $name = $this->faker->text(50);\n        return [\n            'title' => $name,\n            'thumbnail' => $this->faker->imageUrl($width = 640, $height = 480),\n            'slug' => Str::slug($name),\n            'short_text' => $this->faker->paragraph(),\n            'full_text' => $this->faker->text(1000),\n            'position' => rand(1, 10),\n            'status' => rand(1, 3),\n            'created_by' => rand(1, 5),\n            'updated_by' => rand(1, 5),\n        ];\n    }\n}\n"
  },
  {
    "path": "database/factories/QuestionFactory.php",
    "content": "<?php\n\nnamespace Database\\Factories;\n\nuse Carbon\\Carbon;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\App\\Models\\Question>\n */\nclass QuestionFactory extends Factory\n{\n    /**\n     * Define the model's default state.\n     *\n     * @return array\n     */\n    public function definition()\n    {\n        $answer = Carbon::now()->isoFormat(\"x\") . '-' . rand(100, 999);\n        return [\n            'created_by' => rand(1, 10),\n            'question' => $this->faker->sentence(10),\n            'options' => [\n                [\n                    'option' => 'true',\n                    'id' => $answer\n                ],\n                [\n                    'option' => 'false',\n                    'id' => Carbon::now()->isoFormat(\"x\") . '-' . rand(100, 999)\n                ],\n                [\n                    'option' => 'both',\n                    'id' => Carbon::now()->isoFormat(\"x\") . '-' . rand(100, 999)\n                ],\n                [\n                    'option' => 'non',\n                    'id' => Carbon::now()->isoFormat(\"x\") . '-' . rand(100, 999)\n                ]\n            ],\n            'answer' => [$answer],\n            'hint' => 'Answer always true',\n            'explanation' => 'you are giving answer form faker generate question',\n            'exam_id' => rand(1, 10),\n        ];\n    }\n}\n"
  },
  {
    "path": "database/factories/SectionFactory.php",
    "content": "<?php\n\nnamespace Database\\Factories;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\App\\Models\\Section>\n */\nclass SectionFactory extends Factory\n{\n    /**\n     * Define the model's default state.\n     *\n     * @return array\n     */\n    public function definition()\n    {\n        $name = ['Intruduction', 'Basic', 'Get into Deep', 'Advance',  'Example', 'Practices'];\n        return [\n            'title' => $name[rand(0, 5)],\n            'description' => $this->faker->paragraph(),\n        ];\n    }\n}\n"
  },
  {
    "path": "database/factories/SubjectFactory.php",
    "content": "<?php\n\nnamespace Database\\Factories;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\App\\Models\\Subject>\n */\nclass SubjectFactory extends Factory\n{\n    /**\n     * Define the model's default state.\n     *\n     * @return array\n     */\n    public function definition()\n    {\n        return [\n            'title' => $this->faker->title,\n            'description' => $this->faker->paragraph()\n        ];\n    }\n}\n"
  },
  {
    "path": "database/factories/TopicFactory.php",
    "content": "<?php\n\nnamespace Database\\Factories;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\App\\Models\\Topic>\n */\nclass TopicFactory extends Factory\n{\n    /**\n     * Define the model's default state.\n     *\n     * @return array\n     */\n    public function definition()\n    {\n        return [\n            'title' => $this->faker->unique()->words(rand(2, 4), true),\n            'description' => $this->faker->paragraph(),\n        ];\n    }\n}\n"
  },
  {
    "path": "database/factories/UserFactory.php",
    "content": "<?php\n\nnamespace Database\\Factories;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\nuse Illuminate\\Support\\Facades\\Hash;\nuse Illuminate\\Support\\Str;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\App\\Models\\User>\n */\nclass UserFactory extends Factory\n{\n    /**\n     * The current password being used by the factory.\n     */\n    protected static ?string $password;\n\n    /**\n     * Define the model's default state.\n     *\n     * @return array<string, mixed>\n     */\n    public function definition(): array\n    {\n        return [\n            'firstname'      => $this->faker->firstName,\n            'lastname'       => $this->faker->lastName,\n            'avatar'         => 'http://lorempixel.com/80/60/',\n            'name'           => $this->faker->unique()->userName,\n            'email'          => $this->faker->unique()->safeEmail,\n            'email_verified_at' => now(),\n            'password'       => static::$password ??= Hash::make('password'),\n            'ip'             => $this->faker->ipv6,\n            'remember_token' => Str::random(10),\n        ];\n    }\n\n    /**\n     * Indicate that the model's email address should be unverified.\n     */\n    public function unverified(): static\n    {\n        return $this->state(fn (array $attributes) => [\n            'email_verified_at' => null,\n        ]);\n    }\n\n    public function banned(): static\n    {\n        return $this->state(fn(array $attributes) => [\n            'deleted_at' => now()\n        ]);\n    }\n}\n"
  },
  {
    "path": "database/migrations/0001_01_01_000000_create_users_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up(): void\n    {\n        Schema::create('users', function (Blueprint $table) {\n            $table->id();\n            $table->string('name');\n            $table->string('firstname')->nullable();\n            $table->string('lastname')->nullable();\n            $table->string('email')->unique();\n            $table->string('avatar')->nullable();\n            $table->string('password');\n            $table->timestamp('email_verified_at')->nullable();\n            $table->timestamp('last_loged_in')->useCurrent();\n            $table->ipAddress('ip')->nullable();\n            $table->rememberToken();\n            $table->timestamps();\n            $table->softDeletes();\n        });\n\n        Schema::create('password_reset_tokens', function (Blueprint $table) {\n            $table->string('email')->primary();\n            $table->string('token');\n            $table->timestamp('created_at')->nullable();\n        });\n\n        Schema::create('sessions', function (Blueprint $table) {\n            $table->string('id')->primary();\n            $table->foreignId('user_id')->nullable()->index();\n            $table->string('ip_address', 45)->nullable();\n            $table->text('user_agent')->nullable();\n            $table->longText('payload');\n            $table->integer('last_activity')->index();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down(): void\n    {\n        Schema::dropIfExists('users');\n        Schema::dropIfExists('password_reset_tokens');\n        Schema::dropIfExists('sessions');\n    }\n};\n"
  },
  {
    "path": "database/migrations/0001_01_01_000001_create_cache_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up(): void\n    {\n        Schema::create('cache', function (Blueprint $table) {\n            $table->string('key')->primary();\n            $table->mediumText('value');\n            $table->integer('expiration');\n        });\n\n        Schema::create('cache_locks', function (Blueprint $table) {\n            $table->string('key')->primary();\n            $table->string('owner');\n            $table->integer('expiration');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down(): void\n    {\n        Schema::dropIfExists('cache');\n        Schema::dropIfExists('cache_locks');\n    }\n};\n"
  },
  {
    "path": "database/migrations/0001_01_01_000002_create_jobs_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up(): void\n    {\n        Schema::create('jobs', function (Blueprint $table) {\n            $table->id();\n            $table->string('queue')->index();\n            $table->longText('payload');\n            $table->unsignedTinyInteger('attempts');\n            $table->unsignedInteger('reserved_at')->nullable();\n            $table->unsignedInteger('available_at');\n            $table->unsignedInteger('created_at');\n        });\n\n        Schema::create('job_batches', function (Blueprint $table) {\n            $table->string('id')->primary();\n            $table->string('name');\n            $table->integer('total_jobs');\n            $table->integer('pending_jobs');\n            $table->integer('failed_jobs');\n            $table->longText('failed_job_ids');\n            $table->mediumText('options')->nullable();\n            $table->integer('cancelled_at')->nullable();\n            $table->integer('created_at');\n            $table->integer('finished_at')->nullable();\n        });\n\n        Schema::create('failed_jobs', function (Blueprint $table) {\n            $table->id();\n            $table->string('uuid')->unique();\n            $table->text('connection');\n            $table->text('queue');\n            $table->longText('payload');\n            $table->longText('exception');\n            $table->timestamp('failed_at')->useCurrent();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down(): void\n    {\n        Schema::dropIfExists('jobs');\n        Schema::dropIfExists('job_batches');\n        Schema::dropIfExists('failed_jobs');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_000001_create_personal_access_tokens_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('personal_access_tokens', function (Blueprint $table) {\n            $table->id();\n            $table->morphs('tokenable');\n            $table->string('name');\n            $table->string('token', 64)->unique();\n            $table->text('abilities')->nullable();\n            $table->timestamp('last_used_at')->nullable();\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('personal_access_tokens');\n    }\n};"
  },
  {
    "path": "database/migrations/2024_05_07_054845_create_files_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('files', function (Blueprint $table) {\n            $table->id();\n\n\t\t\t$table->string('name')->index();\n            $table->string('description', 150)->nullable();\n            $table->string('path')->nullable()->index();\n            $table->string('type', 20)->nullable()->index();\n            $table->string('public_path', 255)->nullable();\n            $table->string('extension', 10)->nullable();\n            $table->string('mime', 50)->nullable();\n            $table->bigInteger('file_size')->nullable()->unsigned();\n            $table->string('file_name', 255);\n\n            $table->integer('parent_id')->nullable();\n            $table->string('driver')->nullable();\n            $table->string('driver_data')->nullable();\n            $table->boolean('isdraft')->default(true);\n\n            $table->integer('uploaded_by')->nullable();\n            $table->integer('deleted_by')->nullable();\n            $table->json('meta')->nullable();\n            $table->json('permissions')->nullable();\n\n            $table->timestamps();\n            $table->softDeletes();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('files');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_054954_create_fileables_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('fileables', function (Blueprint $table) {\n            $table->bigInteger('file_id')->unsigned();\n            $table->morphs('fileable');\n\n            $table->foreign('file_id')\n                ->references('id')\n                ->on('files')\n                ->onDelete('cascade');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('fileables');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_092254_create_settings_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up(): void\n    {\n        Schema::create('settings', function (Blueprint $table) {\n            $table->id();\n            $table->morphs('resource');\n            $table->string(\"key\");\n            $table->string(\"value\");\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down(): void\n    {\n        Schema::dropIfExists('settings');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_112940_create_permission_tables.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up(): void\n    {\n        $teams = config('permission.teams');\n        $tableNames = config('permission.table_names');\n        $columnNames = config('permission.column_names');\n        $pivotRole = $columnNames['role_pivot_key'] ?? 'role_id';\n        $pivotPermission = $columnNames['permission_pivot_key'] ?? 'permission_id';\n\n        if (empty($tableNames)) {\n            throw new \\Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.');\n        }\n        if ($teams && empty($columnNames['team_foreign_key'] ?? null)) {\n            throw new \\Exception('Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.');\n        }\n\n        Schema::create($tableNames['permissions'], function (Blueprint $table) {\n            $table->bigIncrements('id'); // permission id\n            $table->string('name');       // For MySQL 8.0 use string('name', 125);\n            $table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);\n            $table->timestamps();\n\n            $table->unique(['name', 'guard_name']);\n        });\n\n        Schema::create($tableNames['roles'], function (Blueprint $table) use ($teams, $columnNames) {\n            $table->bigIncrements('id'); // role id\n            if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing\n                $table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();\n                $table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');\n            }\n            $table->string('name');       // For MySQL 8.0 use string('name', 125);\n            $table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);\n            $table->timestamps();\n            if ($teams || config('permission.testing')) {\n                $table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);\n            } else {\n                $table->unique(['name', 'guard_name']);\n            }\n        });\n\n        Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) {\n            $table->unsignedBigInteger($pivotPermission);\n\n            $table->string('model_type');\n            $table->unsignedBigInteger($columnNames['model_morph_key']);\n            $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');\n\n            $table->foreign($pivotPermission)\n                ->references('id') // permission id\n                ->on($tableNames['permissions'])\n                ->onDelete('cascade');\n            if ($teams) {\n                $table->unsignedBigInteger($columnNames['team_foreign_key']);\n                $table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');\n\n                $table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],\n                    'model_has_permissions_permission_model_type_primary');\n            } else {\n                $table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],\n                    'model_has_permissions_permission_model_type_primary');\n            }\n\n        });\n\n        Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {\n            $table->unsignedBigInteger($pivotRole);\n\n            $table->string('model_type');\n            $table->unsignedBigInteger($columnNames['model_morph_key']);\n            $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');\n\n            $table->foreign($pivotRole)\n                ->references('id') // role id\n                ->on($tableNames['roles'])\n                ->onDelete('cascade');\n            if ($teams) {\n                $table->unsignedBigInteger($columnNames['team_foreign_key']);\n                $table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');\n\n                $table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],\n                    'model_has_roles_role_model_type_primary');\n            } else {\n                $table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],\n                    'model_has_roles_role_model_type_primary');\n            }\n        });\n\n        Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) {\n            $table->unsignedBigInteger($pivotPermission);\n            $table->unsignedBigInteger($pivotRole);\n\n            $table->foreign($pivotPermission)\n                ->references('id') // permission id\n                ->on($tableNames['permissions'])\n                ->onDelete('cascade');\n\n            $table->foreign($pivotRole)\n                ->references('id') // role id\n                ->on($tableNames['roles'])\n                ->onDelete('cascade');\n\n            $table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary');\n        });\n\n        app('cache')\n            ->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)\n            ->forget(config('permission.cache.key'));\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down(): void\n    {\n        $tableNames = config('permission.table_names');\n\n        if (empty($tableNames)) {\n            throw new \\Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');\n        }\n\n        Schema::drop($tableNames['role_has_permissions']);\n        Schema::drop($tableNames['model_has_roles']);\n        Schema::drop($tableNames['model_has_permissions']);\n        Schema::drop($tableNames['roles']);\n        Schema::drop($tableNames['permissions']);\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_142204_create_sections_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('sections', function (Blueprint $table) {\n            $table->id();\n            $table->string('title');\n            $table->text('description');\n            $table->unsignedBigInteger('course_id')->index();\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('sections');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_145026_create_subjects_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('subjects', function (Blueprint $table) {\n            $table->id();\n            $table->string('title');\n            $table->string('slug');\n            $table->text('description')->nullable();\n            $table->bigInteger('parent')->default(0);\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('subjects');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_152004_create_sectionables_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('sectionables', function (Blueprint $table) {\n            $table->id();\n            $table->bigInteger('section_id');\n            $table->morphs('sectionable');\n            $table->unsignedTinyInteger('order')->default(0);\n            $table->bigInteger('course_id');\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('sectionables');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_153027_create_exams_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('exams', function (Blueprint $table) {\n            $table->id();\n            $table->bigInteger('examiner')->unsigned();\n            $table->string('title');\n            $table->text(\"description\")->nullable();\n            $table->unsignedTinyInteger('status')->default(1)->index()->comment(\"1=>free, 2=>course, 3=>course & paid, 4=>paid\");\n            $table->integer(\"price\")->nullable();\n            $table->unsignedTinyInteger('duration')->default(0);\n            $table->unsignedTinyInteger('pass_mark')->default(0);\n            $table->unsignedTinyInteger('number_of_questions')->default(0);\n            $table->boolean('random_questions')->default(true);\n            $table->boolean('certification')->default(false);\n            $table->unsignedTinyInteger(\"difficulty\")->default(1);\n            $table->json('meta')->nullable();\n            $table->timestamps();\n\n            $table->softDeletes()->index();\n\n\n            $table->foreign('examiner')->references('id')->on('users')->onDelete('cascade');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('exams');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_153507_create_questions_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('questions', function (Blueprint $table) {\n            $table->id();\n            $table->bigInteger('created_by')->unsigned();\n            $table->tinyInteger( 'qtype' )->default( 0 )->comment( '0: Objective; 1: True/False;');\n            $table->string(\"question\");\n            $table->json(\"options\");\n            $table->json(\"answers\");\n            $table->string(\"hint\")->nullable();\n            $table->integer(\"mark\")->default(1);\n            $table->integer(\"nmark\")->default(0);\n            $table->string(\"explanation\")->nullable();\n            $table->bigInteger('exam_id')->unsigned()->index();\n\n            $table->timestamps();\n            $table->softDeletes()->index();\n\n            $table->foreign('created_by')->references('id')->on('users')->onDelete('cascade');\n            $table->foreign('exam_id')->references('id')->on('exams')->onDelete('cascade');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('questions');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_170835_create_topics_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('topics', function (Blueprint $table) {\n            $table->id();\n            $table->string(\"title\");\n            $table->text(\"description\")->nullable();\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('topics');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_180360_create_topicables_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('topicables', function (Blueprint $table) {\n            $table->bigInteger('topic_id')->unsigned();\n            $table->morphs('topicable');\n\n            \n            $table->foreign('topic_id')\n                    ->references('id')->on('topics')\n                    ->onDelete('cascade');\n            \n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('topicables');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_190045_create_results_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('results', function (Blueprint $table) {\n            $table->id();\n            $table->bigInteger('examinee');\n            $table->bigInteger('exam_id');\n            $table->json('answers');\n            $table->float('obtain_mark');\n            $table->boolean('is_pass')->default(false);\n            $table->float('time_taken');\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('results');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_191956_create_courses_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('courses', function (Blueprint $table) {\n            $table->id();\n            $table->string('title');\n            $table->string('subtitle')->nullable();\n            $table->string('slug')->nullable();\n            $table->text('description')->nullable();\n            $table->text('features')->nullable();\n            $table->text('requirements')->nullable();\n            $table->decimal('price', 15, 2)->nullable();\n            $table->integer('discount')->nullable();\n            $table->string('thumbnail')->nullable();\n            $table->date('start_date')->nullable();\n            \n            $table->tinyInteger('certified')->default(1);\n            $table->tinyInteger('status')->default(0);\n\n            $table->bigInteger('created_by')->unsigned();\n            $table->bigInteger('updated_by')->unsigned();\n            \n            $table->timestamps();\n            $table->softDeletes();\n\n            $table->index(['deleted_at']);\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('courses');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_193251_create_lessons_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('lessons', function (Blueprint $table) {\n                $table->id();\n                $table->string('title')->nullable();\n                $table->string('slug')->nullable();\n                $table->string('thumbnail')->nullable();\n                $table->unsignedTinyInteger('type')->default(1)->comment(\"1=>text, 2=> video, 3=>audio, 4=> pdf \");\n                $table->json('object')->nullable();\n                $table->text('short_text')->nullable();\n                $table->text('full_text')->nullable();\n                $table->unsignedTinyInteger('position')->default(1);\n                $table->unsignedTinyInteger('status')->default(1)->comment(\"1=>free, 2=>subscriber, 3=>paid\");\n                \n                $table->timestamps();\n                $table->softDeletes();\n\n                $table->bigInteger('created_by')->unsigned();\n                $table->bigInteger('updated_by')->unsigned();\n                \n                $table->index(['deleted_at']);\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('lessons');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_195152_create_subjectables_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('subjectables', function( Blueprint $table ){\n            $table->bigInteger('subject_id')->unsigned();\n            $table->morphs('subjectables');\n\n            \n            $table->foreign('subject_id')\n                    ->references('id')->on('subjects')\n                    ->onDelete('cascade');\n\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('subjectables');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_200921_create_course_students_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('course_students', function (Blueprint $table) {\n            $table->bigInteger('course_id')->unsigned();\n            $table->foreign('course_id')->references('id')->on('courses')->onDelete('cascade');\n            $table->bigInteger('user_id')->unsigned();\n            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');\n            $table->integer('rating')->unsigned()->default(0);\n            $table->integer('progress')->unsigned()->default(0);\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('course_students');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_201001_create_course_teachers_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('course_teachers', function (Blueprint $table) {\n            $table->bigInteger('course_id')->unsigned();\n            $table->foreign('course_id')->references('id')->on('courses')->onDelete('cascade');\n            $table->bigInteger('user_id')->unsigned();\n            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('course_teachers');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_05_07_203101_create_lesson_student_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('lesson_student', function (Blueprint $table) {\n            $table->bigInteger('lesson_id')->unsigned();\n            $table->foreign('lesson_id')->references('id')->on('lessons')->onDelete('cascade');\n            $table->bigInteger('user_id')->unsigned();\n            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');\n            $table->integer('status')->unsigned()->default(0);\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('lesson_student');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_07_23_104822_store_last_learning.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     */\n    public function up(): void\n    {\n        Schema::table('course_students', function(Blueprint $table) {\n            $table->json('last_lesson')->nullable()->default(null);\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     */\n    public function down(): void\n    {\n        //\n    }\n};\n"
  },
  {
    "path": "database/migrations/2024_08_13_073632_create_socialite_providers_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nreturn new class extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('socialite_providers', function (Blueprint $table) {\n            $table->id();\n            $table->unsignedBigInteger('user_id')->index();\n            $table->string('provider');\n            $table->string('provider_user_id')->index();\n            $table->longText('access_token')->nullable();\n            $table->longText('refresh_token')->nullable();\n            $table->longText('avatar')->nullable();\n            $table->timestamps();\n\n            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('socialite_providers');\n    }\n};\n"
  },
  {
    "path": "database/migrations/2026_04_25_000001_add_icon_and_image_to_subjects_table.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Schema;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nreturn new class extends Migration\n{\n    public function up(): void\n    {\n        Schema::table('subjects', function (Blueprint $table) {\n            $table->string('icon')->nullable()->after('description');\n            $table->string('image')->nullable()->after('icon');\n        });\n    }\n\n    public function down(): void\n    {\n        Schema::table('subjects', function (Blueprint $table) {\n            $table->dropColumn(['icon', 'image']);\n        });\n    }\n};\n"
  },
  {
    "path": "database/seeders/CourseSeed.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse App\\Models\\Exam;\nuse App\\Models\\Course;\nuse App\\Models\\Lesson;\nuse App\\Models\\Section;\nuse App\\Models\\Question;\nuse App\\Models\\ExamSession;\nuse App\\Models\\ExamSessionable;\nuse Illuminate\\Database\\Seeder;\n\nclass CourseSeed extends Seeder\n{\n    /**\n     * Run the database seeds.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        $count = (int) $this->command->ask('How Course seed do you need ?', 10);\n        Course::factory()->count($count)->create()->each(function ($course) {\n            $course->teachers()->sync(rand(1, 3));\n            $course->teachers()->sync(rand(1, 10));\n\n            $course->students()->sync(rand(1, 3));\n            $course->students()->sync(rand(1, 10));\n\n            $course->subjects()->attach(rand(1, 100));\n            $course->topics()->attach([rand(1, 5), rand(1, 10), rand(1, 10), rand(1, 10)]);\n            $sessions = Section::factory()->count(5)->create(['course_id' => $course->id]);\n\n            Lesson::factory()->count(15)->create()->each(function ($lesson) use ($sessions, $course) {\n                $course->lessons()->save($lesson, [\n                    'section_id' => $sessions->random()->id,\n                    'sectionable_type' => Lesson::class,\n                    'order' => rand(1, 15)\n                ]);\n            });\n\n            Exam::factory()->count(rand(3, 8))->create()->each(function ($exam) use ($sessions, $course) {\n\n                $exam->topics()->attach([rand(1, 5), rand(1, 10), rand(1, 10), rand(1, 10)]);\n                $exam->subjects()->attach(rand(1, 100));\n                Question::factory()->count(20)->create(['exam_id' => $exam->id]);\n\n                $course->exams()->save($exam, [\n                    'section_id' => $sessions->random()->id,\n                    'sectionable_type' => Exam::class,\n                    'order' => rand(15, 30)\n                ]);\n            });\n        });\n    }\n}\n"
  },
  {
    "path": "database/seeders/DatabaseSeeder.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\n// use Illuminate\\Database\\Console\\Seeds\\WithoutModelEvents;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass DatabaseSeeder extends Seeder\n{\n    /**\n     * Seed the application's database.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        // Disable foreign key checks for MySQL, skip for PostgreSQL\n        $driver = DB::connection()->getDriverName();\n        if ($driver === 'mysql') {\n            DB::statement('SET FOREIGN_KEY_CHECKS = 0');\n        }\n        \n        $this->call([\n            UserSeed::class,\n            RoleSeed::class,\n            SubjectSeed::class,\n            TopicSeed::class,\n            CourseSeed::class\n        ]);\n        \n        // Re-enable foreign key checks for MySQL\n        if ($driver === 'mysql') {\n            DB::statement('SET FOREIGN_KEY_CHECKS = 1');\n        }\n    }\n}\n"
  },
  {
    "path": "database/seeders/RoleSeed.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse App\\Models\\User;\nuse Illuminate\\Database\\Seeder;\nuse Illuminate\\Support\\Facades\\DB;\nuse Spatie\\Permission\\Models\\Role;\nuse Spatie\\Permission\\Models\\Permission;\n\nclass RoleSeed extends Seeder\n{\n    /**\n     * Run the database seeds.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        Role::create(['name' => 'superadmin']);\n        Role::create(['name' => 'admin']);\n        Role::create(['name' => 'instructor']);\n\n\n\n        Permission::create(['name' => 'course.create ']);\n        Permission::create(['name' => 'course.edit']);\n        Permission::create(['name' => 'course.delete']);\n\n        Permission::create(['name' => 'exam.create ']);\n        Permission::create(['name' => 'exam.edit']);\n        Permission::create(['name' => 'exam.delete']);\n\n        Permission::create(['name' => 'question.create ']);\n        Permission::create(['name' => 'question.edit']);\n        Permission::create(['name' => 'question.delete']);\n\n        Permission::create(['name' => 'lesson.create ']);\n        Permission::create(['name' => 'lesson.edit']);\n        Permission::create(['name' => 'lesson.delete']);\n\n        Permission::create(['name' => 'topic.create ']);\n        Permission::create(['name' => 'topic.edit']);\n        Permission::create(['name' => 'topic.delete']);\n\n        Permission::create(['name' => 'session.create ']);\n        Permission::create(['name' => 'session.edit']);\n        Permission::create(['name' => 'session.delete']);\n\n        Permission::create(['name' => 'subject.create ']);\n        Permission::create(['name' => 'subject.edit']);\n        Permission::create(['name' => 'subject.delete']);\n\n        Permission::create(['name' => 'file.view.all']);\n        Permission::create(['name' => 'file.make.private']);\n        Permission::create(['name' => 'file.view.private']);\n\n        DB::table('model_has_roles')->insert([\n            'role_id'             => '1',\n            'model_id'             => '1',\n            'model_type'        => User::class\n\n        ]);\n    }\n}\n"
  },
  {
    "path": "database/seeders/SubjectSeed.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse App\\Models\\Subject;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Database\\Seeder;\n\nclass SubjectSeed extends Seeder\n{\n    /** Heroicon component names assigned to each parent category. */\n    private array $categoryIcons = [\n        'Development'          => 'CodeBracketIcon',\n        'Business'             => 'BriefcaseIcon',\n        'Finance & Accounting' => 'BanknotesIcon',\n        'IT & Software'        => 'ComputerDesktopIcon',\n        'Office Productivity'  => 'DocumentTextIcon',\n        'Personal Development' => 'LightBulbIcon',\n        'Design'               => 'PaintBrushIcon',\n        'Marketing'            => 'MegaphoneIcon',\n        'Lifestyle'            => 'SparklesIcon',\n        'Photography'          => 'CameraIcon',\n        'Health & Fitness'     => 'HeartIcon',\n        'Music'                => 'MusicalNoteIcon',\n        'Teaching & Academics' => 'AcademicCapIcon',\n    ];\n\n    /** Icon pool used when picking randomly for child subjects. */\n    private array $iconPool = [\n        'BookOpenIcon', 'BeakerIcon', 'ChartBarIcon', 'CpuChipIcon',\n        'GlobeAltIcon', 'RocketLaunchIcon', 'StarIcon', 'TrophyIcon',\n        'PuzzlePieceIcon', 'FireIcon', 'WrenchScrewdriverIcon', 'KeyIcon',\n        'SignalIcon', 'CircleStackIcon', 'CommandLineIcon', 'ShieldCheckIcon',\n        'CloudIcon', 'TableCellsIcon', 'CalculatorIcon', 'FilmIcon',\n        'LanguageIcon', 'ChatBubbleLeftRightIcon', 'CursorArrowRaysIcon',\n        'SwatchIcon', 'MicrophoneIcon', 'TicketIcon', 'FlagIcon', 'TagIcon',\n    ];\n\n    private function generateImage(): string\n    {\n        $dir = storage_path('app/public/subjects');\n        if (! is_dir($dir)) {\n            mkdir($dir, 0755, true);\n        }\n\n        // Generate a simple colored SVG — no HTTP request, instant\n        $colors  = ['4f46e5', '0891b2', '059669', 'd97706', 'dc2626', '7c3aed', 'db2777', '0284c7'];\n        $bg      = $colors[array_rand($colors)];\n        $filename = Str::uuid() . '.svg';\n        $svg = <<<SVG\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"400\" height=\"300\" viewBox=\"0 0 400 300\">\n  <rect width=\"400\" height=\"300\" fill=\"#{$bg}\" opacity=\"0.15\"/>\n  <rect width=\"400\" height=\"300\" fill=\"none\" stroke=\"#{$bg}\" stroke-width=\"2\" opacity=\"0.4\"/>\n</svg>\nSVG;\n        file_put_contents(\"{$dir}/{$filename}\", $svg);\n\n        return \"subjects/{$filename}\";\n    }\n\n    /**\n     * Run the database seeds.\n     */\n    public function run(): void\n    {\n        // Truncate and reset primary key sequence (PostgreSQL)\n        DB::statement('TRUNCATE TABLE subjects RESTART IDENTITY CASCADE');\n\n        // Also clear old generated images\n        Storage::disk('public')->deleteDirectory('subjects');\n\n        $subjects = [\n            'Development' => [\n                \"Web Development\",\n                \"Data Science\",\n                \"Mobile Apps\",\n                \"Programming Languages\",\n                \"Game Development\",\n                \"Databases\",\n                \"Software Testing\",\n                \"Software Engineering\",\n                \"Development Tools\",\n                \"E-Commerce\",\n            ],\n            \"Business\" => [\n                \"Finance\",\n                \"Entrepreneurship\",\n                \"Communications\",\n                \"Management\",\n                \"Sales\",\n                \"Strategy\",\n                \"Operations\",\n                \"Project Management\",\n                \"Business Law\",\n                \"Data & Analytics\",\n                \"Home Business\",\n                \"Human Resources\",\n                \"Industry\",\n                \"Media\",\n                \"Real Estate\",\n            ],\n            \"Finance & Accounting\" => [\n                \"Accounting & Bookkeeping\",\n                \"Compliance\",\n                \"Cryptocurrency & Blockchain\",\n                \"Economics\",\n                \"Finance\",\n                \"Finance Cert & Exam Prep\",\n                \"Financial Modeling & Analysis\",\n                \"Investing & Trading\",\n                \"Money Management Tools\",\n                \"Taxes\",\n                \"Other Finance & Economics\",\n            ],\n            \"IT & Software\" => [\n                \"IT Certification\",\n                \"Network & Security\",\n                \"Hardware\",\n                \"Operating Systems\",\n                \"Other\",\n            ],\n            \"Office Productivity\" => [\n                \"Microsoft\",\n                \"Apple\",\n                \"Google\",\n                \"SAP\",\n                \"Oracle\",\n                \"Other\",\n            ],\n            \"Personal Development\" => [\n                \"Personal Transformation\",\n                \"Productivity\",\n                \"Leadership\",\n                \"Personal Finance\",\n                \"Career Development\",\n                \"Parenting & Relationships\",\n                \"Happiness\",\n                \"Religion & Spirituality\",\n                \"Personal Brand Building\",\n                \"Creativity\",\n                \"Influence\",\n                \"Self Esteem\",\n                \"Stress Management\",\n                \"Memory & Study Skills\",\n                \"Motivation\",\n                \"Other\",\n            ],\n            \"Design\" => [\n                \"Web Design\",\n                \"Graphic Design\",\n                \"Design Tools\",\n                \"User Experience\",\n                \"Game Design\",\n                \"Design Thinking\",\n                \"3D & Animation\",\n                \"Fashion\",\n                \"Architectural Design\",\n                \"Interior Design\",\n                \"Other\",\n            ],\n            \"Marketing\" => [\n                \"Digital Marketing\",\n                \"Search Engine Optimization\",\n                \"Social Media Marketing\",\n                \"Branding\",\n                \"Marketing Fundamentals\",\n                \"Analytics & Automation\",\n                \"Public Relations\",\n                \"Advertising\",\n                \"Video & Mobile Marketing\",\n                \"Content Marketing\",\n                \"Growth Hacking\",\n                \"Affiliate Marketing\",\n                \"Product Marketing\",\n                \"Other\",\n            ],\n            \"Lifestyle\" => [\n                \"Arts & Crafts\",\n                \"Food & Beverage\",\n                \"Beauty & Makeup\",\n                \"Travel\",\n                \"Gaming\",\n                \"Home Improvement\",\n                \"Pet Care & Training\",\n                \"Other\",\n            ],\n            \"Photography\" => [\n                \"Digital Photography\",\n                \"Photography Fundamentals\",\n                \"Portraits\",\n                \"Photography Tools\",\n                \"Commercial Photography\",\n                \"Video Design\",\n                \"Other\",\n            ],\n            \"Health & Fitness\" => [\n                \"Fitness\",\n                \"General Health\",\n                \"Sports\",\n                \"Nutrition\",\n                \"Yoga\",\n                \"Mental Health\",\n                \"Dieting\",\n                \"Self Defense\",\n                \"Safety & First Aid\",\n                \"Dance\",\n                \"Meditation\",\n                \"Other\",\n            ],\n            \"Music\" => [\n                \"Instruments\",\n                \"Production\",\n                \"Music Fundamentals\",\n                \"Vocal\",\n                \"Music Techniques\",\n                \"Music Software\",\n                \"Other\",\n            ],\n            \"Teaching & Academics\" => [\n                \"Engineering\",\n                \"Humanities\",\n                \"Math\",\n                \"Science\",\n                \"Online Education\",\n                \"Social Science\",\n                \"Language\",\n                \"Teacher Training\",\n                \"Test Prep\",\n                \"Other Teaching & Academics\",\n            ],\n\n        ];\n\n\n        foreach ($subjects as $key => $value) {\n            $p = Subject::create([\n                'title' => $key,\n                'slug'  => Str::slug($key),\n                'icon'  => $this->categoryIcons[$key] ?? $this->iconPool[array_rand($this->iconPool)],\n                'image' => $this->generateImage(),\n            ]);\n\n            foreach ($value as $subject) {\n                Subject::create([\n                    'title'  => $subject,\n                    'parent' => $p->id,\n                    'slug'   => Str::slug($subject),\n                    'icon'   => $this->iconPool[array_rand($this->iconPool)],\n                    'image'  => $this->generateImage(),\n                ]);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "database/seeders/TopicSeed.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse Illuminate\\Database\\Seeder;\nuse App\\Models\\Topic;\n\nclass TopicSeed extends Seeder\n{\n    /**\n     * Run the database seeds.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        Topic::factory()->count(50)->create();\n    }\n}\n"
  },
  {
    "path": "database/seeders/UserSeed.php",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse App\\Models\\User;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Database\\Seeder;\n\nclass UserSeed extends Seeder\n{\n    /**\n     * Run the database seeds.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        $items = [\n            [\n                'firstname'      => 'admin',\n                'lastname'       => null,\n                'avatar'         => 'http://lorempixel.com/80/60/',\n                'name'           => 'admin',\n                'email'          => 'admin@admin.com',\n                'password'       => '$2y$10$l4MghrLnKXTRUDlR07XQeesKHRIaAe7WzDf90g751BEf70AwnJ5m.', // password\n                'remember_token' => Str::random(10)\n            ],\n            [\n                'firstname'      => 'Teacher',\n                'lastname'       => null,\n                'avatar'         => 'http://lorempixel.com/80/60/',\n                'name'           => 'teacher',\n                'email'          => 'teacher@admin.com',\n                'password'       => '$2y$10$l4MghrLnKXTRUDlR07XQeesKHRIaAe7WzDf90g751BEf70AwnJ5m.', // password\n                'remember_token' => Str::random(10)\n            ],\n            [\n                'firstname'      => 'Student',\n                'lastname'       => null,\n                'avatar'         => 'http://lorempixel.com/80/60/',\n                'name'           => 'student',\n                'email'          => 'student@admin.com',\n                'password'       => '$2y$10$l4MghrLnKXTRUDlR07XQeesKHRIaAe7WzDf90g751BEf70AwnJ5m.', // password\n                'remember_token' => Str::random(10)\n            ]\n        ];\n\n        foreach ($items as $key => $item) {\n            $user = User::create($item);\n        }\n\n        User::factory()->count(50)->create();\n        User::factory()->unverified()->count(30)->create();\n        User::factory()->banned()->count(20)->create();\n    }\n}\n"
  },
  {
    "path": "docker/nginx/default.conf",
    "content": "server {\n    listen 80;\n    server_name localhost;\n    root /var/www/html/public;\n    index index.php index.html;\n\n    # Client body size\n    client_max_body_size 50M;\n\n    # Logs\n    access_log /var/log/nginx/access.log;\n    error_log /var/log/nginx/error.log;\n\n    # Serve static files directly\n    location ~* \\.(jpg|jpeg|gif|css|png|js|ico|html|svg|woff|woff2|ttf|eot)$ {\n        access_log off;\n        expires max;\n        add_header Cache-Control \"public, immutable\";\n    }\n\n    # Front controller pattern\n    location / {\n        try_files $uri $uri/ /index.php?$query_string;\n    }\n\n    # PHP-FPM configuration\n    location ~ \\.php$ {\n        try_files $uri =404;\n        fastcgi_split_path_info ^(.+\\.php)(/.+)$;\n        fastcgi_pass app:9000;\n        fastcgi_index index.php;\n        include fastcgi_params;\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        fastcgi_param PATH_INFO $fastcgi_path_info;\n        fastcgi_read_timeout 300;\n        fastcgi_buffers 16 16k;\n        fastcgi_buffer_size 32k;\n    }\n\n    # Deny access to hidden files\n    location ~ /\\. {\n        deny all;\n        access_log off;\n        log_not_found off;\n    }\n\n    # Deny access to certain files\n    location ~ /\\.(?!well-known).* {\n        deny all;\n    }\n}\n"
  },
  {
    "path": "docker/php/local.ini",
    "content": "upload_max_filesize=50M\npost_max_size=50M\nmemory_limit=512M\nmax_execution_time=300\nmax_input_time=300\ndate.timezone=UTC\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: '3.8'\n\nservices:\n  # PHP-FPM Service\n  app:\n    build:\n      context: .\n      dockerfile: Dockerfile\n    container_name: examinee-app\n    restart: unless-stopped\n    working_dir: /var/www/html\n    volumes:\n      - ./:/var/www/html\n      - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini\n    networks:\n      - examinee-network\n    depends_on:\n      - db\n      - redis\n    environment:\n      - DB_CONNECTION=pgsql\n      - DB_HOST=db\n      - DB_PORT=5432\n      - DB_DATABASE=examinee_db\n      - DB_USERNAME=examinee_user\n      - DB_PASSWORD=examinee_password\n      - REDIS_HOST=redis\n      - REDIS_PORT=6379\n      - CACHE_DRIVER=redis\n      - SESSION_DRIVER=redis\n      - QUEUE_CONNECTION=redis\n\n  # Nginx Service\n  nginx:\n    image: nginx:alpine\n    container_name: examinee-nginx\n    restart: unless-stopped\n    ports:\n      - \"8000:80\"\n    volumes:\n      - ./:/var/www/html\n      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf\n    networks:\n      - examinee-network\n    depends_on:\n      - app\n\n  # PostgreSQL Service\n  db:\n    image: postgres:16-alpine\n    container_name: examinee-db\n    restart: unless-stopped\n    environment:\n      POSTGRES_DB: examinee_db\n      POSTGRES_USER: examinee_user\n      POSTGRES_PASSWORD: examinee_password\n    ports:\n      - \"5433:5432\"\n    volumes:\n      - dbdata:/var/lib/postgresql/data\n    networks:\n      - examinee-network\n\n  # Redis Service\n  redis:\n    image: redis:alpine\n    container_name: examinee-redis\n    restart: unless-stopped\n    ports:\n      - \"6380:6379\"\n    networks:\n      - examinee-network\n\n  # Queue Worker Service\n  queue:\n    build:\n      context: .\n      dockerfile: Dockerfile\n    container_name: examinee-queue\n    restart: unless-stopped\n    working_dir: /var/www/html\n    volumes:\n      - ./:/var/www/html\n    networks:\n      - examinee-network\n    depends_on:\n      - app\n      - redis\n    environment:\n      - DB_CONNECTION=pgsql\n      - DB_HOST=db\n      - DB_PORT=5432\n      - DB_DATABASE=examinee_db\n      - DB_USERNAME=examinee_user\n      - DB_PASSWORD=examinee_password\n      - REDIS_HOST=redis\n      - REDIS_PORT=6379\n      - QUEUE_CONNECTION=redis\n    command: php artisan queue:work --tries=3 --timeout=90\n\n  # Node Service for building assets\n  node:\n    image: node:20-alpine\n    container_name: examinee-node\n    working_dir: /var/www/html\n    volumes:\n      - ./:/var/www/html\n    networks:\n      - examinee-network\n    command: sh -c \"npm install && npm run build\"\n    profiles:\n      - build\n\nnetworks:\n  examinee-network:\n    driver: bridge\n\nvolumes:\n  dbdata:\n    driver: local\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"private\": true,\n    \"type\": \"module\",\n    \"scripts\": {\n        \"dev\": \"vite\",\n        \"build\": \"vue-tsc && vite build\",\n        \"watch\": \"vue-tsc && vite build --watch\"\n    },\n    \"devDependencies\": {\n        \"@inertiajs/vue3\": \"^1.3.0\",\n        \"@tailwindcss/forms\": \"^0.5.11\",\n        \"@types/lodash\": \"^4.17.24\",\n        \"@vitejs/plugin-vue\": \"^5.2.4\",\n        \"autoprefixer\": \"^10.5.0\",\n        \"axios\": \"^1.15.2\",\n        \"laravel-vite-plugin\": \"^1.3.0\",\n        \"postcss\": \"^8.5.10\",\n        \"tailwindcss\": \"^3.4.19\",\n        \"typescript\": \"^5.9.3\",\n        \"vite\": \"^5.4.21\",\n        \"vue\": \"^3.5.33\",\n        \"vue-tsc\": \"^3.2.7\"\n    },\n    \"dependencies\": {\n        \"@headlessui/tailwindcss\": \"^0.2.2\",\n        \"@headlessui/vue\": \"^1.7.23\",\n        \"@heroicons/vue\": \"^2.2.0\",\n        \"@vueuse/components\": \"^10.11.1\",\n        \"@vueuse/core\": \"^10.11.1\",\n        \"defu\": \"^6.1.7\",\n        \"lodash\": \"^4.18.1\",\n        \"moment\": \"^2.30.1\",\n        \"tailwind-merge\": \"^2.6.1\",\n        \"toasty\": \"^6.0.3\",\n        \"vue-github-button\": \"^3.1.3\",\n        \"vuex-persistedstate\": \"^4.1.0\",\n        \"vuex-shared-mutations\": \"^1.0.2\"\n    }\n}\n"
  },
  {
    "path": "phpstan.neon",
    "content": "includes:\n    - vendor/larastan/larastan/extension.neon\n\nparameters:\n\n    paths:\n        - app/\n\n    # Level 9 is the highest level\n    level: 5\n\n#    ignoreErrors:\n#        - '#PHPDoc tag @var#'\n#\n#    excludePaths:\n#        - ./*/*/FileToBeExcluded.php\n#\n#    checkMissingIterableValueType: false"
  },
  {
    "path": "phpunit.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"vendor/phpunit/phpunit/phpunit.xsd\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n>\n    <testsuites>\n        <testsuite name=\"Unit\">\n            <directory>tests/Unit</directory>\n        </testsuite>\n        <testsuite name=\"Feature\">\n            <directory>tests/Feature</directory>\n        </testsuite>\n    </testsuites>\n    <source>\n        <include>\n            <directory>app</directory>\n        </include>\n    </source>\n    <php>\n        <env name=\"APP_ENV\" value=\"testing\"/>\n        <env name=\"APP_MAINTENANCE_DRIVER\" value=\"file\"/>\n        <env name=\"BCRYPT_ROUNDS\" value=\"4\"/>\n        <env name=\"CACHE_STORE\" value=\"array\"/>\n        <!-- <env name=\"DB_CONNECTION\" value=\"sqlite\"/> -->\n        <!-- <env name=\"DB_DATABASE\" value=\":memory:\"/> -->\n        <env name=\"MAIL_MAILER\" value=\"array\"/>\n        <env name=\"PULSE_ENABLED\" value=\"false\"/>\n        <env name=\"QUEUE_CONNECTION\" value=\"sync\"/>\n        <env name=\"SESSION_DRIVER\" value=\"array\"/>\n        <env name=\"TELESCOPE_ENABLED\" value=\"false\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "postcss.config.js",
    "content": "export default {\n    plugins: {\n        tailwindcss: {},\n        autoprefixer: {},\n    },\n};\n"
  },
  {
    "path": "public/.htaccess",
    "content": "<IfModule mod_rewrite.c>\n    <IfModule mod_negotiation.c>\n        Options -MultiViews -Indexes\n    </IfModule>\n\n    RewriteEngine On\n\n    # Handle Authorization Header\n    RewriteCond %{HTTP:Authorization} .\n    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]\n\n    # Redirect Trailing Slashes If Not A Folder...\n    RewriteCond %{REQUEST_FILENAME} !-d\n    RewriteCond %{REQUEST_URI} (.+)/$\n    RewriteRule ^ %1 [L,R=301]\n\n    # Send Requests To Front Controller...\n    RewriteCond %{REQUEST_FILENAME} !-d\n    RewriteCond %{REQUEST_FILENAME} !-f\n    RewriteRule ^ index.php [L]\n</IfModule>\n"
  },
  {
    "path": "public/index.php",
    "content": "<?php\n\nuse Illuminate\\Http\\Request;\n\ndefine('LARAVEL_START', microtime(true));\n\n// Determine if the application is in maintenance mode...\nif (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {\n    require $maintenance;\n}\n\n// Register the Composer autoloader...\nrequire __DIR__.'/../vendor/autoload.php';\n\n// Bootstrap Laravel and handle the request...\n(require_once __DIR__.'/../bootstrap/app.php')\n    ->handleRequest(Request::capture());\n"
  },
  {
    "path": "public/robots.txt",
    "content": "User-agent: *\nDisallow:\n"
  },
  {
    "path": "resources/css/app.css",
    "content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"
  },
  {
    "path": "resources/js/Components/ApplicationLogo.vue",
    "content": "<template>\n    <svg viewBox=\"0 0 316 316\" xmlns=\"http://www.w3.org/2000/svg\">\n        <path\n            d=\"M305.8 81.125C305.77 80.995 305.69 80.885 305.65 80.755C305.56 80.525 305.49 80.285 305.37 80.075C305.29 79.935 305.17 79.815 305.07 79.685C304.94 79.515 304.83 79.325 304.68 79.175C304.55 79.045 304.39 78.955 304.25 78.845C304.09 78.715 303.95 78.575 303.77 78.475L251.32 48.275C249.97 47.495 248.31 47.495 246.96 48.275L194.51 78.475C194.33 78.575 194.19 78.725 194.03 78.845C193.89 78.955 193.73 79.045 193.6 79.175C193.45 79.325 193.34 79.515 193.21 79.685C193.11 79.815 192.99 79.935 192.91 80.075C192.79 80.285 192.71 80.525 192.63 80.755C192.58 80.875 192.51 80.995 192.48 81.125C192.38 81.495 192.33 81.875 192.33 82.265V139.625L148.62 164.795V52.575C148.62 52.185 148.57 51.805 148.47 51.435C148.44 51.305 148.36 51.195 148.32 51.065C148.23 50.835 148.16 50.595 148.04 50.385C147.96 50.245 147.84 50.125 147.74 49.995C147.61 49.825 147.5 49.635 147.35 49.485C147.22 49.355 147.06 49.265 146.92 49.155C146.76 49.025 146.62 48.885 146.44 48.785L93.99 18.585C92.64 17.805 90.98 17.805 89.63 18.585L37.18 48.785C37 48.885 36.86 49.035 36.7 49.155C36.56 49.265 36.4 49.355 36.27 49.485C36.12 49.635 36.01 49.825 35.88 49.995C35.78 50.125 35.66 50.245 35.58 50.385C35.46 50.595 35.38 50.835 35.3 51.065C35.25 51.185 35.18 51.305 35.15 51.435C35.05 51.805 35 52.185 35 52.575V232.235C35 233.795 35.84 235.245 37.19 236.025L142.1 296.425C142.33 296.555 142.58 296.635 142.82 296.725C142.93 296.765 143.04 296.835 143.16 296.865C143.53 296.965 143.9 297.015 144.28 297.015C144.66 297.015 145.03 296.965 145.4 296.865C145.5 296.835 145.59 296.775 145.69 296.745C145.95 296.655 146.21 296.565 146.45 296.435L251.36 236.035C252.72 235.255 253.55 233.815 253.55 232.245V174.885L303.81 145.945C305.17 145.165 306 143.725 306 142.155V82.265C305.95 81.875 305.89 81.495 305.8 81.125ZM144.2 227.205L100.57 202.515L146.39 176.135L196.66 147.195L240.33 172.335L208.29 190.625L144.2 227.205ZM244.75 114.995V164.795L226.39 154.225L201.03 139.625V89.825L219.39 100.395L244.75 114.995ZM249.12 57.105L292.81 82.265L249.12 107.425L205.43 82.265L249.12 57.105ZM114.49 184.425L96.13 194.995V85.305L121.49 70.705L139.85 60.135V169.815L114.49 184.425ZM91.76 27.425L135.45 52.585L91.76 77.745L48.07 52.585L91.76 27.425ZM43.67 60.135L62.03 70.705L87.39 85.305V202.545V202.555V202.565C87.39 202.735 87.44 202.895 87.46 203.055C87.49 203.265 87.49 203.485 87.55 203.695V203.705C87.6 203.875 87.69 204.035 87.76 204.195C87.84 204.375 87.89 204.575 87.99 204.745C87.99 204.745 87.99 204.755 88 204.755C88.09 204.905 88.22 205.035 88.33 205.175C88.45 205.335 88.55 205.495 88.69 205.635L88.7 205.645C88.82 205.765 88.98 205.855 89.12 205.965C89.28 206.085 89.42 206.225 89.59 206.325C89.6 206.325 89.6 206.325 89.61 206.335C89.62 206.335 89.62 206.345 89.63 206.345L139.87 234.775V285.065L43.67 229.705V60.135ZM244.75 229.705L148.58 285.075V234.775L219.8 194.115L244.75 179.875V229.705ZM297.2 139.625L253.49 164.795V114.995L278.85 100.395L297.21 89.825V139.625H297.2Z\"\n        />\n    </svg>\n</template>\n"
  },
  {
    "path": "resources/js/Components/Breadcrumb.vue",
    "content": "<template>\n    <nav :class=\"ui.wrapper\" aria-label=\"Breadcrumb\">\n        <Link :href=\"route('admin.dashboard')\" :class=\"breadcrumbClass\">\n            <svg\n                class=\"w-3 h-3 me-2.5\"\n                aria-hidden=\"true\"\n                xmlns=\"http://www.w3.org/2000/svg\"\n                fill=\"currentColor\"\n                viewBox=\"0 0 20 20\"\n            >\n                <path\n                    d=\"m19.707 9.293-2-2-7-7a1 1 0 0 0-1.414 0l-7 7-2 2a1 1 0 0 0 1.414 1.414L2 10.414V18a2 2 0 0 0 2 2h3a1 1 0 0 0 1-1v-4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 0 1 1h3a2 2 0 0 0 2-2v-7.586l.293.293a1 1 0 0 0 1.414-1.414Z\"\n                />\n            </svg>\n            Dashboard\n        </Link>\n        <div\n            v-for=\"(item, index) in items\"\n            :key=\"index\"\n            class=\"flex items-center\"\n        >\n            <svg\n                class=\"rtl:rotate-180 block w-3 h-3 mx-1 text-gray-400\"\n                aria-hidden=\"true\"\n                xmlns=\"http://www.w3.org/2000/svg\"\n                fill=\"none\"\n                viewBox=\"0 0 6 10\"\n            >\n                <path\n                    stroke=\"currentColor\"\n                    stroke-linecap=\"round\"\n                    stroke-linejoin=\"round\"\n                    stroke-width=\"2\"\n                    d=\"m1 9 4-4-4-4\"\n                />\n            </svg>\n            <span\n                v-if=\"item.current\"\n                :class=\"breadcrumbClass\"\n            >\n                {{ item.name }}\n            </span>\n            <Link v-else :href=\"item.href\" :class=\"breadcrumbClass\">\n                {{ item.name }}\n            </Link>\n        </div>\n    </nav>\n</template>\n\n<script lang=\"ts\">\nimport { Link } from \"@inertiajs/vue3\";\nimport { LinkType } from \"@/types\";\nimport { PropType } from \"vue\";\nimport { useUI } from \"@/Composables/useUI\";\nimport { computed, toRef, defineComponent } from \"vue\";\nimport { twMerge, twJoin } from \"tailwind-merge\";\n\nconst config = {\n    wrapper: \"flex\",\n    base: \"inline-flex items-center\",\n    size: {\n        \"2xs\": \"text-xs\",\n        xs: \"text-xs\",\n        sm: \"text-sm\",\n        md: \"text-md\",\n        lg: \"text-lg\",\n        xl: \"text-base\",\n    },\n    gap: {\n        \"2xs\": \"ms-1\",\n        xs: \"ms-1\",\n        sm: \"ms-1\",\n        md: \"ms-1\",\n        lg: \"ms-2\",\n        xl: \"ms-3\",\n    },\n    color: \"text-gray-700 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white\",\n    default: {\n        size: \"sm\",\n    },\n};\n\nexport default defineComponent({\n    name: \"Breadcrumbs\",\n    components: {\n        Link,\n    },\n    props: {\n        items: {\n            type: Object as PropType<LinkType[]>,\n            required: true,\n        },\n        size: {\n            type: String,\n            default: () => config.default.size,\n            validator(value: string) {\n                return Object.keys(config.size).includes(value);\n            },\n        },\n        class: {\n            type: [String, Object, Array] as PropType<any>,\n            default: () => \"\",\n        },\n        ui: {\n            type: Object as PropType<Partial<typeof config>>,\n            default: () => ({}),\n        },\n    },\n    setup(props, { slots }) {\n        const { ui, attrs } = useUI(\"breadcrumb\", toRef(props, \"ui\"), config);\n\n        const breadcrumbClass = computed(() => {\n            return twMerge(\n                twJoin(\n                    ui.value.base,\n                    ui.value.size[props.size],\n                    ui.value.gap[props.size],\n                    ui.value.color\n                ),\n                props.class\n            );\n        });\n\n        return {\n            ui,\n            breadcrumbClass,\n        };\n    },\n});\n</script>\n"
  },
  {
    "path": "resources/js/Components/Button.vue",
    "content": "<template>\n    <component\n        :is=\"is\"\n        :disabled=\"disabled || loading\"\n        :class=\"buttonClass\"\n        v-bind=\"{ ...attrs }\"\n    >\n        <slot> </slot>\n    </component>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, toRef } from \"vue\";\nimport type { PropType } from \"vue\";\nimport { twMerge, twJoin } from \"tailwind-merge\";\nimport { useUI } from \"@/Composables/useUI\";\nimport { mergeConfig } from \"@/Composables/utils\";\n\nconst config = {\n    base: \"focus:outline-none focus-visible:outline-0 disabled:cursor-not-allowed disabled:opacity-75 flex-shrink-0\",\n    font: \"font-medium\",\n    rounded: \"rounded-md\",\n    truncate: \"text-left break-all line-clamp-1\",\n    block: \"w-full flex justify-center items-center\",\n    inline: \"inline-flex items-center\",\n    size: {\n        \"2xs\": \"text-xs\",\n        xs: \"text-xs\",\n        sm: \"text-sm\",\n        md: \"text-sm\",\n        lg: \"text-sm\",\n        xl: \"text-base\",\n    },\n    gap: {\n        \"2xs\": \"gap-x-1\",\n        xs: \"gap-x-1.5\",\n        sm: \"gap-x-1.5\",\n        md: \"gap-x-2\",\n        lg: \"gap-x-2.5\",\n        xl: \"gap-x-2.5\",\n    },\n    padding: {\n        \"2xs\": \"px-2 py-1\",\n        xs: \"px-2.5 py-1.5\",\n        sm: \"px-2.5 py-1.5\",\n        md: \"px-3 py-2\",\n        lg: \"px-3.5 py-2.5\",\n        xl: \"px-3.5 py-2.5\",\n    },\n    square: {\n        \"2xs\": \"p-1\",\n        xs: \"p-1.5\",\n        sm: \"p-1.5\",\n        md: \"p-2\",\n        lg: \"p-2.5\",\n        xl: \"p-2.5\",\n    },\n    color: {\n        white: {\n            solid: \"shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-700 text-gray-900 dark:text-white bg-white hover:bg-gray-50 disabled:bg-white dark:bg-gray-900 dark:hover:bg-gray-800/50 dark:disabled:bg-gray-900 focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400\",\n            ghost: \"text-gray-900 dark:text-white hover:bg-white dark:hover:bg-gray-900 focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400\",\n        },\n        gray: {\n            solid: \"shadow-sm ring-1 ring-inset ring-gray-300 dark:ring-gray-700 text-gray-700 dark:text-gray-200 bg-gray-50 hover:bg-gray-100 disabled:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700/50 dark:disabled:bg-gray-800 focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400\",\n            ghost: \"text-gray-700 dark:text-gray-200 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-800 focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400\",\n            link: \"text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 underline-offset-4 hover:underline focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400\",\n        },\n        black: {\n            solid: \"shadow-sm text-white dark:text-gray-900 bg-gray-900 hover:bg-gray-800 disabled:bg-gray-900 dark:bg-white dark:hover:bg-gray-100 dark:disabled:bg-white focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400\",\n            link: \"text-gray-900 dark:text-white underline-offset-4 hover:underline focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400\",\n        },\n        red: {\n            solid: \"shadow-sm text-white  bg-red-900 hover:bg-red-800 disabled:bg-red-900 dark:bg-red dark:hover:bg-red-100 dark:disabled:bg-red focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400\",\n            link: \"text-red-900 dark:text-red underline-offset-4 hover:underline focus-visible:ring-inset focus-visible:ring-2 focus-visible:ring-primary-500 dark:focus-visible:ring-primary-400\",\n        },\n    },\n    variant: {\n        solid: \"shadow-sm text-white dark:text-gray-200 bg-{color}-500 hover:bg-{color}-600 disabled:bg-{color}-500 dark:bg-{color}-400 dark:hover:bg-{color}-500 dark:disabled:bg-{color}-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-{color}-500 dark:focus-visible:outline-{color}-400\",\n        outline:\n            \"ring-1 ring-inset ring-current text-{color}-500 dark:text-{color}-400 hover:bg-{color}-50 disabled:bg-transparent dark:hover:bg-{color}-950 dark:disabled:bg-transparent focus-visible:ring-2 focus-visible:ring-{color}-500 dark:focus-visible:ring-{color}-400\",\n        soft: \"text-{color}-500 dark:text-{color}-400 bg-{color}-50 hover:bg-{color}-100 disabled:bg-{color}-50 dark:bg-{color}-950 dark:hover:bg-{color}-900 dark:disabled:bg-{color}-950 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-{color}-500 dark:focus-visible:ring-{color}-400\",\n        ghost: \"text-{color}-500 dark:text-{color}-400 hover:bg-{color}-50 disabled:bg-transparent dark:hover:bg-{color}-950 dark:disabled:bg-transparent focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-{color}-500 dark:focus-visible:ring-{color}-400\",\n        link: \"text-{color}-500 hover:text-{color}-600 disabled:text-{color}-500 dark:text-{color}-400 dark:hover:text-{color}-500 dark:disabled:text-{color}-400 underline-offset-4 hover:underline focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-{color}-500 dark:focus-visible:ring-{color}-400\",\n    },\n    default: {\n        size: \"sm\",\n        variant: \"solid\",\n        color: \"blue\",\n    },\n};\n\ntype ButtonSize = keyof typeof config.size;\ntype ButtonColor = keyof typeof config.color;\ntype ButtonVariant = keyof typeof config.variant;\n\nexport default defineComponent({\n    inheritAttrs: false,\n    props: {\n        is: {\n            type: String,\n            default: \"button\",\n        },\n        block: {\n            type: Boolean,\n            default: false,\n        },\n        label: {\n            type: String,\n            default: null,\n        },\n        loading: {\n            type: Boolean,\n            default: false,\n        },\n        disabled: {\n            type: Boolean,\n            default: false,\n        },\n        padded: {\n            type: Boolean,\n            default: true,\n        },\n        size: {\n            type: String as PropType<ButtonSize>,\n            default: () => config.default.size,\n            validator(value: string) {\n                return Object.keys(config.size).includes(value);\n            },\n        },\n        color: {\n            type: String as PropType<ButtonColor>,\n            default: () => config.default.color,\n            validator(value: string) {\n                return [...Object.keys(config.color)].includes(value);\n            },\n        },\n        variant: {\n            type: String as PropType<ButtonVariant>,\n            default: () => config.default.variant,\n            validator(value: string) {\n                return [\n                    ...Object.keys(config.variant),\n                    ...Object.values(config.color).flatMap((value) =>\n                        Object.keys(value)\n                    ),\n                ].includes(value);\n            },\n        },\n        square: {\n            type: Boolean,\n            default: false,\n        },\n        truncate: {\n            type: Boolean,\n            default: false,\n        },\n        class: {\n            type: [String, Object, Array] as PropType<any>,\n            default: () => \"\",\n        },\n        ui: {\n            type: Object as PropType<Partial<typeof config>>,\n            default: () => ({}),\n        },\n    },\n    setup(props, { slots }) {\n        const { ui, attrs } = useUI(\"button\", toRef(props, \"ui\"), config);\n\n        const size = props.size;\n\n        const isSquare = computed(\n            () => props.square || (!slots.default && !props.label)\n        );\n\n        const buttonClass = computed(() => {\n            const variant =\n                ui.value.color?.[props.color]?.[props.variant] ||\n                ui.value.variant[props.variant];\n\n            return twMerge(\n                twJoin(\n                    ui.value.base,\n                    ui.value.font,\n                    ui.value.rounded,\n                    ui.value.size[size],\n                    ui.value.gap[size],\n                    props.padded &&\n                        ui.value[isSquare.value ? \"square\" : \"padding\"][size],\n                    variant?.replaceAll(\"{color}\", props.color),\n                    props.block ? ui.value.block : ui.value.inline\n                ),\n                props.class\n            );\n        });\n\n        return {\n            // eslint-disable-next-line vue/no-dupe-keys\n            ui,\n            attrs,\n            isSquare,\n            buttonClass,\n        };\n    },\n});\n</script>\n"
  },
  {
    "path": "resources/js/Components/Card.vue",
    "content": "<template>\n    <component\n      :is=\"$attrs.onSubmit ? 'form' : as\"\n      :class=\"cardClass\"\n      v-bind=\"attrs\"\n    >\n      <div v-if=\"$slots.header\" :class=\"[ui.header.base, ui.header.padding, ui.header.background]\">\n        <slot name=\"header\" />\n      </div>\n      <div v-if=\"$slots.default\" :class=\"[ui.body.base, ui.body.padding, ui.body.background]\">\n        <slot />\n      </div>\n      <div v-if=\"$slots.footer\" :class=\"[ui.footer.base, ui.footer.padding, ui.footer.background]\">\n        <slot name=\"footer\" />\n      </div>\n    </component>\n  </template>\n  \n  <script lang=\"ts\">\n  import { computed, toRef, defineComponent } from 'vue'\n  import type { PropType } from 'vue'\n  import { twMerge, twJoin } from 'tailwind-merge'\n  import { useUI } from '@/Composables/useUI';\n  import type { Strategy } from '@/types';\n\n  \n  const config =  {\n        base: '',\n        background: 'bg-white dark:bg-gray-900',\n        divide: 'divide-y divide-gray-200 dark:divide-gray-800',\n        ring: 'ring-1 ring-gray-200 dark:ring-gray-800',\n        rounded: 'rounded-lg',\n        shadow: 'shadow',\n        body: {\n            base: '',\n            background: '',\n            padding: 'px-4 py-5 sm:p-6'\n        },\n        header: {\n            base: '',\n            background: '',\n            padding: 'px-4 py-5 sm:px-6'\n        },\n        footer: {\n            base: '',\n            background: '',\n            padding: 'px-4 py-4 sm:px-6'\n        }\n    }\n  \n  export default defineComponent({\n    inheritAttrs: false,\n    props: {\n      as: {\n        type: String,\n        default: 'div'\n      },\n      class: {\n        type: [String, Object, Array] as PropType<any>,\n        default: () => ''\n      },\n      ui: {\n        type: Object as PropType<Partial<typeof config> & { strategy?: Strategy }>,\n        default: () => ({})\n      }\n    },\n    setup (props) {\n      const { ui, attrs } = useUI('card', toRef(props, 'ui'), config)\n  \n      const cardClass = computed(() => {\n        return twMerge(twJoin(\n          ui.value.base,\n          ui.value.rounded,\n          ui.value.divide,\n          ui.value.ring,\n          ui.value.shadow,\n          ui.value.background\n        ), props.class)\n      })\n  \n      return {\n        // eslint-disable-next-line vue/no-dupe-keys\n        ui,\n        attrs,\n        cardClass\n      }\n    }\n  })\n  </script>"
  },
  {
    "path": "resources/js/Components/Checkbox.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\nconst emit = defineEmits(['update:checked']);\n\nconst props = defineProps<{\n    checked: boolean;\n    value?: any;\n}>();\n\nconst proxyChecked = computed({\n    get() {\n        return props.checked;\n    },\n\n    set(val) {\n        emit('update:checked', val);\n    },\n});\n</script>\n\n<template>\n    <input\n        type=\"checkbox\"\n        :value=\"value\"\n        v-model=\"proxyChecked\"\n        class=\"rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800\"\n    />\n</template>\n"
  },
  {
    "path": "resources/js/Components/CircleSvg.vue",
    "content": "<template>\n  <svg\n    :width=\"w\"\n    :height=\"h\"\n    :viewBox=\"viewBox\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    :stroke=\"stroke\"\n  >\n    <g fill=\"none\" fill-rule=\"evenodd\">\n      <g transform=\"translate(1 1)\" stroke-width=\"2\">\n        <circle stroke-opacity=\".8\" cx=\"18\" cy=\"18\" r=\"18\" />\n        <path d=\"M36 18c0-9.94-8.06-18-18-18\">\n          <animateTransform\n            attributeName=\"transform\"\n            type=\"rotate\"\n            from=\"0 18 18\"\n            to=\"360 18 18\"\n            dur=\"1s\"\n            repeatCount=\"indefinite\"\n          />\n        </path>\n      </g>\n    </g>\n  </svg>\n</template>\n\n<script>\nexport default {\n  props: {\n    stroke: {\n      type: String,\n      default: '#fff',\n    },\n    w: {\n      type: Number,\n      default: 38,\n    },\n    h: {\n      type: Number,\n      default: 38,\n    },\n  },\n  computed: {\n    viewBox() {\n      return `0 0 ${this.w} ${this.h}`;\n    },\n  },\n};\n</script>\n"
  },
  {
    "path": "resources/js/Components/Datatable/Table.vue",
    "content": "<template>\n    <div :class=\"ui.wrapper\" v-bind=\"attrs\">\n        <table :class=\"[ui.base, ui.divide]\">\n            <slot v-if=\"$slots.caption || caption\" name=\"caption\">\n                <caption :class=\"ui.caption\">\n                    {{ caption }}\n                </caption>\n            </slot>\n\n            <thead :class=\"ui.thead\">\n                <tr :class=\"ui.tr.base\">\n                    <th v-if=\"modelValue\" scope=\"col\" class=\"p-2 text-center\">\n                        <input :value=\"indeterminate || selected.length === rows.length\" :indeterminate=\"indeterminate\" aria-label=\"Select all\" @change=\"onChange\"  type=\"checkbox\" v-bind=\"ui.checkbox\" />\n                    </th>\n\n                    <th v-for=\"(column, index) in columns\" :key=\"index\" scope=\"col\"\n                        :class=\"[ui.th.base, ui.th.padding, ui.th.color, ui.th.font, ui.th.size, column.class]\"\n                        :aria-sort=\"getAriaSort(column)\">\n                        <slot :name=\"`${column.key}-header`\" :column=\"column\" :sort=\"sort\" :on-sort=\"onSort\">\n                            <button v-if=\"column.sortable\" @click=\"onSort(column)\" v-bind=\"{ ...(ui.sortButton || {}), ...sortButton }\">\n                                <span>{{ column[columnAttribute] }}</span>\n                                <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-3 h-3 ms-1.5 opacity-0 group-hover:opacity-100\">\n                                    <path stroke-linecap=\"round\" stroke-linejoin=\"round\" :d=\"getSortIconPath(column)\" />\n                                </svg>\n                            </button>\n                            <span v-else>{{ column[columnAttribute] }}</span>\n                        </slot>\n                    </th>\n                </tr>\n            </thead>\n            <tbody :class=\"ui.tbody\">\n                <tr v-if=\"loadingState && loading && !rows.length\">\n                    <td :colspan=\"columns.length + (modelValue ? 1 : 0)\">\n                        <slot name=\"loading-state\">\n                            <div :class=\"ui.loadingState.wrapper\">\n                                <svg width=\"36\" height=\"36\" :class=\"ui.loadingState.icon\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z\" opacity=\".25\"/><path d=\"M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z\" class=\"spinner_ajPY\"/></svg>\n                                <p :class=\"ui.loadingState.label\">\n                                    {{ loadingState.label }}\n                                </p>\n                            </div>\n                        </slot>\n                    </td>\n                </tr>\n\n                <tr v-else-if=\"emptyState && !rows.length\">\n                    <td :colspan=\"columns.length + (modelValue ? 1 : 0)\">\n                        <slot name=\"empty-state\">\n                            <div :class=\"ui.emptyState.wrapper\">\n                                <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-6\">\n                                    <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M20.25 6.375c0 2.278-3.694 4.125-8.25 4.125S3.75 8.653 3.75 6.375m16.5 0c0-2.278-3.694-4.125-8.25-4.125S3.75 4.097 3.75 6.375m16.5 0v11.25c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125V6.375m16.5 0v3.75m-16.5-3.75v3.75m16.5 0v3.75C20.25 16.153 16.556 18 12 18s-8.25-1.847-8.25-4.125v-3.75m16.5 0c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125\" />\n                                </svg>\n\n                                <p :class=\"ui.emptyState.label\">\n                                    {{ emptyState.label }}\n                                </p>\n                            </div>\n                        </slot>\n                    </td>\n                </tr>\n\n                <template v-else>\n                    <tr v-for=\"(row, index) in rows\" :key=\"index\"\n                        :class=\"[ui.tr.base, isSelected(row) && ui.tr.selected, $attrs.onSelect && ui.tr.active, row?.class]\"\n                        @click=\"() => onSelect(row)\">\n                        <td v-if=\"modelValue\" class=\"p-2 text-center\">\n                            <input v-model=\"selected\" :value=\"row\" aria-label=\"Select row\" @click.stop  type=\"checkbox\" v-bind=\"ui.checkbox\">\n                        </td>\n\n                        <td v-for=\"(column, subIndex) in columns\" :key=\"subIndex\"\n                            :class=\"[ui.td.base, ui.td.padding, ui.td.color, ui.td.font, ui.td.size, row[column.key]?.class]\">\n                            <slot :name=\"`${column.key}-data`\" :column=\"column\" :row=\"row\" :index=\"index\"\n                                :get-row-data=\"(defaultValue: any) => getRowData(row, column.key, defaultValue)\">\n                                {{ getRowData(row, column.key) }}\n                            </slot>\n                        </td>\n                    </tr>\n                </template>\n            </tbody>\n        </table>\n    </div>\n</template>\n<script lang=\"ts\">\nimport { PropType, AriaAttributes, computed, defineComponent, toRaw, toRef } from 'vue';\nimport { useVModel } from '@vueuse/core';\nimport { useUI } from '@/Composables/useUI';\nimport { defu } from 'defu';\nimport { upperFirst } from 'lodash';\nimport { mergeConfig, get } from '@/Composables/utils';\nimport type { Strategy } from '@/types';\n\nlet config = {\n    wrapper: 'relative overflow-x-auto flex-1 my-4',\n    base: 'min-w-full table-fixed',\n    divide: 'divide-y divide-gray-300 dark:divide-gray-700',\n    thead: 'relative',\n    tbody: 'divide-y divide-gray-200 dark:divide-gray-800',\n    caption: 'sr-only',\n    tr: {\n      base: '',\n      selected: 'bg-gray-50 dark:bg-gray-800/50',\n      active: 'hover:bg-gray-50 dark:hover:bg-gray-800/50 cursor-pointer'\n    },\n    th: {\n      base: 'text-left rtl:text-right',\n      padding: 'px-4 py-4',\n      color: 'text-gray-900 dark:text-white',\n      font: 'font-semibold',\n      size: 'text-sm',\n    },\n    td: {\n      base: 'whitespace-nowrap',\n      padding: 'px-4 py-4',\n      color: 'text-gray-500 dark:text-gray-400',\n      font: '',\n      size: 'text-sm'\n    },\n    checkbox: {\n      class: \"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600\",\n    },\n    loadingState: {\n      wrapper: 'flex flex-col items-center justify-center flex-1 px-6 py-14 sm:px-14',\n      label: 'text-sm text-center text-gray-900 dark:text-white',\n      icon: 'w-6 h-6 mx-auto text-gray-400 dark:text-gray-500 mb-4 animate-spin'\n    },\n    emptyState: {\n      wrapper: 'flex flex-col items-center justify-center flex-1 px-6 py-14 sm:px-14',\n      label: 'text-sm text-center text-gray-900 dark:text-white',\n      icon: 'w-6 h-6 mx-auto text-gray-400 dark:text-gray-500 mb-4',\n    },\n    progress: {\n      wrapper: 'absolute inset-x-0 -bottom-[0.5px] p-0',\n      color: 'primary' as const,\n      animation: 'carousel' as const\n    },\n    sortButton: {\n      trailing: true,\n      square: true,\n      color: 'gray' as const,\n      variant: 'ghost' as const,\n      class: 'flex items-center gap-x-1 focus:outline-none'\n    },\n    sortIcon: \"M3 7.5 7.5 3m0 0L12 7.5M7.5 3v13.5m13.5 0L16.5 21m0 0L12 16.5m4.5 4.5V7.5\",\n    sortAscIcon: \"M3 4.5h14.25M3 9h9.75M3 13.5h9.75m4.5-4.5v12m0 0-3.75-3.75M17.25 21 21 17.25\",\n    sortDescIcon: \"M3 4.5h14.25M3 9h9.75M3 13.5h5.25m5.25-.75L17.25 9m0 0L21 12.75M17.25 9v12\"\n  };\n\n config = mergeConfig<typeof config>('merge', config)\n\nfunction defaultComparator<T>(a: T, z: T): boolean {\n    return a === z\n}\n\nfunction defaultSort(a: any, b: any, direction: 'asc' | 'desc') {\n    if (a === b) {\n        return 0\n    }\n\n    if (direction === 'asc') {\n        return a < b ? -1 : 1\n    } else {\n        return a > b ? -1 : 1\n    }\n}\n\ninterface Column {\n    key: string\n    sortable?: boolean\n    sort?: (a: any, b: any, direction: 'asc' | 'desc') => number\n    direction?: 'asc' | 'desc'\n    class?: string\n    [key: string]: any\n}\n\nexport default defineComponent({\n    inheritAttrs: false,\n    props: {\n        modelValue: {\n            type: Array,\n            default: null\n        },\n        by: {\n            type: [String, Function],\n            default: () => defaultComparator\n        },\n        rows: {\n            type: Array as PropType<{ [key: string]: any }[]>,\n            default: () => []\n        },\n        columns: {\n            type: Array as PropType<Column[]>,\n            default: null\n        },\n        columnAttribute: {\n            type: String,\n            default: 'label'\n        },\n        sort: {\n            type: Object as PropType<{ column: string, direction: 'asc' | 'desc' }>,\n            default: () => ({})\n        },\n        sortMode: {\n            type: String as PropType<'manual' | 'auto'>,\n            default: 'auto'\n        },\n        sortButton: {\n            type: Object as PropType<{ icon: string, trailing: string }>,\n            default: () => config.sortButton\n        },\n        sortIcon: {\n            type: String,\n            default: () => config.sortIcon\n        },\n        sortAscIcon: {\n            type: String,\n            default: () => config.sortAscIcon\n        },\n        sortDescIcon: {\n            type: String,\n            default: () => config.sortDescIcon\n        },\n        loading: {\n            type: Boolean,\n            default: false\n        },\n        loadingState: {\n            type: Object as PropType<{ icon: string, label: string }>,\n            default: () => config.loadingState\n        },\n        emptyState: {\n            type: Object as PropType<{ icon: string, label: string }>,\n            default: () => config.emptyState\n        },\n        caption: {\n            type: String,\n            default: null\n        },\n        progress: {\n            type: Object,\n            default: () => null\n        },\n        class: {\n            type: [String, Object, Array] as PropType<any>,\n            default: () => ''\n        },\n        ui: {\n            type: Object as PropType<Partial<typeof config> & { strategy?: Strategy }>,\n            default: () => ({})\n        }\n    },\n    emits: ['update:modelValue', 'update:sort'],\n    setup(props, { emit, attrs: $attrs }) {\n        const { ui, attrs } = useUI('table', toRef(props, 'ui'), config, toRef(props, 'class'))\n\n        const columns = computed(() => props.columns ?? Object.keys(props.rows[0] ?? {}).map((key) => ({ key, label: upperFirst(key), sortable: false, class: undefined, sort: defaultSort })))\n\n        const sort = useVModel(props, 'sort', emit, { passive: true, defaultValue: defu({}, props.sort, { column: 'abc', direction: 'asc' }) }); \n\n        const savedSort = { column: 'bc', direction: 'desc' }\n\n        const rows = computed(() => {\n            if (!sort.value?.column || props.sortMode === 'manual') {\n                return props.rows\n            }\n\n            const { column, direction } = sort.value\n\n            return props.rows.slice().sort((a, b) => {\n                const aValue = get(a, column)\n                const bValue = get(b, column)\n\n                const sort = columns.value.find((col) => col.key === column)?.sort ?? defaultSort\n\n                return sort(aValue, bValue, direction)\n            })\n        })\n\n        const selected = computed({\n            get() {\n                return props.modelValue\n            },\n            set(value) {\n                emit('update:modelValue', value)\n            }\n        })\n\n        const indeterminate = computed(() => selected.value && selected.value.length > 0 && selected.value.length < props.rows.length)\n\n        const emptyState = computed(() => {\n            if (props.emptyState === null) return null\n            return { ...ui.value.emptyState, ...props.emptyState }\n        })\n\n        const loadingState = computed(() => {\n            if (props.loadingState === null) return null\n            return { ...ui.value.loadingState, ...props.loadingState }\n        })\n\n        function compare(a: any, z: any) {\n            if (typeof props.by === 'string') {\n                const property = props.by as unknown as any\n                return a?.[property] === z?.[property]\n            }\n            return props.by(a, z)\n        }\n\n        function isSelected(row: any) {\n            if (!props.modelValue) {\n                return false\n            }\n\n            return selected.value.some((item) => compare(toRaw(item), toRaw(row)))\n        }\n\n        function onSort(column: { key: string, direction?: 'asc' | 'desc' }) {\n            if (sort.value.column === column.key) {\n                const direction = !column.direction || column.direction === 'asc' ? 'desc' : 'asc'\n\n                if (sort.value.direction === direction) {\n                    /** Todo */\n                    // sort.value = defu(savedSort, { column: 'abc', direction: 'asc' })\n                } else {\n                    sort.value = { column: sort.value.column, direction: sort.value.direction === 'asc' ? 'desc' : 'asc' }\n                }\n            } else {\n                sort.value = { column: column.key, direction: column.direction || 'asc' }\n            }\n        }\n\n        function onSelect(row: any) {\n            if (!$attrs.onSelect) {\n                return\n            }\n\n            // @ts-ignore\n            $attrs.onSelect(row)\n        }\n\n        function selectAllRows() {\n            props.rows.forEach((row) => {\n                // If the row is already selected, don't select it again\n                if (isSelected(row)) {\n                    return\n                }\n\n                // @ts-ignore\n                selected.value.push(row)\n            })\n        }\n\n        function onChange (event: Event) {\n            const checked = (event.target as HTMLInputElement).checked\n            if (checked) {\n                selectAllRows()\n            } else {\n                selected.value = []\n            }\n        }\n\n        function getRowData(row: Object, rowKey: string | string[], defaultValue: any = '') {\n            return get(row, rowKey, defaultValue)\n        }\n\n        function getAriaSort(column: Column): AriaAttributes['aria-sort'] {\n            if (!column.sortable) {\n                return undefined\n            }\n\n            if (sort.value.column !== column.key) {\n                return 'none'\n            }\n\n            if (sort.value.direction === 'asc') {\n                return 'ascending'\n            }\n\n            if (sort.value.direction === 'desc') {\n                return 'descending'\n            }\n\n            return undefined\n        }\n\n        function getSortIconPath(column: Column): string {\n\n            if (sort.value.column !== column.key) {\n                return props.sortIcon\n            }\n\n            if (sort.value.direction === 'asc') {\n                return props.sortAscIcon\n            }\n\n            if (sort.value.direction === 'desc') {\n                return props.sortDescIcon\n            }\n\n            return props.sortIcon\n        }\n\n        return {\n            // eslint-disable-next-line vue/no-dupe-keys\n            ui,\n            attrs,\n            // eslint-disable-next-line vue/no-dupe-keys\n            sort,\n            // eslint-disable-next-line vue/no-dupe-keys\n            columns,\n            // eslint-disable-next-line vue/no-dupe-keys\n            rows,\n            selected,\n            indeterminate,\n            // eslint-disable-next-line vue/no-dupe-keys\n            emptyState,\n            // eslint-disable-next-line vue/no-dupe-keys\n            loadingState,\n            isSelected,\n            onSort,\n            onSelect,\n            onChange,\n            getRowData,\n            getAriaSort,\n            getSortIconPath\n        }\n    }\n\n});\n</script>\n<style scoped>\nth svg {\n    opacity: 0;\n}\nth:hover svg,\nth[aria-sort='ascending'] svg,\nth[aria-sort='descending'] svg {\n    opacity: 1;\n}\n.spinner_ajPY{transform-origin:center;animation:spinner_AtaB .75s infinite linear}@keyframes spinner_AtaB{100%{transform:rotate(360deg)}}\n</style>"
  },
  {
    "path": "resources/js/Components/Dropdown.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue';\n\nconst props = withDefaults(\n    defineProps<{\n        align?: 'left' | 'right';\n        width?: '48';\n        contentClasses?: string;\n    }>(),\n    {\n        align: 'right',\n        width: '48',\n        contentClasses: 'py-1 bg-white dark:bg-gray-700',\n    }\n);\n\nconst closeOnEscape = (e: KeyboardEvent) => {\n    if (open.value && e.key === 'Escape') {\n        open.value = false;\n    }\n};\n\nonMounted(() => document.addEventListener('keydown', closeOnEscape));\nonUnmounted(() => document.removeEventListener('keydown', closeOnEscape));\n\nconst widthClass = computed(() => {\n    return {\n        48: 'w-48',\n    }[props.width.toString()];\n});\n\nconst alignmentClasses = computed(() => {\n    if (props.align === 'left') {\n        return 'ltr:origin-top-left rtl:origin-top-right start-0';\n    } else if (props.align === 'right') {\n        return 'ltr:origin-top-right rtl:origin-top-left end-0';\n    } else {\n        return 'origin-top';\n    }\n});\n\nconst open = ref(false);\n</script>\n\n<template>\n    <div class=\"relative\">\n        <div @click=\"open = !open\">\n            <slot name=\"trigger\" />\n        </div>\n\n        <!-- Full Screen Dropdown Overlay -->\n        <div v-show=\"open\" class=\"fixed inset-0 z-40\" @click=\"open = false\"></div>\n\n        <Transition\n            enter-active-class=\"transition ease-out duration-200\"\n            enter-from-class=\"opacity-0 scale-95\"\n            enter-to-class=\"opacity-100 scale-100\"\n            leave-active-class=\"transition ease-in duration-75\"\n            leave-from-class=\"opacity-100 scale-100\"\n            leave-to-class=\"opacity-0 scale-95\"\n        >\n            <div\n                v-show=\"open\"\n                class=\"absolute z-50 mt-2 rounded-md shadow-lg\"\n                :class=\"[widthClass, alignmentClasses]\"\n                style=\"display: none\"\n                @click=\"open = false\"\n            >\n                <div class=\"rounded-md ring-1 ring-black ring-opacity-5\" :class=\"contentClasses\">\n                    <slot name=\"content\" />\n                </div>\n            </div>\n        </Transition>\n    </div>\n</template>\n"
  },
  {
    "path": "resources/js/Components/DropdownLink.vue",
    "content": "<script setup lang=\"ts\">\nimport { Link } from '@inertiajs/vue3';\n\ndefineProps<{\n    href: string;\n}>();\n</script>\n\n<template>\n    <Link\n        :href=\"href\"\n        class=\"block w-full px-4 py-2 text-start text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-800 transition duration-150 ease-in-out\"\n    >\n        <slot />\n    </Link>\n</template>\n"
  },
  {
    "path": "resources/js/Components/Form/Checkbox.vue",
    "content": "<template>\n    <div :class=\"ui.wrapper\">\n        <input \n            v-bind=\"attrs\" \n            :id=\"labelId\" \n            type=\"checkbox\" \n            :value=\"value\" \n            v-model=\"proxyChecked\"\n            :class=\"[ui.checkbox.base, ui.checkbox.size, ui.checkbox.color]\" \n        />\n        <label :for=\"labelId\" :class=\"[ui.label.base, ui.label.size, ui.label.color]\">{{ label }}</label>\n    </div>\n</template>\n<script setup lang=\"ts\">\nimport { useUI } from '@/Composables/useUI';\nimport { computed, toRef } from 'vue';\n\nconst emit = defineEmits(['update:checked']);\n\nconst config = {\n    wrapper: 'flex items-center my-4',\n    checkbox: {\n        base: 'rounded focus:ring-2',\n        size: 'w-4 h-4',\n        color: 'text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600'\n    },\n    label: {\n        base: 'ms-2',\n        size: 'text-sm font-medium',\n        color: 'text-gray-900 dark:text-gray-300'\n    }\n};\n\nconst props = defineProps<{\n    modelValue: boolean;\n    value?: any;\n    label?: string; \n    ui?: any\n}>();\n\nconst { ui, attrs } = useUI('checkbox', toRef(props, 'ui'), config)\n\nconst proxyChecked = computed({\n    get() {\n        return props.modelValue;\n    },\n\n    set(val) {\n        emit('update:checked', val);\n    },\n});\n\nconst labelId = props.label.replace(/\\d*\\s*/, '').replaceAll(' ', '_').toLowerCase()\n\n</script>"
  },
  {
    "path": "resources/js/Components/Form/HeroiconPicker.vue",
    "content": "<template>\n  <div class=\"relative\" ref=\"container\">\n    <!-- Trigger button -->\n    <button\n      type=\"button\"\n      @click=\"open = !open\"\n      class=\"flex items-center gap-2 px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-200 hover:border-indigo-400 transition-colors text-sm w-full\"\n    >\n      <component :is=\"selectedComponent\" v-if=\"selectedComponent\" class=\"h-5 w-5 text-indigo-600 dark:text-indigo-400 flex-shrink-0\" />\n      <span v-else class=\"h-5 w-5 rounded bg-gray-200 dark:bg-gray-700 flex-shrink-0\" />\n      <span class=\"flex-1 text-left truncate\">{{ modelValue || 'Select an icon…' }}</span>\n      <ChevronDownIcon class=\"h-4 w-4 text-gray-400 flex-shrink-0\" />\n    </button>\n\n    <!-- Dropdown panel -->\n    <teleport to=\"body\">\n      <div\n        v-if=\"open\"\n        :style=\"panelStyle\"\n        class=\"fixed z-50 w-80 bg-white dark:bg-gray-900 rounded-xl shadow-2xl border border-gray-200 dark:border-gray-700 flex flex-col\"\n        style=\"max-height: 380px;\"\n      >\n        <!-- Search -->\n        <div class=\"p-2 border-b border-gray-100 dark:border-gray-800 flex-shrink-0\">\n          <div class=\"flex items-center gap-2 px-2 py-1.5 rounded-lg bg-gray-100 dark:bg-gray-800\">\n            <MagnifyingGlassIcon class=\"h-4 w-4 text-gray-400 flex-shrink-0\" />\n            <input\n              ref=\"searchInput\"\n              v-model=\"query\"\n              placeholder=\"Search icons…\"\n              class=\"flex-1 bg-transparent text-sm text-gray-800 dark:text-gray-100 outline-none placeholder-gray-400\"\n            />\n            <button v-if=\"query\" type=\"button\" @click=\"query = ''\" class=\"text-gray-400 hover:text-gray-600\">\n              <XMarkIcon class=\"h-3.5 w-3.5\" />\n            </button>\n          </div>\n        </div>\n\n        <!-- Icon grid -->\n        <div class=\"overflow-y-auto p-2 flex-1\">\n          <p v-if=\"filtered.length === 0\" class=\"text-xs text-gray-400 text-center py-6\">No icons found</p>\n          <div class=\"grid grid-cols-8 gap-1\">\n            <button\n              v-for=\"name in filtered\"\n              :key=\"name\"\n              type=\"button\"\n              :title=\"name.replace(/Icon$/, '')\"\n              @click=\"select(name)\"\n              class=\"flex items-center justify-center h-8 w-8 rounded-lg transition-colors\"\n              :class=\"modelValue === name\n                ? 'bg-indigo-100 dark:bg-indigo-900 text-indigo-600 dark:text-indigo-400'\n                : 'hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-600 dark:text-gray-400'\"\n            >\n              <component :is=\"allIcons[name]\" class=\"h-5 w-5\" />\n            </button>\n          </div>\n        </div>\n\n        <!-- Clear selection -->\n        <div v-if=\"modelValue\" class=\"p-2 border-t border-gray-100 dark:border-gray-800 flex-shrink-0\">\n          <button type=\"button\" @click=\"select('')\" class=\"text-xs text-red-500 hover:underline w-full text-left\">\n            Clear selection\n          </button>\n        </div>\n      </div>\n    </teleport>\n  </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue';\nimport * as OutlineIcons from '@heroicons/vue/24/outline';\nimport { ChevronDownIcon, MagnifyingGlassIcon, XMarkIcon } from '@heroicons/vue/24/outline';\n\nconst props = defineProps<{ modelValue: string }>();\nconst emit = defineEmits<{ (e: 'update:modelValue', value: string): void }>();\n\n// All icon names (excludes re-exported helpers that aren't components)\nconst allIcons = OutlineIcons as Record<string, any>;\nconst allNames: string[] = Object.keys(allIcons).filter(k => k.endsWith('Icon'));\n\nconst open = ref(false);\nconst query = ref('');\nconst container = ref<HTMLElement | null>(null);\nconst searchInput = ref<HTMLInputElement | null>(null);\nconst panelStyle = ref<Record<string, string>>({});\n\nconst filtered = computed(() => {\n  if (!query.value) return allNames;\n  const q = query.value.toLowerCase().replace(/\\s+/g, '');\n  return allNames.filter(n => n.toLowerCase().replace('icon', '').includes(q));\n});\n\nconst selectedComponent = computed(() =>\n  props.modelValue ? allIcons[props.modelValue] ?? null : null\n);\n\nfunction select(name: string) {\n  emit('update:modelValue', name);\n  open.value = false;\n  query.value = '';\n}\n\nfunction positionPanel() {\n  if (!container.value) return;\n  const rect = container.value.getBoundingClientRect();\n  const spaceBelow = window.innerHeight - rect.bottom;\n  const top = spaceBelow > 390 ? rect.bottom + 4 : rect.top - 384;\n  panelStyle.value = {\n    top: `${top}px`,\n    left: `${Math.min(rect.left, window.innerWidth - 320 - 8)}px`,\n  };\n}\n\nwatch(open, async (val) => {\n  if (val) {\n    positionPanel();\n    await nextTick();\n    searchInput.value?.focus();\n  }\n});\n\nfunction onClickOutside(e: MouseEvent) {\n  if (!open.value) return;\n  const target = e.target as Node;\n  if (container.value && container.value.contains(target)) return;\n  // Check if click is inside the teleported panel\n  const panel = document.querySelector('.fixed.z-50.w-80');\n  if (panel && panel.contains(target)) return;\n  open.value = false;\n}\n\nonMounted(() => document.addEventListener('mousedown', onClickOutside));\nonUnmounted(() => document.removeEventListener('mousedown', onClickOutside));\n</script>\n"
  },
  {
    "path": "resources/js/Components/Form/Input.vue",
    "content": "<template>\n    <div :class=\"type === 'hidden' ? 'hidden' : ui.wrapper\">\n        <input\n            :id=\"inputId\"\n            ref=\"input\"\n            :name=\"name\"\n            :value=\"modelValue\"\n            :type=\"type\"\n            :required=\"required\"\n            :placeholder=\"placeholder\"\n            :disabled=\"disabled\"\n            :class=\"inputClass\"\n            v-bind=\"attrs\"\n            @input=\"onInput\"\n            @blur=\"onBlur\"\n            @change=\"onChange\"\n        />\n        <slot />\n\n        <span\n            v-if=\"(isLeading && leadingIconName) || $slots.leading\"\n            :class=\"leadingWrapperIconClass\"\n        >\n            <slot name=\"leading\" :disabled=\"disabled\" :loading=\"loading\">\n                <svg\n                    width=\"36\"\n                    height=\"36\"\n                    :class=\"leadingIconClass\"\n                    viewBox=\"0 0 24 24\"\n                    xmlns=\"http://www.w3.org/2000/svg\"\n                >\n                    <path\n                        d=\"M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z\"\n                        opacity=\".25\"\n                    />\n                    <path\n                        d=\"M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z\"\n                        class=\"spinner_ajPY\"\n                    />\n                </svg>\n            </slot>\n        </span>\n\n        <span\n            v-if=\"(isTrailing && trailingIconName) || $slots.trailing\"\n            :class=\"trailingWrapperIconClass\"\n        >\n            <slot name=\"trailing\" :disabled=\"disabled\" :loading=\"loading\">\n                <Icon :name=\"trailingIconName\" :class=\"trailingIconClass\" />\n            </slot>\n        </span>\n    </div>\n</template>\n\n<script lang=\"ts\">\nimport { ref, computed, toRef, onMounted, defineComponent } from \"vue\";\nimport type { PropType } from \"vue\";\nimport { twMerge, twJoin } from \"tailwind-merge\";\nimport { defu } from \"defu\";\nimport { useUI } from \"@/Composables/useUI\";\nimport { useFormGroup } from \"@/Composables/useFormGroup\";\nimport { mergeConfig, looseToNumber } from \"@/Composables/utils\";\nimport { useInjectButtonGroup } from \"@/Composables/useButtonGroup\";\nimport type { Sizes, InputColor, InputVariant, Strategy, IconName } from \"@/types\";\nimport Icon from \"@/Components/Icon.vue\";\n\nconst config = {\n    wrapper: \"relative\",\n    base: \"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0\",\n    form: \"form-input\",\n    rounded: \"rounded-md\",\n    placeholder: \"placeholder-gray-400 dark:placeholder-gray-500\",\n    file: {\n        base: \"file:mr-1.5 file:font-medium file:text-gray-500 dark:file:text-gray-400 file:bg-transparent file:border-0 file:p-0 file:outline-none\",\n    },\n    size: {\n        \"2xs\": \"text-xs\",\n        xs: \"text-xs\",\n        sm: \"text-sm\",\n        md: \"text-md\",\n        lg: \"text-lg\",\n        xl: \"text-base\",\n    },\n    gap: {\n        \"2xs\": \"gap-x-1\",\n        xs: \"gap-x-1.5\",\n        sm: \"gap-x-1.5\",\n        md: \"gap-x-2\",\n        lg: \"gap-x-2.5\",\n        xl: \"gap-x-2.5\",\n    },\n    padding: {\n        \"2xs\": \"px-2 py-1\",\n        xs: \"px-2.5 py-1.5\",\n        sm: \"px-2.5 py-1.5\",\n        md: \"px-3 py-2\",\n        lg: \"px-3.5 py-2.5\",\n        xl: \"px-3.5 py-2.5\",\n    },\n    leading: {\n        padding: {\n            \"2xs\": \"ps-7\",\n            xs: \"ps-8\",\n            sm: \"ps-9\",\n            md: \"ps-10\",\n            lg: \"ps-11\",\n            xl: \"ps-12\",\n        },\n    },\n    trailing: {\n        padding: {\n            \"2xs\": \"pe-7\",\n            xs: \"pe-8\",\n            sm: \"pe-9\",\n            md: \"pe-10\",\n            lg: \"pe-11\",\n            xl: \"pe-12\",\n        },\n    },\n    color: {\n        white: {\n            outline:\n                \"shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400\",\n        },\n        gray: {\n            outline:\n                \"shadow-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400\",\n        },\n        red: {\n            outline:\n                \"shadow-sm bg-gray-50 dark:bg-gray-800 text-red-900 dark:text-white ring-1 ring-inset ring-red-300 dark:ring-red-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400\",\n        },\n    },\n    variant: {\n        outline:\n            \"shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-{color}-500 dark:ring-{color}-400 focus:ring-2 focus:ring-{color}-500 dark:focus:ring-{color}-400\",\n        none: \"bg-transparent focus:ring-0 focus:shadow-none\",\n    },\n    icon: {\n        base: \"flex-shrink-0 text-gray-400 dark:text-gray-500\",\n        color: \"text-{color}-500 dark:text-{color}-400\",\n        loading: \"animate-spin\",\n        size: {\n            \"2xs\": \"h-4 w-4\",\n            xs: \"h-4 w-4\",\n            sm: \"h-5 w-5\",\n            md: \"h-5 w-5\",\n            lg: \"h-5 w-5\",\n            xl: \"h-6 w-6\",\n        },\n        leading: {\n            wrapper: \"absolute inset-y-0 start-0 flex items-center\",\n            pointer: \"pointer-events-none\",\n            padding: {\n                \"2xs\": \"px-2\",\n                xs: \"px-2.5\",\n                sm: \"px-2.5\",\n                md: \"px-3\",\n                lg: \"px-3.5\",\n                xl: \"px-3.5\",\n            },\n        },\n        trailing: {\n            wrapper: \"absolute inset-y-0 end-0 flex items-center\",\n            pointer: \"\",\n            padding: {\n                \"2xs\": \"px-2\",\n                xs: \"px-2.5\",\n                sm: \"px-2.5\",\n                md: \"px-3\",\n                lg: \"px-3.5\",\n                xl: \"px-3.5\",\n            },\n        },\n    },\n    default: {\n        size: \"md\",\n        color: \"blue\",\n        variant: \"outline\",\n        loadingIcon: \"i-heroicons-arrow-path-20-solid\",\n    },\n};\n\nexport default defineComponent({\n    components: {\n        Icon\n    },\n    inheritAttrs: false,\n    props: {\n        modelValue: {\n            type: [String, Number],\n            default: \"\",\n        },\n        type: {\n            type: String,\n            default: \"text\",\n        },\n        id: {\n            type: String,\n            default: null,\n        },\n        name: {\n            type: String,\n            default: null,\n        },\n        placeholder: {\n            type: String,\n            default: null,\n        },\n        required: {\n            type: Boolean,\n            default: false,\n        },\n        disabled: {\n            type: Boolean,\n            default: false,\n        },\n        autofocus: {\n            type: Boolean,\n            default: false,\n        },\n        autofocusDelay: {\n            type: Number,\n            default: 100,\n        },\n        icon: {\n            type: String as PropType<IconName>,\n            default: null,\n        },\n        loadingIcon: {\n            type: String as PropType<IconName>,\n            default: () => config.default.loadingIcon,\n        },\n        leadingIcon: {\n            type: String as PropType<IconName>,\n            default: null,\n        },\n        trailingIcon: {\n            type: String as PropType<IconName>,\n            default: null,\n        },\n        trailing: {\n            type: Boolean,\n            default: false,\n        },\n        leading: {\n            type: Boolean,\n            default: false,\n        },\n        loading: {\n            type: Boolean,\n            default: false,\n        },\n        padded: {\n            type: Boolean,\n            default: true,\n        },\n        size: {\n            type: String as PropType<Sizes>,\n            default: config.default.size,\n            validator(value: string) {\n                return Object.keys(config.size).includes(value);\n            },\n        },\n        color: {\n            type: String as PropType<InputColor>,\n            default: () => config.default.color,\n            validator(value: string) {\n                return [...Object.keys(config.color)].includes(value);\n            },\n        },\n        variant: {\n            type: String as PropType<InputVariant>,\n            default: () => config.default.variant,\n            validator(value: string) {\n                return [\n                    ...Object.keys(config.variant),\n                    ...Object.values(config.color).flatMap((value) =>\n                        Object.keys(value)\n                    ),\n                ].includes(value);\n            },\n        },\n        inputClass: {\n            type: String,\n            default: null,\n        },\n        class: {\n            type: [String, Object, Array] as PropType<any>,\n            default: () => \"\",\n        },\n        ui: {\n            type: Object as PropType<\n                Partial<typeof config> & { strategy?: Strategy }\n            >,\n            default: () => ({}),\n        },\n        modelModifiers: {\n            type: Object as PropType<{\n                trim?: boolean;\n                lazy?: boolean;\n                number?: boolean;\n            }>,\n            default: () => ({}),\n        },\n    },\n    emits: [\"update:modelValue\", \"blur\", \"change\"],\n    setup(props, { emit, slots }) {\n        const { ui, attrs } = useUI(\n            \"input\",\n            toRef(props, \"ui\"),\n            config,\n            toRef(props, \"class\")\n        );\n\n        const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({\n            ui,\n            props,\n        });\n\n        const {\n            emitFormBlur,\n            emitFormInput,\n            size: sizeFormGroup,\n            color,\n            inputId,\n            name,\n        } = useFormGroup(props, config);\n\n        const size = computed<Sizes>(\n            () => sizeButtonGroup.value ?? sizeFormGroup.value\n        );\n\n        const modelModifiers = ref(\n            defu({}, props.modelModifiers, {\n                trim: false,\n                lazy: false,\n                number: false,\n            })\n        );\n\n        const input = ref<HTMLInputElement | null>(null);\n\n        const autoFocus = () => {\n            if (props.autofocus) {\n                input.value?.focus();\n            }\n        };\n\n        // Custom function to handle the v-model properties\n        const updateInput = (value: string) => {\n            if (modelModifiers.value.trim) {\n                value = value.trim();\n            }\n\n            if (modelModifiers.value.number || props.type === \"number\") {\n                value = looseToNumber(value);\n            }\n\n            emit(\"update:modelValue\", value);\n            emitFormInput();\n        };\n\n        const onInput = (event: Event) => {\n            if (!modelModifiers.value.lazy) {\n                updateInput((event.target as HTMLInputElement).value);\n            }\n        };\n\n        const onChange = (event: Event) => {\n            if (props.type === \"file\") {\n                const value = (event.target as HTMLInputElement).files;\n                emit(\"change\", value);\n            } else {\n                const value = (event.target as HTMLInputElement).value;\n                emit(\"change\", value);\n                if (modelModifiers.value.lazy) {\n                    updateInput(value);\n                }\n                // Update trimmed input so that it has same behavior as native input https://github.com/vuejs/core/blob/5ea8a8a4fab4e19a71e123e4d27d051f5e927172/packages/runtime-dom/src/directives/vModel.ts#L63\n                if (modelModifiers.value.trim) {\n                    (event.target as HTMLInputElement).value = value.trim();\n                }\n            }\n        };\n\n        const onBlur = (event: FocusEvent) => {\n            emitFormBlur();\n            emit(\"blur\", event);\n        };\n\n        onMounted(() => {\n            setTimeout(() => {\n                autoFocus();\n            }, props.autofocusDelay);\n        });\n\n        const inputClass = computed(() => {\n            const variant =\n                ui.value.color?.[color.value as string]?.[\n                    props.variant as string\n                ] || ui.value.variant[props.variant];\n\n            return twMerge(\n                twJoin(\n                    ui.value.base,\n                    ui.value.form,\n                    rounded.value,\n                    ui.value.placeholder,\n                    props.type === \"file\" && ui.value.file.base,\n                    ui.value.size[size.value],\n                    props.padded ? ui.value.padding[size.value] : \"p-0\",\n                    variant?.replaceAll(\"{color}\", color.value ?? \"gray\"),\n                    (isLeading.value || slots.leading) &&\n                        ui.value.leading.padding[size.value],\n                    (isTrailing.value || slots.trailing) &&\n                        ui.value.trailing.padding[size.value]\n                ),\n                props.inputClass\n            );\n        });\n\n        const isLeading = computed(() => {\n            return (\n                (props.icon && props.leading) ||\n                (props.icon && !props.trailing) ||\n                (props.loading && !props.trailing) ||\n                props.leadingIcon\n            );\n        });\n\n        const isTrailing = computed(() => {\n            return (\n                (props.icon && props.trailing) ||\n                (props.loading && props.trailing) ||\n                props.trailingIcon\n            );\n        });\n\n        const leadingIconName = computed(() => {\n            if (props.loading) {\n                return props.loadingIcon;\n            }\n\n            return props.leadingIcon || props.icon;\n        });\n\n        const trailingIconName = computed(() => {\n            if (props.loading && !isLeading.value) {\n                return props.loadingIcon;\n            }\n\n            return props.trailingIcon || props.icon;\n        });\n\n        const leadingWrapperIconClass = computed(() => {\n            return twJoin(\n                ui.value.icon.leading.wrapper,\n                ui.value.icon.leading.pointer,\n                ui.value.icon.leading.padding[size.value]\n            );\n        });\n\n        const leadingIconClass = computed(() => {\n            return twJoin(\n                ui.value.icon.base,\n                color.value &&\n                    ui.value.icon.color.replaceAll(\"{color}\", color.value),\n                ui.value.icon.size[size.value],\n                props.loading && ui.value.icon.loading\n            );\n        });\n\n        const trailingWrapperIconClass = computed(() => {\n            return twJoin(\n                ui.value.icon.trailing.wrapper,\n                ui.value.icon.trailing.pointer,\n                // ui.value.icon.trailing.padding[size.value]\n            );\n        });\n\n        const trailingIconClass = computed(() => {\n            return twJoin(\n                ui.value.icon.base,\n                color.value &&\n                    ui.value.icon.color.replaceAll(\"{color}\", color.value),\n                ui.value.icon.size[size.value],\n                props.loading && !isLeading.value && ui.value.icon.loading\n            );\n        });\n\n        return {\n            // eslint-disable-next-line vue/no-dupe-keys\n            ui,\n            attrs,\n            // eslint-disable-next-line vue/no-dupe-keys\n            name,\n            inputId,\n            input,\n            isLeading,\n            isTrailing,\n            // eslint-disable-next-line vue/no-dupe-keys\n            inputClass,\n            leadingIconName,\n            leadingIconClass,\n            leadingWrapperIconClass,\n            trailingIconName,\n            trailingIconClass,\n            trailingWrapperIconClass,\n            onInput,\n            onChange,\n            onBlur,\n        };\n    },\n});\n</script>\n"
  },
  {
    "path": "resources/js/Components/Form/Label.vue",
    "content": "<template>\n    <div :class=\"ui.wrapper\" v-bind=\"attrs\">\n      <div :class=\"ui.inner\">\n        <div v-if=\"label || $slots.label\" :class=\"[ui.label.wrapper, size]\">\n          <label :for=\"inputId\" :class=\"[ui.label.base, required ? ui.label.required : '']\">\n            <slot v-if=\"$slots.label\" name=\"label\" v-bind=\"{ error, label, name, hint, description, help }\" />\n            <template v-else>{{ label }}</template>\n          </label>\n          <span v-if=\"hint || $slots.hint\" :class=\"[ui.hint]\">\n            <slot v-if=\"$slots.hint\" name=\"hint\" v-bind=\"{ error, label, name, hint, description, help }\" />\n            <template v-else>{{ hint }}</template>\n          </span>\n        </div>\n  \n        <p v-if=\"description || $slots.description\" :class=\"[ui.description, size]\">\n          <slot v-if=\"$slots.description\" name=\"description\" v-bind=\"{ error, label, name, hint, description, help }\" />\n          <template v-else>\n            {{ description }}\n          </template>\n        </p>\n      </div>\n  \n      <div :class=\"[label ? ui.container : '']\">\n        <slot v-bind=\"{ error }\" />\n  \n        <p v-if=\"typeof error === 'string' && error\" :class=\"[ui.error, size]\">\n          <slot v-if=\"$slots.error\" name=\"error\" v-bind=\"{ error, label, name, hint, description, help }\" />\n          <template v-else>\n            {{ error }}\n          </template>\n        </p>\n        <p v-else-if=\"help || $slots.help\" :class=\"[ui.help, size]\">\n          <slot v-if=\"$slots.help\" name=\"help\" v-bind=\"{ error, label, name, hint, description, help }\" />\n          <template v-else>\n            {{ help }}\n          </template>\n        </p>\n      </div>\n    </div>\n  </template>\n  \n  <script lang=\"ts\">\n  import { computed, defineComponent, provide, inject, ref, toRef } from 'vue'\n  import type { Ref, PropType } from 'vue'\n  import { useUI } from '@/Composables/useUI';\n  import { useId } from '@/Composables/utils';\n  import type { Strategy } from '@/types';\n  import type { FormError, InjectedFormGroupValue, Sizes } from '@/types'\n\n  const config = {\n  wrapper: '',\n  inner: '',\n  label: {\n    wrapper: 'flex content-center items-center justify-between',\n    base: 'block font-medium text-gray-700 dark:text-gray-200',\n    // eslint-disable-next-line quotes\n    required: `after:content-['*'] after:ms-0.5 after:text-red-500 dark:after:text-red-400`\n  },\n  size: {\n    '2xs': 'text-xs',\n    xs: 'text-xs',\n    sm: 'text-sm',\n    md: 'text-sm',\n    lg: 'text-sm',\n    xl: 'text-base'\n  },\n  container: 'mt-1 relative',\n  description: 'text-gray-500 dark:text-gray-400',\n  hint: 'text-gray-500 dark:text-gray-400',\n  help: 'mt-2 text-gray-500 dark:text-gray-400',\n  error: 'mt-2 text-red-500 dark:text-red-400',\n  default: {\n    size: 'md'\n  }\n}\n  \n  export default defineComponent({\n    inheritAttrs: false,\n    props: {\n      name: {\n        type: String,\n        default: null\n      },\n      size: {\n        type: String as PropType<Sizes>,\n        default: null,\n        validator (value: string) {\n          return Object.keys(config.size).includes(value)\n        }\n      },\n      label: {\n        type: String,\n        default: null\n      },\n      description: {\n        type: String,\n        default: null\n      },\n      required: {\n        type: Boolean,\n        default: false\n      },\n      help: {\n        type: String,\n        default: null\n      },\n      error: {\n        type: [String, Boolean],\n        default: null\n      },\n      hint: {\n        type: String,\n        default: null\n      },\n      class: {\n        type: [String, Object, Array] as PropType<any>,\n        default: () => ''\n      },\n      ui: {\n        type: Object as PropType<Partial<typeof config> & { strategy?: Strategy }>,\n        default: () => ({})\n      },\n      eagerValidation: {\n        type: Boolean,\n        default: false\n      }\n    },\n    setup (props) {\n      const { ui, attrs } = useUI('formGroup', toRef(props, 'ui'), config, toRef(props, 'class'))\n  \n      const formErrors = inject<Ref<FormError[]> | null>('form-errors', null)\n  \n      const error = computed(() => {\n        return (props.error && typeof props.error === 'string') || typeof props.error === 'boolean'\n          ? props.error\n          : formErrors?.value?.find((error) => error.path === props.name)?.message\n      })\n  \n      const size = computed(() => ui.value.size[props.size ?? config.default.size])\n      const inputId = ref(useId())\n  \n      provide<InjectedFormGroupValue>('form-group', {\n        error,\n        inputId,\n        name: computed(() => props.name),\n        size: computed(() => props.size),\n        eagerValidation: computed(() => props.eagerValidation)\n      })\n  \n      return {\n        // eslint-disable-next-line vue/no-dupe-keys\n        ui,\n        attrs,\n        inputId,\n        // eslint-disable-next-line vue/no-dupe-keys\n        size,\n        // eslint-disable-next-line vue/no-dupe-keys\n        error\n      }\n    }\n  })\n  </script>"
  },
  {
    "path": "resources/js/Components/Form/Listbox.examplevue",
    "content": "<template>\n  <component\n    :is=\"searchable ? 'HCombobox' : 'HListbox'\"\n    v-slot=\"{ open }\"\n    :by=\"by\"\n    :name=\"name\"\n    :model-value=\"modelValue\"\n    :multiple=\"multiple\"\n    :disabled=\"disabled\"\n    as=\"div\"\n    :class=\"ui.wrapper\"\n    @update:model-value=\"onUpdate\"\n  >\n    <input\n      v-if=\"required\"\n      :value=\"modelValue\"\n      :required=\"required\"\n      :class=\"ui.required\"\n      tabindex=\"-1\"\n      aria-hidden=\"true\"\n    >\n\n    <component\n      :is=\"searchable ? 'HComboboxButton' : 'HListboxButton'\"\n      ref=\"trigger\"\n      as=\"div\"\n      role=\"button\"\n      :class=\"ui.trigger\"\n    >\n      <slot :open=\"open\" :disabled=\"disabled\" :loading=\"loading\">\n        <button :id=\"inputId\" :class=\"selectClass\" :disabled=\"disabled\" type=\"button\" v-bind=\"attrs\">\n          <span v-if=\"(isLeading && leadingIconName) || $slots.leading\" :class=\"leadingWrapperIconClass\">\n            <slot name=\"leading\" :disabled=\"disabled\" :loading=\"loading\">\n              <Icon :name=\"leadingIconName\" :class=\"leadingIconClass\" />\n            </slot>\n          </span>\n\n          <slot name=\"label\">\n            <span v-if=\"label\" :class=\"ui.label\">{{ label }}</span>\n            <span v-else :class=\"ui.label\">{{ placeholder || '&nbsp;' }}</span>\n          </slot>\n\n          <span v-if=\"(isTrailing && trailingIconName) || $slots.trailing\" :class=\"trailingWrapperIconClass\">\n            <slot name=\"trailing\" :disabled=\"disabled\" :loading=\"loading\">\n              <Icon :name=\"trailingIconName\" :class=\"trailingIconClass\" aria-hidden=\"true\" />\n            </slot>\n          </span>\n        </button>\n      </slot>\n    </component>\n\n    <div v-if=\"open\" ref=\"container\" :class=\"[ui.container, ui.width]\">\n      <Transition appear v-bind=\"ui.transition\">\n        <div>\n          <div v-if=\"popper.arrow\" data-popper-arrow :class=\"Object.values(ui.arrow)\" />\n\n          <component :is=\"searchable ? 'HComboboxOptions' : 'HListboxOptions'\" static :class=\"[ui.base, ui.ring, ui.rounded, ui.shadow, ui.background, ui.padding, ui.height]\">\n            <HComboboxInput\n              v-if=\"searchable\"\n              :display-value=\"() => query\"\n              name=\"q\"\n              :placeholder=\"searchablePlaceholder\"\n              autofocus\n              autocomplete=\"off\"\n              :class=\"ui.input\"\n              @change=\"onQueryChange\"\n            />\n            <component\n              :is=\"searchable ? 'HComboboxOption' : 'HListboxOption'\"\n              v-for=\"(option, index) in filteredOptions\"\n              v-slot=\"{ active, selected, disabled: optionDisabled }\"\n              :key=\"index\"\n              as=\"template\"\n              :value=\"valueAttribute ? option[valueAttribute] : option\"\n              :disabled=\"option.disabled\"\n            >\n              <li :class=\"[ui.option.base, ui.option.rounded, ui.option.padding, ui.option.size, ui.option.color, active ? ui.option.active : ui.option.inactive, selected && ui.option.selected, optionDisabled && ui.option.disabled]\">\n                <div :class=\"ui.option.container\">\n                  <slot name=\"option\" :option=\"option\" :active=\"active\" :selected=\"selected\">\n                    <Icon v-if=\"option.icon\" :name=\"option.icon\" :class=\"[ui.option.icon.base, active ? ui.option.icon.active : ui.option.icon.inactive, option.iconClass]\" aria-hidden=\"true\" />\n                    <UAvatar\n                      v-else-if=\"option.avatar\"\n                      v-bind=\"{ size: ui.option.avatar.size, ...option.avatar }\"\n                      :class=\"ui.option.avatar.base\"\n                      aria-hidden=\"true\"\n                    />\n                    <span v-else-if=\"option.chip\" :class=\"ui.option.chip.base\" :style=\"{ background: `#${option.chip}` }\" />\n\n                    <span class=\"truncate\">{{ ['string', 'number'].includes(typeof option) ? option : option[optionAttribute] }}</span>\n                  </slot>\n                </div>\n\n                <span v-if=\"selected\" :class=\"[ui.option.selectedIcon.wrapper, ui.option.selectedIcon.padding]\">\n                  <Icon :name=\"selectedIcon\" :class=\"ui.option.selectedIcon.base\" aria-hidden=\"true\" />\n                </span>\n              </li>\n            </component>\n\n            <component :is=\"searchable ? 'HComboboxOption' : 'HListboxOption'\" v-if=\"creatable && createOption\" v-slot=\"{ active, selected }\" :value=\"createOption\" as=\"template\">\n              <li :class=\"[ui.option.base, ui.option.rounded, ui.option.padding, ui.option.size, ui.option.color, active ? ui.option.active : ui.option.inactive]\">\n                <div :class=\"ui.option.container\">\n                  <slot name=\"option-create\" :option=\"createOption\" :active=\"active\" :selected=\"selected\">\n                    <span :class=\"ui.option.create\">Create \"{{ createOption[optionAttribute] }}\"</span>\n                  </slot>\n                </div>\n              </li>\n            </component>\n            <p v-else-if=\"searchable && query && !filteredOptions?.length\" :class=\"ui.option.empty\">\n              <slot name=\"option-empty\" :query=\"query\">\n                No results for \"{{ query }}\".\n              </slot>\n            </p>\n            <p v-else-if=\"!filteredOptions?.length\" :class=\"ui.empty\">\n              <slot name=\"empty\" :query=\"query\">\n                No options.\n              </slot>\n            </p>\n          </component>\n        </div>\n      </Transition>\n    </div>\n  </component>\n</template>\n\n<script lang=\"ts\">\nimport { ref, computed, toRef, watch, defineComponent } from 'vue'\nimport type { PropType } from 'vue'\nimport {\n  Combobox as HCombobox,\n  ComboboxButton as HComboboxButton,\n  ComboboxOptions as HComboboxOptions,\n  ComboboxOption as HComboboxOption,\n  ComboboxInput as HComboboxInput,\n  Listbox as HListbox,\n  ListboxButton as HListboxButton,\n  ListboxOptions as HListboxOptions,\n  ListboxOption as HListboxOption,\n  provideUseId\n} from '@headlessui/vue'\nimport { computedAsync, useDebounceFn } from '@vueuse/core'\nimport { defu } from 'defu'\nimport { twMerge, twJoin } from 'tailwind-merge'\nimport Icon from '@/Components/Icon.vue'\nimport { useUI } from '@/Composables/useUI'\nimport { usePopper } from '@/Composables/usePopper'\nimport { useFormGroup } from '@/Composables/useFormGroup'\nimport { get, useId, mergeConfig } from '@/Composables/utils'\nimport { useInjectButtonGroup } from '@/Composables/useButtonGroup'\nimport type { PopperOptions, Strategy } from '../../types'\n\n\nconst config = {\n    wrapper: \"relative\",\n    base: \"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0\",\n    form: \"form-select\",\n    select: '',\n    placeholder: \"text-gray-400 dark:text-gray-500\",\n    rounded: \"rounded-md\",\n    file: {\n        base: \"file:mr-1.5 file:font-medium file:text-gray-500 dark:file:text-gray-400 file:bg-transparent file:border-0 file:p-0 file:outline-none\",\n    },\n    size: {\n        \"2xs\": \"text-xs\",\n        xs: \"text-xs\",\n        sm: \"text-sm\",\n        md: \"text-sm\",\n        lg: \"text-sm\",\n        xl: \"text-base\",\n    },\n    gap: {\n        \"2xs\": \"gap-x-1\",\n        xs: \"gap-x-1.5\",\n        sm: \"gap-x-1.5\",\n        md: \"gap-x-2\",\n        lg: \"gap-x-2.5\",\n        xl: \"gap-x-2.5\",\n    },\n    padding: {\n        \"2xs\": \"px-2 py-1\",\n        xs: \"px-2.5 py-1.5\",\n        sm: \"px-2.5 py-1.5\",\n        md: \"px-3 py-2\",\n        lg: \"px-3.5 py-2.5\",\n        xl: \"px-3.5 py-2.5\",\n    },\n    leading: {\n        padding: {\n            \"2xs\": \"ps-7\",\n            xs: \"ps-8\",\n            sm: \"ps-9\",\n            md: \"ps-10\",\n            lg: \"ps-11\",\n            xl: \"ps-12\",\n        },\n    },\n    trailing: {\n        padding: {\n            \"2xs\": \"pe-7\",\n            xs: \"pe-8\",\n            sm: \"pe-9\",\n            md: \"pe-10\",\n            lg: \"pe-11\",\n            xl: \"pe-12\",\n        },\n    },\n    color: {\n        white: {\n            outline:\n                \"shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400\",\n        },\n        gray: {\n            outline:\n                \"shadow-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400\",\n        },\n    },\n    variant: {\n        outline:\n            \"shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-{color}-500 dark:ring-{color}-400 focus:ring-2 focus:ring-{color}-500 dark:focus:ring-{color}-400\",\n        none: \"bg-transparent focus:ring-0 focus:shadow-none\",\n    },\n    icon: {\n        base: \"flex-shrink-0 text-gray-400 dark:text-gray-500\",\n        color: \"text-{color}-500 dark:text-{color}-400\",\n        loading: \"animate-spin\",\n        size: {\n            \"2xs\": \"h-4 w-4\",\n            xs: \"h-4 w-4\",\n            sm: \"h-5 w-5\",\n            md: \"h-5 w-5\",\n            lg: \"h-5 w-5\",\n            xl: \"h-6 w-6\",\n        },\n        leading: {\n            wrapper: \"absolute inset-y-0 start-0 flex items-center\",\n            pointer: \"pointer-events-none\",\n            padding: {\n                \"2xs\": \"px-2\",\n                xs: \"px-2.5\",\n                sm: \"px-2.5\",\n                md: \"px-3\",\n                lg: \"px-3.5\",\n                xl: \"px-3.5\",\n            },\n        },\n        trailing: {\n            wrapper: \"absolute inset-y-0 end-0 flex items-center\",\n            pointer: \"pointer-events-none\",\n            padding: {\n                \"2xs\": \"px-2\",\n                xs: \"px-2.5\",\n                sm: \"px-2.5\",\n                md: \"px-3\",\n                lg: \"px-3.5\",\n                xl: \"px-3.5\",\n            },\n        },\n    },\n    default: {\n        size: \"sm\",\n        color: \"white\",\n        variant: \"outline\",\n        loadingIcon: \"LoadingIcon\",\n        trailingIcon: \"MagnifyingGlassIcon\",\n        selectedIcon: \"\",\n        clearSearchOnClose: true,\n        showCreateOptionWhen: ''\n    },\n};\n\n type SelectSize = keyof typeof config.size \n type SelectColor = keyof typeof config.color \n type SelectVariant = keyof typeof config.variant \n\n\nexport default defineComponent({\n  components: {\n    HCombobox,\n    HComboboxButton,\n    HComboboxOptions,\n    HComboboxOption,\n    HComboboxInput,\n    HListbox,\n    HListboxButton,\n    HListboxOptions,\n    HListboxOption,\n    Icon,\n  },\n  inheritAttrs: false,\n  props: {\n    modelValue: {\n      type: [String, Number, Object, Array, Boolean],\n      default: ''\n    },\n    query: {\n      type: String,\n      default: null\n    },\n    by: {\n      type: String,\n      default: undefined\n    },\n    options: {\n      type: Array as PropType<{ [key: string]: any, disabled?: boolean }[] | string[]>,\n      default: () => []\n    },\n    id: {\n      type: String,\n      default: null\n    },\n    name: {\n      type: String,\n      default: null\n    },\n    required: {\n      type: Boolean,\n      default: false\n    },\n    icon: {\n      type: String,\n      default: null\n    },\n    loadingIcon: {\n      type: String,\n      default: () => config.default.loadingIcon\n    },\n    leadingIcon: {\n      type: String,\n      default: null\n    },\n    trailingIcon: {\n      type: String,\n      default: () => config.default.trailingIcon\n    },\n    trailing: {\n      type: Boolean,\n      default: false\n    },\n    leading: {\n      type: Boolean,\n      default: false\n    },\n    loading: {\n      type: Boolean,\n      default: false\n    },\n    selectedIcon: {\n      type: String,\n      default: () => config.default.selectedIcon\n    },\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    multiple: {\n      type: Boolean,\n      default: false\n    },\n    searchable: {\n      type: [Boolean, Function] as PropType<boolean | ((query: string) => Promise<any[]> | any[])>,\n      default: false\n    },\n    searchablePlaceholder: {\n      type: String,\n      default: 'Search...'\n    },\n    searchableLazy: {\n      type: Boolean,\n      default: false\n    },\n    clearSearchOnClose: {\n      type: Boolean,\n      default: () => config.default.clearSearchOnClose\n    },\n    debounce: {\n      type: Number,\n      default: 200\n    },\n    creatable: {\n      type: Boolean,\n      default: false\n    },\n    showCreateOptionWhen: {\n      type: [String, Function] as PropType<'always' | 'empty' | ((query: string, results: any[]) => boolean)>,\n      default: () => config.default.showCreateOptionWhen\n    },\n    placeholder: {\n      type: String,\n      default: null\n    },\n    padded: {\n      type: Boolean,\n      default: true\n    },\n    size: {\n      type: String as PropType<SelectSize>,\n      default: null,\n      validator (value: string) {\n        return Object.keys(config.size).includes(value)\n      }\n    },\n    color: {\n      type: String as PropType<SelectColor>,\n      default: () => config.default.color,\n      validator (value: string) {\n        return [ ...Object.keys(config.color)].includes(value)\n      }\n    },\n    variant: {\n      type: String as PropType<SelectVariant>,\n      default: () => config.default.variant,\n      validator (value: string) {\n        return [\n          ...Object.keys(config.variant),\n          ...Object.values(config.color).flatMap(value => Object.keys(value))\n        ].includes(value)\n      }\n    },\n    optionAttribute: {\n      type: String,\n      default: 'label'\n    },\n    valueAttribute: {\n      type: String,\n      default: null\n    },\n    searchAttributes: {\n      type: Array,\n      default: null\n    },\n    popper: {\n      type: Object as PropType<PopperOptions>,\n      default: () => ({})\n    },\n    selectClass: {\n      type: String,\n      default: null\n    },\n    class: {\n      type: [String, Object, Array] as PropType<any>,\n      default: () => ''\n    },\n    ui: {\n      type: Object as PropType<Partial<typeof config> & { strategy?: Strategy }>,\n      default: () => ({})\n    },\n  },\n  emits: ['update:modelValue', 'update:query', 'open', 'close', 'change'],\n  setup (props, { emit, slots }) {\n    const { ui, attrs } = useUI('selectMenu', toRef(props, 'ui'), config, toRef(props, 'class'))\n\n    // const popper = computed<PopperOptions>(() => defu({}, props.popper, ui.value.popper as PopperOptions))\n\n    // const [trigger, container] = usePopper(popper.value)\n\n    const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({ ui, props })\n    const { emitFormBlur, emitFormChange, inputId, color, size: sizeFormGroup, name } = useFormGroup(props, config)\n\n    const size = computed(() => sizeButtonGroup.value ?? sizeFormGroup.value)\n\n    const internalQuery = ref('')\n    const query = computed({\n      get () {\n        return props.query ?? internalQuery.value\n      },\n      set (value) {\n        internalQuery.value = value\n        emit('update:query', value)\n      }\n    })\n\n    const label = computed(() => {\n      if (props.multiple) {\n        if (Array.isArray(props.modelValue) && props.modelValue.length) {\n          return `${props.modelValue.length} selected`\n        } else {\n          return null\n        }\n      } else if (props.modelValue !== undefined && props.modelValue !== null) {\n        if (props.valueAttribute) {\n          const option = options.value.find(option => option[props.valueAttribute] === props.modelValue)\n          return option ? option[props.optionAttribute] : null\n        } else {\n          return ['string', 'number'].includes(typeof props.modelValue) ? props.modelValue : props.modelValue[props.optionAttribute]\n        }\n      }\n\n      return null\n    })\n\n    const selectClass = computed(() => {\n      const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]\n\n      return twMerge(twJoin(\n        ui.value.base,\n        ui.value.select,\n        rounded.value,\n        ui.value.size[size.value],\n        ui.value.gap[size.value],\n        props.padded ? ui.value.padding[size.value] : 'p-0',\n        variant?.replaceAll('{color}', color.value),\n        (isLeading.value || slots.leading) && ui.value.leading.padding[size.value],\n        (isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value]\n      ), props.placeholder && !props.modelValue && ui.value.placeholder, props.selectClass)\n    })\n\n    const isLeading = computed(() => {\n      return (props.icon && props.leading) || (props.icon && !props.trailing) || (props.loading && !props.trailing) || props.leadingIcon\n    })\n\n    const isTrailing = computed(() => {\n      return (props.icon && props.trailing) || (props.loading && props.trailing) || props.trailingIcon\n    })\n\n    const leadingIconName = computed(() => {\n      if (props.loading) {\n        return props.loadingIcon\n      }\n\n      return props.leadingIcon || props.icon\n    })\n\n    const trailingIconName = computed(() => {\n      if (props.loading && !isLeading.value) {\n        return props.loadingIcon\n      }\n\n      return props.trailingIcon || props.icon\n    })\n\n    const leadingWrapperIconClass = computed(() => {\n      return twJoin(\n        ui.value.icon.leading.wrapper,\n        ui.value.icon.leading.pointer,\n        ui.value.icon.leading.padding[size.value]\n      )\n    })\n\n    const leadingIconClass = computed(() => {\n      return twJoin(\n        ui.value.icon.base,\n        color.value && ui.value.icon.color.replaceAll('{color}', color.value),\n        ui.value.icon.size[size.value],\n        props.loading && ui.value.icon.loading\n      )\n    })\n\n    const trailingWrapperIconClass = computed(() => {\n      return twJoin(\n        ui.value.icon.trailing.wrapper,\n        ui.value.icon.trailing.pointer,\n        ui.value.icon.trailing.padding[size.value]\n      )\n    })\n\n    const trailingIconClass = computed(() => {\n      return twJoin(\n        ui.value.icon.base,\n        color.value && ui.value.icon.color.replaceAll('{color}', color.value),\n        ui.value.icon.size[size.value],\n        props.loading && !isLeading.value && ui.value.icon.loading\n      )\n    })\n\n    const debouncedSearch = props.searchable && typeof props.searchable === 'function' ? useDebounceFn(props.searchable, props.debounce) : undefined\n\n    const options = computedAsync(async () => {\n      if (debouncedSearch) {\n        return await debouncedSearch(query.value)\n      }\n\n      return props.options || []\n    }, [], {\n      lazy: props.searchableLazy\n    })\n\n    const filteredOptions = computed(() => {\n      if (!query.value || debouncedSearch) {\n        return options.value\n      }\n\n      return options.value.filter((option: any) => {\n        return (props.searchAttributes?.length ? props.searchAttributes : [props.optionAttribute]).some((searchAttribute: any) => {\n          if (['string', 'number'].includes(typeof option)) {\n            return String(option).search(new RegExp(query.value, 'i')) !== -1\n          }\n\n          const child = get(option, searchAttribute)\n\n          return child !== null && child !== undefined && String(child).search(new RegExp(query.value, 'i')) !== -1\n        })\n      })\n    })\n\n    const createOption = computed(() => {\n      if (query.value === '') {\n        return null\n      }\n      if (props.showCreateOptionWhen === 'empty' && filteredOptions.value.length) {\n        return null\n      }\n      if (props.showCreateOptionWhen === 'always') {\n        const existingOption = filteredOptions.value.find(option => ['string', 'number'].includes(typeof option) ? option === query.value : option[props.optionAttribute] === query.value)\n        if (existingOption) {\n          return null\n        }\n      }\n      if (typeof props.showCreateOptionWhen === 'function') {\n        if (!props.showCreateOptionWhen(query.value, filteredOptions.value)) {\n          return null\n        }\n      }\n      return ['string', 'number'].includes(typeof props.modelValue) ? query.value : { [props.optionAttribute]: query.value }\n    })\n\n    function clearOnClose () {\n      if (props.clearSearchOnClose) {\n        query.value = ''\n      }\n    }\n\n    // watch(container, (value) => {\n    //   if (value) {\n    //     emit('open')\n    //   } else {\n    //     clearOnClose()\n    //     emit('close')\n    //     emitFormBlur()\n    //   }\n    // })\n\n    function onUpdate (value: any) {\n      emit('update:modelValue', value)\n      emit('change', value)\n      emitFormChange()\n    }\n\n    function onQueryChange (event: any) {\n      query.value = event.target.value\n    }\n\n    provideUseId(() => useId())\n\n    return {\n      ui,\n      attrs,\n      // eslint-disable-next-line vue/no-dupe-keys\n      name,\n      inputId,\n      // eslint-disable-next-line vue/no-dupe-keys\n      // popper,\n      // trigger,\n      // container,\n      label,\n      isLeading,\n      isTrailing,\n      // eslint-disable-next-line vue/no-dupe-keys\n      selectClass,\n      leadingIconName,\n      leadingIconClass,\n      leadingWrapperIconClass,\n      trailingIconName,\n      trailingIconClass,\n      trailingWrapperIconClass,\n      filteredOptions,\n      createOption,\n      // eslint-disable-next-line vue/no-dupe-keys\n      query,\n      onUpdate,\n      onQueryChange\n    }\n  }\n})\n</script>"
  },
  {
    "path": "resources/js/Components/Form/Select.vue",
    "content": "<template>\n    <div :class=\"ui.wrapper\">\n        <select\n            :id=\"inputId\"\n            :name=\"name\"\n            :value=\"modelValue\"\n            :required=\"required\"\n            :disabled=\"disabled\"\n            :class=\"selectClass\"\n            v-bind=\"attrs\"\n            @input=\"onInput\"\n            @change=\"onChange\"\n        >\n            <template\n                v-for=\"(option, index) in normalizedOptionsWithPlaceholder\"\n            >\n                <optgroup\n                    v-if=\"option.children\"\n                    :key=\"`${option[valueAttribute]}-optgroup-${index}`\"\n                    :value=\"option[valueAttribute]\"\n                    :label=\"option[optionAttribute]\"\n                >\n                    <option\n                        v-for=\"(childOption, index2) in option.children\"\n                        :key=\"`${childOption[valueAttribute]}-${index}-${index2}`\"\n                        :value=\"childOption[valueAttribute]\"\n                        :selected=\"\n                            childOption[valueAttribute] === normalizedValue\n                        \"\n                        :disabled=\"childOption.disabled\"\n                        v-text=\"childOption[optionAttribute]\"\n                    />\n                </optgroup>\n                <option\n                    v-else\n                    :key=\"`${option[valueAttribute]}-${index}`\"\n                    :value=\"option[valueAttribute]\"\n                    :selected=\"option[valueAttribute] === normalizedValue\"\n                    :disabled=\"option.disabled\"\n                    v-text=\"option[optionAttribute]\"\n                />\n            </template>\n        </select>\n\n        <span\n            v-if=\"(isLeading && leadingIconName) || $slots.leading\"\n            :class=\"leadingWrapperIconClass\"\n        >\n            <slot name=\"leading\" :disabled=\"disabled\" :loading=\"loading\">\n                <Icon :name=\"loadingIcon\" type=\"custom\" :class=\"leadingIconClass\" />\n            </slot>\n        </span>\n\n        <span\n            v-if=\"(isTrailing && trailingIconName) || $slots.trailing\"\n            :class=\"trailingWrapperIconClass\"\n        >\n            <slot name=\"trailing\" :disabled=\"disabled\" :loading=\"loading\">\n                <Icon\n                    :name=\"trailingIconName\"\n                    :class=\"trailingIconClass\"\n                    aria-hidden=\"true\"\n                />\n            </slot>\n        </span>\n    </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, toRef, defineComponent } from \"vue\";\nimport type { PropType, ComputedRef } from \"vue\";\nimport { twMerge, twJoin } from \"tailwind-merge\";\nimport Icon  from \"@/Components/Icon.vue\";\nimport { useUI } from \"@/Composables/useUI\";\nimport { useFormGroup } from \"@/Composables/useFormGroup\";\nimport { mergeConfig, get } from \"@/Composables/utils\";\nimport { useInjectButtonGroup } from \"@/Composables/useButtonGroup\";\nimport type { CustomIconName, IconName, Strategy } from '@/types'\n \n\nconst config = {\n    wrapper: \"relative\",\n    base: \"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0\",\n    form: \"form-select\",\n    placeholder: \"text-gray-400 dark:text-gray-500\",\n    rounded: \"rounded-md\",\n    file: {\n        base: \"file:mr-1.5 file:font-medium file:text-gray-500 dark:file:text-gray-400 file:bg-transparent file:border-0 file:p-0 file:outline-none\",\n    },\n    size: {\n        \"2xs\": \"text-xs\",\n        xs: \"text-xs\",\n        sm: \"text-sm\",\n        md: \"text-md\",\n        lg: \"text-lg\",\n        xl: \"text-base\",\n    },\n    gap: {\n        \"2xs\": \"gap-x-1\",\n        xs: \"gap-x-1.5\",\n        sm: \"gap-x-1.5\",\n        md: \"gap-x-2\",\n        lg: \"gap-x-2.5\",\n        xl: \"gap-x-2.5\",\n    },\n    padding: {\n        \"2xs\": \"px-2 py-1\",\n        xs: \"px-2.5 py-1.5\",\n        sm: \"px-2.5 py-1.5\",\n        md: \"px-3 py-2\",\n        lg: \"px-3.5 py-2.5\",\n        xl: \"px-3.5 py-2.5\",\n    },\n    leading: {\n        padding: {\n            \"2xs\": \"ps-7\",\n            xs: \"ps-8\",\n            sm: \"ps-9\",\n            md: \"ps-10\",\n            lg: \"ps-11\",\n            xl: \"ps-12\",\n        },\n    },\n    trailing: {\n        padding: {\n            \"2xs\": \"pe-7\",\n            xs: \"pe-8\",\n            sm: \"pe-9\",\n            md: \"pe-10\",\n            lg: \"pe-11\",\n            xl: \"pe-12\",\n        },\n    },\n    color: {\n        white: {\n            outline:\n                \"shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400\",\n        },\n        gray: {\n            outline:\n                \"shadow-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400\",\n        },\n    },\n    variant: {\n        outline:\n            \"shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-{color}-500 dark:ring-{color}-400 focus:ring-2 focus:ring-{color}-500 dark:focus:ring-{color}-400\",\n        none: \"bg-transparent focus:ring-0 focus:shadow-none\",\n    },\n    icon: {\n        base: \"flex-shrink-0 text-gray-400 dark:text-gray-500\",\n        color: \"text-{color}-500 dark:text-{color}-400\",\n        loading: \"animate-spin\",\n        size: {\n            \"2xs\": \"h-4 w-4\",\n            xs: \"h-4 w-4\",\n            sm: \"h-5 w-5\",\n            md: \"h-5 w-5\",\n            lg: \"h-5 w-5\",\n            xl: \"h-6 w-6\",\n        },\n        leading: {\n            wrapper: \"absolute inset-y-0 start-0 flex items-center\",\n            pointer: \"pointer-events-none\",\n            padding: {\n                \"2xs\": \"px-2\",\n                xs: \"px-2.5\",\n                sm: \"px-2.5\",\n                md: \"px-3\",\n                lg: \"px-3.5\",\n                xl: \"px-3.5\",\n            },\n        },\n        trailing: {\n            wrapper: \"absolute inset-y-0 end-0 flex items-center\",\n            pointer: \"pointer-events-none\",\n            padding: {\n                \"2xs\": \"px-2\",\n                xs: \"px-2.5\",\n                sm: \"px-2.5\",\n                md: \"px-3\",\n                lg: \"px-3.5\",\n                xl: \"px-3.5\",\n            },\n        },\n    },\n    default: {\n        size: \"md\",\n        color: \"blue\",\n        variant: \"outline\",\n        loadingIcon: \"LoadingIcon\",\n        trailingIcon: \"ArrowDownOnSquareIcon\",\n    },\n};\n\n type SelectSize = keyof typeof config.size \n type SelectColor = keyof typeof config.color \n type SelectVariant = keyof typeof config.variant \n\nexport default defineComponent({\n    components: {\n        Icon,\n    },      \n    inheritAttrs: false,\n    props: {\n        modelValue: {\n            type: [String, Number, Object],\n            default: \"\",\n        },\n        id: {\n            type: String,\n            default: null,\n        },\n        name: {\n            type: String,\n            default: null,\n        },\n        placeholder: {\n            type: String,\n            default: null,\n        },\n        required: {\n            type: Boolean,\n            default: false,\n        },\n        disabled: {\n            type: Boolean,\n            default: false,\n        },\n        icon: {\n            type: String as PropType<IconName>,\n            default: null,\n        },\n        loadingIcon: {\n            type: String as PropType<CustomIconName>,\n            default: () => config.default.loadingIcon,\n        },\n        leadingIcon: {\n            type: String,\n            default: null,\n        },\n        trailingIcon: {\n            type: String as PropType<IconName>,\n            default: () => config.default.trailingIcon,\n        },\n        trailing: {\n            type: Boolean,\n            default: false,\n        },\n        leading: {\n            type: Boolean,\n            default: false,\n        },\n        loading: {\n            type: Boolean,\n            default: false,\n        },\n        padded: {\n            type: Boolean,\n            default: true,\n        },\n        options: {\n            type: Array,\n            default: () => [],\n        },\n        size: {\n            type: String as PropType<SelectSize>,\n            default: config.default.size,\n            validator(value: string) {\n                return Object.keys(config.size).includes(value);\n            },\n        },\n        color: {\n            type: String as PropType<SelectColor>,\n            default: () => config.default.color,\n            validator(value: string) {\n                return [\n                    ...Object.keys(config.color),\n                ].includes(value);\n            },\n        },\n        variant: {\n            type: String as PropType<SelectVariant>,\n            default: () => config.default.variant,\n            validator(value: string) {\n                return [\n                    ...Object.keys(config.variant),\n                    ...Object.values(config.color).flatMap((value) =>\n                        Object.keys(value)\n                    ),\n                ].includes(value);\n            },\n        },\n        optionAttribute: {\n            type: String,\n            default: \"label\",\n        },\n        valueAttribute: {\n            type: String,\n            default: \"value\",\n        },\n        selectClass: {\n            type: String,\n            default: null,\n        },\n        class: {\n            type: [String, Object, Array] as PropType<any>,\n            default: () => \"\",\n        },\n        ui: {\n            type: Object as PropType<\n                Partial<typeof config> & { strategy?: Strategy }\n            >,\n            default: () => ({}),\n        },\n    },\n    emits: [\"update:modelValue\", \"change\"],\n    setup(props, { emit, slots }) {\n        const { ui, attrs } = useUI(\n            \"select\",\n            toRef(props, \"ui\"),\n            config,\n            toRef(props, \"class\")\n        );\n\n        const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({\n            ui,\n            props,\n        });\n\n        const {\n            emitFormChange,\n            inputId,\n            color,\n            size: sizeFormGroup,\n            name,\n        } = useFormGroup(props, config);\n\n        const size = computed(\n            () => sizeButtonGroup.value ?? sizeFormGroup.value\n        );\n\n        const onInput = (event: Event) => {\n            emit(\"update:modelValue\", (event.target as HTMLInputElement).value);\n        };\n\n        const onChange = (event: Event) => {\n            emit(\"change\", (event.target as HTMLInputElement).value);\n            emitFormChange();\n        };\n\n        const guessOptionValue = (option: any) => {\n            return get(option, props.valueAttribute, \"\");\n        };\n\n        const guessOptionText = (option: any) => {\n            return get(option, props.optionAttribute, \"\");\n        };\n\n        const normalizeOption = (option: any) => {\n            if ([\"string\", \"number\", \"boolean\"].includes(typeof option)) {\n                return {\n                    [props.valueAttribute]: option,\n                    [props.optionAttribute]: option,\n                };\n            }\n\n            return {\n                ...option,\n                [props.valueAttribute]: guessOptionValue(option),\n                [props.optionAttribute]: guessOptionText(option),\n            };\n        };\n\n        const normalizedOptions = computed(() => {\n            return props.options.map((option) => normalizeOption(option));\n        });\n\n        const normalizedOptionsWithPlaceholder: ComputedRef<\n            { disabled?: boolean; children: { disabled?: boolean }[] }[]\n        > = computed(() => {\n            if (!props.placeholder) {\n                return normalizedOptions.value;\n            }\n\n            return [\n                {\n                    [props.valueAttribute]: \"\",\n                    [props.optionAttribute]: props.placeholder,\n                    disabled: true,\n                },\n                ...normalizedOptions.value,\n            ];\n        });\n\n        const normalizedValue = computed(() => {\n            const normalizeModelValue = normalizeOption(props.modelValue);\n            const foundOption = normalizedOptionsWithPlaceholder.value.find(\n                (option) =>\n                    option[props.valueAttribute] ===\n                    normalizeModelValue[props.valueAttribute]\n            );\n            if (!foundOption) {\n                return \"\";\n            }\n\n            return foundOption[props.valueAttribute];\n        });\n\n        const selectClass = computed(() => {\n            const variant =\n                ui.value.color?.[color.value as string]?.[\n                    props.variant as string\n                ] || ui.value.variant[props.variant];\n\n            return twMerge(\n                twJoin(\n                    ui.value.base,\n                    ui.value.form,\n                    rounded.value,\n                    ui.value.size[size.value],\n                    props.padded ? ui.value.padding[size.value] : \"p-0\",\n                    variant?.replaceAll(\"{color}\", color.value),\n                    (isLeading.value || slots.leading) &&\n                        ui.value.leading.padding[size.value],\n                    (isTrailing.value || slots.trailing) &&\n                        ui.value.trailing.padding[size.value]\n                ),\n                props.placeholder && !props.modelValue && ui.value.placeholder,\n                props.selectClass\n            );\n        });\n\n        const isLeading = computed(() => {\n            return (\n                (props.icon && props.leading) ||\n                (props.icon && !props.trailing) ||\n                (props.loading && !props.trailing) ||\n                props.leadingIcon\n            );\n        });\n\n        const isTrailing = computed(() => {\n            return (\n                (props.icon && props.trailing) ||\n                (props.loading && props.trailing) ||\n                props.trailingIcon\n            );\n        });\n\n        const leadingIconName = computed(() => {\n            if (props.loading) {\n                return props.loadingIcon;\n            }\n\n            return props.leadingIcon || props.icon;\n        });\n\n        const trailingIconName = computed<IconName>(() => {\n            if (props.loading && !isLeading.value) {\n                return props.loadingIcon;\n            }\n\n            return props.trailingIcon || props.icon;\n        });\n\n        const leadingWrapperIconClass = computed(() => {\n            return twJoin(\n                ui.value.icon.leading.wrapper,\n                ui.value.icon.leading.pointer,\n                ui.value.icon.leading.padding[size.value]\n            );\n        });\n\n        const leadingIconClass = computed(() => {\n            return twJoin(\n                ui.value.icon.base,\n                color.value &&\n                    ui.value.icon.color.replaceAll(\"{color}\", color.value),\n                ui.value.icon.size[size.value],\n                props.loading && ui.value.icon.loading\n            );\n        });\n\n        const trailingWrapperIconClass = computed(() => {\n            return twJoin(\n                ui.value.icon.trailing.wrapper,\n                ui.value.icon.trailing.pointer,\n                ui.value.icon.trailing.padding[size.value]\n            );\n        });\n\n        const trailingIconClass = computed(() => {\n            return twJoin(\n                ui.value.icon.base,\n                color.value &&\n                    ui.value.icon.color.replaceAll(\"{color}\", color.value),\n                ui.value.icon.size[size.value],\n                props.loading && !isLeading.value && ui.value.icon.loading\n            );\n        });\n\n        return {\n            // eslint-disable-next-line vue/no-dupe-keys\n            ui,\n            attrs,\n            // eslint-disable-next-line vue/no-dupe-keys\n            name,\n            inputId,\n            normalizedOptionsWithPlaceholder,\n            normalizedValue,\n            isLeading,\n            isTrailing,\n            // eslint-disable-next-line vue/no-dupe-keys\n            selectClass,\n            leadingIconName,\n            leadingIconClass,\n            leadingWrapperIconClass,\n            trailingIconName,\n            trailingIconClass,\n            trailingWrapperIconClass,\n            onInput,\n            onChange,\n        };\n    },\n});\n</script>\n\n<style scoped>\n.form-select {\n    background-image: none;\n}\n</style>\n"
  },
  {
    "path": "resources/js/Components/Icon.vue",
    "content": "<template>\n    <component :is=\"component\" v-bind=\"attrs\"/>\n</template>\n\n<script lang=\"ts\" setup>\nimport { Component, useAttrs } from \"vue\";\nimport { HeroIconName, CustomIconName } from \"@/types\";\nimport * as solid from \"@heroicons/vue/24/solid\";\nimport * as Custom from '@/Components/Icons/index'\n\ninterface Props {\n    name: HeroIconName | CustomIconName;\n    type?: \"solid\" | \"outline\" | \"custom\";\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n    name: \"ExclamationCircleIcon\",\n    type: \"solid\",\n});\n\nconst component = solid[props.name] ? solid[props.name] : Custom[props.name];\n\nconst attrs = useAttrs();\n</script>\n"
  },
  {
    "path": "resources/js/Components/Icons/LoadingIcon.vue",
    "content": "<template>\n    <div role=\"status\">\n        <svg aria-hidden=\"true\" class=\"w-8 h-8 text-gray-200 animate-spin dark:text-gray-600\"  viewBox=\"0 0 100 101\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n            <path d=\"M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z\" fill=\"currentColor\"/>\n            <path d=\"M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z\" fill=\"currentFill\"/>\n        </svg>\n        <span class=\"sr-only\">Loading...</span>\n    </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { defineComponent } from 'vue'\n\nconst props = withDefaults(defineProps(), {\n    fill: 'fill-blue-500'\n}) \n\n</script>"
  },
  {
    "path": "resources/js/Components/Icons/index.ts",
    "content": "export { default as LoadingIcon } from './LoadingIcon.vue'"
  },
  {
    "path": "resources/js/Components/Modal.vue",
    "content": "<template>\n    <TransitionRoot :appear=\"appear\" :show=\"isOpen\" as=\"template\" @after-leave=\"onAfterLeave\">\n      <HDialog :class=\"ui.wrapper\" v-bind=\"attrs\" @close=\"close\">\n        <TransitionChild v-if=\"overlay\" as=\"template\" :appear=\"appear\" v-bind=\"ui.overlay.transition\">\n          <div :class=\"[ui.overlay.base, ui.overlay.background]\" />\n        </TransitionChild>\n  \n        <div :class=\"ui.inner\">\n          <div :class=\"[ui.container, !fullscreen && ui.padding]\">\n            <TransitionChild as=\"template\" :appear=\"appear\" v-bind=\"transitionClass\">\n              <HDialogPanel\n                :class=\"[\n                  ui.base,\n                  ui.background,\n                  ui.ring,\n                  ui.shadow,\n                  fullscreen ? ui.fullscreen : [ui.width, ui.height, ui.rounded, ui.margin],\n                ]\"\n              >\n                <slot />\n              </HDialogPanel>\n            </TransitionChild>\n          </div>\n        </div>\n      </HDialog>\n    </TransitionRoot>\n  </template>\n  \n  <script lang=\"ts\">\n  import { computed, toRef, defineComponent } from 'vue'\n  import type { PropType } from 'vue'\n  import { Dialog as HDialog, DialogPanel as HDialogPanel, TransitionRoot, TransitionChild, provideUseId } from '@headlessui/vue'\n  import { useUI } from '@/Composables/useUI';\n  import type { Strategy } from '@/types';\n\n\n  \n  const config = {\n  wrapper: 'relative z-50',\n  inner: 'fixed inset-0 overflow-y-auto',\n  container: 'flex min-h-full items-end sm:items-center justify-center text-center',\n  padding: 'p-4 sm:p-0',\n  margin: 'sm:my-8',\n  base: 'relative text-left rtl:text-right flex flex-col',\n  overlay: {\n    base: 'fixed inset-0 transition-opacity',\n    background: 'bg-gray-200/75 dark:bg-gray-800/75',\n    // Syntax for `<TransitionRoot>` component https://headlessui.com/vue/transition#basic-example\n    transition: {\n      enter: 'ease-out duration-300',\n      enterFrom: 'opacity-0',\n      enterTo: 'opacity-100',\n      leave: 'ease-in duration-200',\n      leaveFrom: 'opacity-100',\n      leaveTo: 'opacity-0'\n    }\n  },\n  background: 'bg-white dark:bg-gray-900',\n  ring: '',\n  rounded: 'rounded-lg',\n  shadow: 'shadow-xl',\n  width: 'w-full sm:max-w-lg',\n  height: '',\n  fullscreen: 'w-screen h-screen',\n  // Syntax for `<TransitionRoot>` component https://headlessui.com/vue/transition#basic-example\n  transition: {\n    enter: 'ease-out duration-300',\n    enterFrom: 'opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95',\n    enterTo: 'opacity-100 translate-y-0 sm:scale-100',\n    leave: 'ease-in duration-200',\n    leaveFrom: 'opacity-100 translate-y-0 sm:scale-100',\n    leaveTo: 'opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95'\n  }\n}\n  \n  export default defineComponent({\n    components: {\n      HDialog,\n      HDialogPanel,\n      TransitionRoot,\n      TransitionChild\n    },\n    inheritAttrs: false,\n    props: {\n      modelValue: {\n        type: Boolean,\n        default: false\n      },\n      appear: {\n        type: Boolean,\n        default: false\n      },\n      overlay: {\n        type: Boolean,\n        default: true\n      },\n      transition: {\n        type: Boolean,\n        default: true\n      },\n      preventClose: {\n        type: Boolean,\n        default: false\n      },\n      fullscreen: {\n        type: Boolean,\n        default: false\n      },\n      class: {\n        type: [String, Object, Array] as PropType<any>,\n        default: () => ''\n      },\n      ui: {\n        type: Object as PropType<Partial<typeof config> & { strategy?: Strategy }>,\n        default: () => ({})\n      }\n    },\n    emits: ['update:modelValue', 'close', 'close-prevented', 'after-leave'],\n    setup (props, { emit }) {\n      const { ui, attrs } = useUI('modal', toRef(props, 'ui'), config, toRef(props, 'class'))\n  \n      const isOpen = computed({\n        get () {\n          return props.modelValue\n        },\n        set (value) {\n          emit('update:modelValue', value)\n        }\n      })\n  \n      const transitionClass = computed(() => {\n        if (!props.transition) {\n          return {}\n        }\n  \n        return {\n          ...ui.value.transition\n        }\n      })\n  \n      function close (value: boolean) {\n        if (props.preventClose) {\n          emit('close-prevented')\n  \n          return\n        }\n  \n        isOpen.value = value\n  \n        emit('close')\n      }\n  \n      const onAfterLeave = () => {\n        emit('after-leave')\n      }\n  \n    //   provideUseId(() => useId())\n  \n      return {\n        // eslint-disable-next-line vue/no-dupe-keys\n        ui,\n        attrs,\n        isOpen,\n        transitionClass,\n        onAfterLeave,\n        close\n      }\n    }\n  })\n  </script>"
  },
  {
    "path": "resources/js/Components/NavLink.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { Link } from '@inertiajs/vue3';\n\nconst props = defineProps<{\n    href: string;\n    active?: boolean;\n}>();\n\nconst classes = computed(() =>\n    props.active\n        ? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 dark:border-indigo-600 text-sm font-medium leading-5 text-gray-900 dark:text-gray-100 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'\n        : 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-700 focus:outline-none focus:text-gray-700 dark:focus:text-gray-300 focus:border-gray-300 dark:focus:border-gray-700 transition duration-150 ease-in-out'\n);\n</script>\n\n<template>\n    <Link :href=\"href\" :class=\"classes\">\n        <slot />\n    </Link>\n</template>\n"
  },
  {
    "path": "resources/js/Components/Pagination.vue",
    "content": "<template>\n    <div :class=\"ui.wrapper\" v-bind=\"attrs\">\n        <nav aria-label=\"pagination\" class=\"inline-flex -space-x-px text-sm\">\n            <Link\n                v-for=\"(page, index) of pages\"\n                :key=\"`page-${index}`\"\n                :href=\"page.url\"\n                :class=\"[\n                    buttonClass,\n                    { '!bg-blue-500 !text-white': page.active },\n                ]\"\n                v-html=\"page.label\"\n                preserve-state\n            >\n            </Link>\n        </nav>\n    </div>\n</template>\n\n<script lang=\"ts\">\nimport {\n    ChevronDoubleLeftIcon,\n    ChevronDoubleRightIcon,\n} from \"@heroicons/vue/24/outline\";\nimport { Link } from \"@inertiajs/vue3\";\nimport { computed, toRef, defineComponent } from \"vue\";\nimport type { PropType } from \"vue\";\nimport Button from \"@/Components/Button.vue\";\nimport { useUI } from \"@/Composables/useUI\";\nimport type { LaravelPagination, PaginationLink } from \"@/types\";\nimport { twMerge, twJoin } from \"tailwind-merge\";\n\nconst config = {\n    wrapper: \"flex items-center -space-x-px\",\n    base: \"flex items-center justify-center\",\n    rounded: \"first:rounded-s-md last:rounded-e-md\",\n    size: {\n        \"2xs\": \"text-xs\",\n        xs: \"text-xs\",\n        sm: \"text-sm\",\n        md: \"text-md\",\n        lg: \"text-lg\",\n        xl: \"text-base\",\n    },\n    padding: {\n        \"2xs\": \"px-2 py-1\",\n        xs: \"px-2.5 py-1.5\",\n        sm: \"px-2.5 py-1.5\",\n        md: \"px-3 py-2\",\n        lg: \"px-3.5 py-2.5\",\n        xl: \"px-3.5 py-2.5\",\n    },\n    color: \"text-gray-500 bg-white border border-e-0 border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white\",\n    default: {\n        size: \"sm\",\n    },\n};\n\n// flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white\n\nexport default defineComponent({\n    components: {\n        Button,\n        ChevronDoubleLeftIcon,\n        ChevronDoubleRightIcon,\n        Link,\n    },\n    inheritAttrs: false,\n    props: {\n        paginate: {\n            type: Object as PropType<LaravelPagination>,\n            required: true,\n        },\n        pagename: {\n            type: String,\n            default: () => \"page\",\n        },\n        max: {\n            type: Number,\n            default: 7,\n            validate(value) {\n                return value >= 5 && value < Number.MAX_VALUE;\n            },\n        },\n\n        size: {\n            type: String,\n            default: () => config.default.size,\n            validator(value: string) {\n                return Object.keys(config.size).includes(value);\n            },\n        },\n        showFirst: {\n            type: Boolean,\n            default: false,\n        },\n        showLast: {\n            type: Boolean,\n            default: false,\n        },\n        divider: {\n            type: String,\n            default: \"…\",\n        },\n        class: {\n            type: [String, Object, Array] as PropType<any>,\n            default: () => \"\",\n        },\n        ui: {\n            type: Object as PropType<Partial<typeof config>>,\n            default: () => ({}),\n        },\n    },\n    emits: [\"update:modelValue\"],\n    setup(props, { emit }) {\n        const { ui, attrs } = useUI(\n            \"pagination\",\n            toRef(props, \"ui\"),\n            config,\n            toRef(props, \"class\")\n        );\n\n        const currentPage = computed({\n            get() {\n                return props.paginate.current_page;\n            },\n            set(value) {\n                emit(\"update:modelValue\", value);\n            },\n        });\n\n        const pages = computed(() => props.paginate.links);\n\n        const buttonClass = computed(() => {\n            return twMerge(\n                twJoin(\n                    ui.value.base,\n                    ui.value.rounded,\n                    ui.value.size[props.size],\n                    ui.value.padding[props.size],\n                    ui.value.color\n                ),\n                props.class\n            );\n        });\n\n        const canGoFirstOrPrev = computed(() => currentPage.value > 1);\n        const canGoLastOrNext = computed(\n            () => currentPage.value < pages.value.length\n        );\n\n        function onClickFirst() {\n            if (!canGoFirstOrPrev.value) {\n                return;\n            }\n\n            currentPage.value = 1;\n        }\n\n        function onClickLast() {\n            if (!canGoLastOrNext.value) {\n                return;\n            }\n\n            currentPage.value = pages.value.length;\n        }\n\n        function onClickPage(page: number | string) {\n            if (typeof page === \"string\") {\n                return;\n            }\n\n            currentPage.value = page;\n        }\n\n        function onClickPrev() {\n            if (!canGoFirstOrPrev.value) {\n                return;\n            }\n\n            currentPage.value--;\n        }\n\n        function onClickNext() {\n            if (!canGoLastOrNext.value) {\n                return;\n            }\n\n            currentPage.value++;\n        }\n\n        return {\n            // eslint-disable-next-line vue/no-dupe-keys\n            ui,\n            attrs,\n            buttonClass,\n            currentPage,\n            pages,\n            canGoLastOrNext,\n            canGoFirstOrPrev,\n            onClickPrev,\n            onClickNext,\n            onClickPage,\n            onClickFirst,\n            onClickLast,\n        };\n    },\n});\n</script>\n"
  },
  {
    "path": "resources/js/Components/ResponsiveNavLink.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { Link } from '@inertiajs/vue3';\n\nconst props = defineProps<{\n    href: string;\n    active?: boolean;\n}>();\n\nconst classes = computed(() =>\n    props.active\n        ? 'block w-full ps-3 pe-4 py-2 border-l-4 border-indigo-400 dark:border-indigo-600 text-start text-base font-medium text-indigo-700 dark:text-indigo-300 bg-indigo-50 dark:bg-indigo-900/50 focus:outline-none focus:text-indigo-800 dark:focus:text-indigo-200 focus:bg-indigo-100 dark:focus:bg-indigo-900 focus:border-indigo-700 dark:focus:border-indigo-300 transition duration-150 ease-in-out'\n        : 'block w-full ps-3 pe-4 py-2 border-l-4 border-transparent text-start text-base font-medium text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:outline-none focus:text-gray-800 dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600 transition duration-150 ease-in-out'\n);\n</script>\n\n<template>\n    <Link :href=\"href\" :class=\"classes\">\n        <slot />\n    </Link>\n</template>\n"
  },
  {
    "path": "resources/js/Components/SocialiteLogins.vue",
    "content": "<template>\n    <div id=\"\" class=\"flex flex-wrap justify-around\">\n        dslk;fjdlk;j\n        <Link :href=\"route('oauth', {driver: 'facebook'})\">\n            Facebook\n        </Link>\n    </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport { Link } from \"@inertiajs/vue3\";\nimport Icon from '@/Components/Icon.vue'\n\nexport default defineComponent({\n    components: {\n        Link,\n        Icon\n    },\n    setup() {\n    \n\n    }\n})\n\n</script>"
  },
  {
    "path": "resources/js/Components/Tabs.vue",
    "content": "<template>\n    <HTabGroup\n        :vertical=\"orientation === 'vertical'\"\n        :selected-index=\"selectedIndex\"\n        as=\"div\"\n        :class=\"ui.wrapper\"\n        v-bind=\"attrs\"\n        @change=\"onChange\"\n    >\n        <HTabList\n            ref=\"listRef\"\n            :class=\"[\n                ui.list.base,\n                ui.list.background,\n                ui.list.rounded,\n                ui.list.shadow,\n                ui.list.padding,\n                ui.list.width,\n                orientation === 'horizontal' && ui.list.height,\n                orientation === 'horizontal' && 'inline-grid items-center',\n            ]\"\n            :style=\"[\n                orientation === 'horizontal' &&\n                    `grid-template-columns: repeat(${items.length}, minmax(0, 1fr))`,\n            ]\"\n        >\n            <div ref=\"markerRef\" :class=\"ui.list.marker.wrapper\">\n                <div\n                    :class=\"[\n                        ui.list.marker.base,\n                        ui.list.marker.background,\n                        ui.list.marker.rounded,\n                        ui.list.marker.shadow,\n                    ]\"\n                />\n            </div>\n\n            <HTab\n                v-for=\"(item, index) of items\"\n                :key=\"index\"\n                ref=\"itemRefs\"\n                v-slot=\"{ selected, disabled }\"\n                :disabled=\"item.disabled\"\n                as=\"template\"\n            >\n                <button\n                    :class=\"[\n                        ui.list.tab.base,\n                        ui.list.tab.background,\n                        ui.list.tab.height,\n                        ui.list.tab.padding,\n                        ui.list.tab.size,\n                        ui.list.tab.font,\n                        ui.list.tab.rounded,\n                        ui.list.tab.shadow,\n                        selected ? ui.list.tab.active : ui.list.tab.inactive,\n                    ]\"\n                >\n                    <slot\n                        name=\"icon\"\n                        :item=\"item\"\n                        :index=\"index\"\n                        :selected=\"selected\"\n                        :disabled=\"disabled\"\n                    >\n                        <UIcon\n                            v-if=\"item.icon\"\n                            :name=\"item.icon\"\n                            :class=\"ui.list.tab.icon\"\n                        />\n                    </slot>\n\n                    <slot\n                        :item=\"item\"\n                        :index=\"index\"\n                        :selected=\"selected\"\n                        :disabled=\"disabled\"\n                    >\n                        <span class=\"truncate\">{{ item.label }}</span>\n                    </slot>\n                </button>\n            </HTab>\n        </HTabList>\n\n        <HTabPanels v-if=\"content\" :class=\"ui.container\">\n            <HTabPanel\n                v-for=\"(item, index) of items\"\n                :key=\"index\"\n                v-slot=\"{ selected }\"\n                :class=\"ui.base\"\n                :unmount=\"unmount\"\n            >\n                <slot\n                    :name=\"item.slot || 'item'\"\n                    :item=\"item\"\n                    :index=\"index\"\n                    :selected=\"selected\"\n                >\n                    {{ item.content }}\n                </slot>\n            </HTabPanel>\n        </HTabPanels>\n    </HTabGroup>\n</template>\n\n<script lang=\"ts\">\nimport { toRef, ref, watch, onMounted, defineComponent } from \"vue\";\nimport type { PropType } from \"vue\";\nimport {\n    TabGroup as HTabGroup,\n    TabList as HTabList,\n    Tab as HTab,\n    TabPanels as HTabPanels,\n    TabPanel as HTabPanel,\n    provideUseId,\n} from \"@headlessui/vue\";\nimport { useResizeObserver } from \"@vueuse/core\";\nimport { useUI } from \"@/Composables/useUI\";\nimport { useId } from \"@/Composables/utils\";\n\nconst config = {\n    wrapper: \"relative space-y-2\",\n    container: \"relative w-full\",\n    base: \"focus:outline-none\",\n    list: {\n        base: \"relative\",\n        background: \"bg-gray-100 dark:bg-gray-800\",\n        rounded: \"rounded-lg\",\n        shadow: \"\",\n        padding: \"p-1\",\n        height: \"h-10\",\n        width: \"w-full\",\n        marker: {\n            wrapper:\n                \"absolute top-[4px] left-[4px] duration-200 ease-out focus:outline-none\",\n            base: \"w-full h-full\",\n            background: \"bg-white dark:bg-gray-900\",\n            rounded: \"rounded-md\",\n            shadow: \"shadow-sm\",\n        },\n        tab: {\n            base: \"relative inline-flex items-center justify-center flex-shrink-0 w-full ui-focus-visible:outline-0 ui-focus-visible:ring-2 ui-focus-visible:ring-primary-500 dark:ui-focus-visible:ring-primary-400 ui-not-focus-visible:outline-none focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 transition-colors duration-200 ease-out\",\n            background: \"\",\n            active: \"text-gray-900 dark:text-white\",\n            inactive: \"text-gray-500 dark:text-gray-400\",\n            height: \"h-20\",\n            padding: \"px-3 py-5\",\n            size: \"text-md\",\n            font: \"font-medium\",\n            rounded: \"rounded-md\",\n            shadow: \"\",\n            icon: \"w-4 h-4 flex-shrink-0 mr-2\",\n        },\n    },\n};\n\ninterface TabItem {\n    label: string;\n    icon?: string;\n    slot?: string;\n    disabled?: boolean;\n    content?: string;\n    [key: string]: any;\n}\n\nexport default defineComponent({\n    components: {\n        HTabGroup,\n        HTabList,\n        HTab,\n        HTabPanels,\n        HTabPanel,\n    },\n    inheritAttrs: false,\n    props: {\n        modelValue: {\n            type: Number,\n            default: undefined,\n        },\n        orientation: {\n            type: String as PropType<\"horizontal\" | \"vertical\">,\n            default: \"horizontal\",\n            validator: (value: string) =>\n                [\"horizontal\", \"vertical\"].includes(value),\n        },\n        defaultIndex: {\n            type: Number,\n            default: 0,\n        },\n        items: {\n            type: Array as PropType<TabItem[]>,\n            default: () => [],\n        },\n        unmount: {\n            type: Boolean,\n            default: false,\n        },\n        content: {\n            type: Boolean,\n            default: true,\n        },\n        class: {\n            type: [String, Object, Array] as PropType<any>,\n            default: () => \"\",\n        },\n        ui: {\n            type: Object as PropType<\n                Partial<typeof config>\n            >,\n            default: () => ({}),\n        },\n    },\n    emits: [\"update:modelValue\", \"change\"],\n    setup(props, { emit }) {\n        const { ui, attrs } = useUI(\n            \"tabs\",\n            toRef(props, \"ui\"),\n            config,\n            toRef(props, \"class\")\n        );\n\n        const listRef = ref<HTMLElement>();\n        const itemRefs = ref<HTMLElement[]>([]);\n        const markerRef = ref<HTMLElement>();\n\n        const selectedIndex = ref<number | undefined>(\n            props.modelValue || props.defaultIndex\n        );\n\n        // Methods\n\n        function calcMarkerSize(index: number | undefined) {\n            // @ts-ignore\n            const tab = itemRefs.value[index]?.$el;\n            if (!tab) {\n                return;\n            }\n\n            if (!markerRef.value) {\n                return;\n            }\n\n            markerRef.value.style.top = `${tab.offsetTop}px`;\n            markerRef.value.style.left = `${tab.offsetLeft}px`;\n            markerRef.value.style.width = `${tab.offsetWidth}px`;\n            markerRef.value.style.height = `${tab.offsetHeight}px`;\n        }\n\n        function onChange(index: number) {\n            selectedIndex.value = index;\n\n            emit(\"change\", index);\n\n            if (props.modelValue !== undefined) {\n                emit(\"update:modelValue\", selectedIndex.value);\n            }\n\n            calcMarkerSize(selectedIndex.value);\n        }\n\n        useResizeObserver(listRef, () => {\n            calcMarkerSize(selectedIndex.value);\n        });\n\n        watch(\n            () => props.modelValue,\n            (value) => {\n                selectedIndex.value = value;\n\n                calcMarkerSize(selectedIndex.value);\n            }\n        );\n\n        onMounted(() => calcMarkerSize(selectedIndex.value));\n\n        provideUseId(() => useId());\n\n        return {\n            // eslint-disable-next-line vue/no-dupe-keys\n            ui,\n            attrs,\n            listRef,\n            itemRefs,\n            markerRef,\n            selectedIndex,\n            onChange,\n        };\n    },\n});\n</script>\n"
  },
  {
    "path": "resources/js/Composables/analytics.js",
    "content": "/* eslint-disable */\n\n// import { track } from '@services/analytics';\nexport function track(\n  action,\n  category = 'click event',\n  label = 'clicked',\n  value = 1,\n) {\n  let appGaEnabled = GA_ENABLED; // eslint-disable-line\n  if (appGaEnabled) {\n    this.$gtag.event(action, {\n      event_category: category,\n      event_label: label,\n      value: value,\n    });\n  }\n}\n"
  },
  {
    "path": "resources/js/Composables/common.js",
    "content": "/* eslint-disable */\nimport moment from 'moment';\n\n// import { parseDisplayDate } from '@services/common';\nexport function parseDisplayDate(date) {\n  return moment(date).format('MMM Do YYYY, h:mma');\n}\n\n// import { capitalizeFirstLetter } from '@services/common';\nexport function capitalizeFirstLetter(str) {\n  if (!str) return '';\n\n  var firstCodeUnit = str[0];\n\n  if (firstCodeUnit < '\\uD800' || firstCodeUnit > '\\uDFFF') {\n    return str[0].toUpperCase() + str.slice(1);\n  }\n\n  return str.slice(0, 2).toUpperCase() + str.slice(2);\n}\n\nexport function greeting() {\n  const date = new Date();\n  const currentTime = date.getHours();\n  let greeting;\n  if (currentTime >= 0 && currentTime <= 12) {\n    greeting = 'Good Morning';\n  } else if (currentTime > 12 && currentTime <= 18) {\n    greeting = 'Good Afternoon';\n  } else {\n    greeting = 'Good Evening';\n  }\n  return greeting;\n}\n\nexport function providerIcon(provider = null) {\n  if (provider.toLowerCase() == 'apple') {\n    return 'fa-brands fa-apple text-gray-800 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'twitter') {\n    return 'fa-brands fa-twitter text-blue-300 dark:text-blue-200';\n  }\n  if (provider.toLowerCase() == 'google') {\n    return 'fa-brands fa-google text-red-500 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'microsoft') {\n    return 'fa-brands fa-microsoft text-blue-300 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'tiktok') {\n    return 'fa-brands fa-tiktok text-pink-600 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'youtube') {\n    return 'fa-brands fa-youtube text-red-600 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'instagram') {\n    return 'fa-brands fa-instagram text-gray-800 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'facebook') {\n    return 'fa-brands fa-facebook text-blue-600 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'github') {\n    return 'fa-brands fa-github text-gray-700 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'twitch') {\n    return 'fa-brands fa-twitch text-blue-300 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'linkedin') {\n    return 'fa-brands fa-linkedin text-blue-900 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'zoho') {\n    return 'fas fa-z text-yellow-500 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'stackexchange') {\n    return 'fa-brands fa-stack-exchange text-blue-400 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'gitlab') {\n    return 'fa-brands fa-square-gitlab text-orange-400 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'reddit') {\n    return 'fa-brands fa-square-reddit text-orange-700 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'snapchat') {\n    return 'fa-brands fa-square-snapchat text-yellow-400 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'meetup') {\n    return 'fa-brands fa-meetup text-red-400 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'bitbucket') {\n    return 'fa-brands fa-bitbucket text-blue-800 dark:text-gray-200';\n  }\n  if (provider.toLowerCase() == 'atlassian') {\n    return 'fa-brands fa-atlassian text-blue-800 dark:text-gray-200';\n  }\n\n  // NEW_PROVIDER_PLUG :: Put New Provider HERE\n\n  return 'fa-solid fa-plug-circle-check text-gray-600 dark:text-gray-200';\n}\n"
  },
  {
    "path": "resources/js/Composables/useAuth.ts",
    "content": "import { usePage } from \"@inertiajs/vue3\";\nimport { User } from \"@/types\";\n\nexport default function useAuth() {\n     const user: User = usePage().props.auth.user;\n\n     return {\n          user,\n          authenticated: !! user,\n          roles: {\n               superAdmin: true,\n               admin: true,\n               moderator: false,\n               editor: false,\n               user: false,\n          },\n     }\n}"
  },
  {
    "path": "resources/js/Composables/useButtonGroup.ts",
    "content": "import { computed, ref, provide, inject, onMounted, onUnmounted, getCurrentInstance } from 'vue'\nimport type { Ref, ComponentInternalInstance } from 'vue'\nimport { buttonGroup } from '@/ui.config'\n\ntype ButtonGroupProps = {\n  orientation?: Ref<'horizontal' | 'vertical'>\n  size?: Ref<string>\n  ui?: Ref<Partial<typeof buttonGroup>>\n  rounded?: Ref<{ start: string, end: string }>\n}\n\n// make a ButtonGroupContext type for injection. Should include ButtonGroupProps\ntype ButtonGroupContext = {\n  children: ComponentInternalInstance[]\n  register (child: ComponentInternalInstance): void\n  unregister (child: ComponentInternalInstance): void\n  orientation: 'horizontal' | 'vertical'\n  size: string\n  ui: Partial<typeof buttonGroup>\n  rounded: { start: string, end: string }\n}\n\nexport function useProvideButtonGroup (buttonGroupProps: ButtonGroupProps) {\n  const instance = getCurrentInstance()\n  const groupKey = `group-${instance?.uid}`\n  const state = ref({\n    children : [] as ComponentInternalInstance[],\n    register (child: ComponentInternalInstance) {\n      this.children.push(child)\n    },\n    unregister (child: ComponentInternalInstance) {\n      const index = this.children.indexOf(child)\n      if (index > -1) {\n        this.children.splice(index, 1)\n      }\n    },\n    ...buttonGroupProps\n  })\n  provide(groupKey, state as Ref<ButtonGroupContext>)\n}\n\nexport function useInjectButtonGroup ({ ui, props }: { ui: any, props: any }) {\n  const instance = getCurrentInstance()\n\n  provide('ButtonGroupContextConsumer', true)\n  const isParentPartOfGroup = inject('ButtonGroupContextConsumer', false)\n\n  // early return if a parent is already part of the group\n  if (isParentPartOfGroup) {\n    return {\n      size: computed(() => props.size),\n      rounded: computed(() => ui.value.rounded)\n    }\n  }\n\n  let parent = instance?.parent\n  let groupContext: Ref<ButtonGroupContext> | undefined\n\n  // Traverse up the parent chain to find the nearest ButtonGroup\n  while (parent && !groupContext) {\n    if (parent.type.name === 'ButtonGroup') {\n      groupContext = inject(`group-${parent.uid}`)\n      break\n    }\n    parent = parent.parent\n  }\n\n  const positionInGroup = computed(() => instance ? groupContext?.value.children.indexOf(instance) : false)\n  if (instance) {\n        onMounted(() => {\n            groupContext?.value.register(instance)\n        })\n        onUnmounted(() => {\n            groupContext?.value.unregister(instance)\n        })\n    }\n\n  return {\n    size: computed(() => {\n      if (!groupContext?.value) return props.size\n      return groupContext?.value.size ?? ui.value.default.size\n    }),\n    rounded: computed(() => {\n      if (!groupContext || positionInGroup.value === -1) return ui.value.rounded\n      if (groupContext.value.children.length === 1) return groupContext.value.ui.rounded\n      if (positionInGroup.value === 0) return groupContext.value.rounded.start\n      if (positionInGroup.value === groupContext.value.children.length - 1) return groupContext.value.rounded.end\n      return 'rounded-none'\n    })\n  }\n}"
  },
  {
    "path": "resources/js/Composables/useFormGroup.ts",
    "content": "import { inject, ref, computed } from 'vue'\nimport { type UseEventBusReturn, useDebounceFn } from '@vueuse/core'\nimport type { FormEvent, FormEventType, InjectedFormGroupValue } from '@/types'\n\n\ntype InputProps = {\n  id?: string\n  size?: string | number | symbol\n  color?: string\n  name?: string\n  eagerValidation?: boolean\n  legend?: string | null\n}\n\n\nexport const useFormGroup = (inputProps?: InputProps, config?: any) => {\n  const formBus = inject<UseEventBusReturn<FormEvent, string> | undefined>('form-events', undefined)\n  const formGroup = inject<InjectedFormGroupValue | undefined>('form-group', undefined)\n  const formInputs = inject<any>('form-inputs', undefined)\n\n  if (formGroup) {\n    if (inputProps?.id) {\n      // Updates for=\"...\" attribute on label if inputProps.id is provided\n      formGroup.inputId.value = inputProps?.id\n    }\n\n    if (formInputs) {\n      formInputs.value[formGroup.name.value] = formGroup.inputId.value\n    }\n  }\n\n  const blurred = ref(false)\n\n  function emitFormEvent (type: FormEventType, path: string) {\n    if (formBus) {\n      formBus.emit({ type, path })\n    }\n  }\n\n  function emitFormBlur () {\n    emitFormEvent('blur', formGroup?.name.value as string)\n    blurred.value = true\n  }\n\n  function emitFormChange () {\n    emitFormEvent('change', formGroup?.name.value as string)\n  }\n\n  const emitFormInput = useDebounceFn(() => {\n    if (blurred.value || formGroup?.eagerValidation.value) {\n      emitFormEvent('input', formGroup?.name.value as string)\n    }\n  }, 300)\n\n  return {\n    inputId: computed(() => inputProps?.id ?? formGroup?.inputId.value),\n    name: computed(() => inputProps?.name ?? formGroup?.name.value),\n    size: computed(() => {\n      const formGroupSize = config.size[formGroup?.size.value as string] ? formGroup?.size.value : null\n      return inputProps?.size ?? formGroupSize ?? 'sm'\n    }),\n    color: computed(() => formGroup?.error?.value ? 'red' : inputProps?.color),\n    emitFormBlur,\n    emitFormInput,\n    emitFormChange\n  }\n}"
  },
  {
    "path": "resources/js/Composables/useSidebarState.ts",
    "content": "import { ref } from 'vue'\nimport { createGlobalState } from '@vueuse/core'\n\nexport const useSidebarState = createGlobalState(\n  () => {\n    let sideBarOpen = ref(true);\n    let fullScreenSideBarOpen = ref(true);\n\n    function toggleSidebar() {\n        sideBarOpen.value = !sideBarOpen.value;\n        if (!sideBarOpen.value) {\n          fullScreenSideBarOpen.value = false;\n        }\n    }\n    function toggleFullScreenSidebar() {\n        fullScreenSideBarOpen.value = !fullScreenSideBarOpen.value;\n        if (fullScreenSideBarOpen.value) {\n          sideBarOpen.value = true;\n        }\n\n    }\n\n    return { sideBarOpen, fullScreenSideBarOpen, toggleSidebar, toggleFullScreenSidebar }\n  }\n)"
  },
  {
    "path": "resources/js/Composables/useUI.ts",
    "content": "import { computed, toValue, useAttrs } from 'vue'\nimport type { Ref } from 'vue'\nimport { mergeConfig, omit, get } from '@/Composables/utils';\nimport type { Strategy } from '@/types'\n\nexport const useUI = <T>(key: string, $ui?: Ref<Partial<T> & { strategy?: Strategy } | undefined>, $config?: Ref<T> | T, $wrapperClass?: Ref<string>) => {\n  const $attrs = useAttrs()\n\n  const ui = computed(() => {\n  const _ui = toValue($ui)\n  const _config = toValue($config)\n  const _wrapperClass = toValue($wrapperClass)\n\n    return mergeConfig<T>(\n      _ui?.strategy || 'merge',\n      _wrapperClass ? { wrapper: _wrapperClass } : {},\n      _ui || {},\n      _config || {}\n    )\n  })\n\n  const attrs = computed(() => omit($attrs, ['class']))\n\n  return {\n    ui,\n    attrs\n  }\n}"
  },
  {
    "path": "resources/js/Composables/utils.ts",
    "content": "import { defu, createDefu } from 'defu'\nimport { extendTailwindMerge } from 'tailwind-merge'\nimport type { Strategy } from '../types'\n\nconst customTwMerge = extendTailwindMerge<string, string>({\n  extend: {\n    classGroups: {\n      icons: [(classPart: string) => /^i-/.test(classPart)]\n    }\n  }\n})\n\nconst defuTwMerge = createDefu((obj, key, value, namespace) => {\n  if (namespace === 'default' || namespace.startsWith('default.')) {\n    return false\n  }\n  if (namespace === 'popper' || namespace.startsWith('popper.')) {\n    return false\n  }\n  if (namespace.endsWith('avatar') && key === 'size') {\n    return false\n  }\n  if (namespace.endsWith('chip') && key === 'size') {\n    return false\n  }\n  if (namespace.endsWith('badge') && key === 'size' || key === 'color' || key === 'variant') {\n    return false\n  }\n  if (typeof obj[key] === 'string' && typeof value === 'string' && obj[key] && value) {\n    // @ts-ignore\n    obj[key] = customTwMerge(obj[key], value)\n    return true\n  }\n})\n\nexport function mergeConfig<T> (strategy: Strategy, ...configs: any): T {\n  if (strategy === 'override') {\n    return defu({}, ...configs) as T\n  }\n\n  return defuTwMerge({}, ...configs) as T\n}\n\nexport function hexToRgb (hex: string) {\n  // Expand shorthand form (e.g. \"03F\") to full form (e.g. \"0033FF\")\n  const shorthandRegex = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i\n  hex = hex.replace(shorthandRegex, function (_, r, g, b) {\n    return r + r + g + g + b + b\n  })\n\n  const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex)\n  return result\n    ? `${parseInt(result[1], 16)} ${parseInt(result[2], 16)} ${parseInt(result[3], 16)}`\n    : null\n}\n\nexport function getSlotsChildren (slots: any) {\n  let children = slots.default?.()\n  if (children?.length) {\n    children = children.flatMap((c: any )=> {\n      if (typeof c.type === 'symbol') {\n        if (typeof c.children === 'string') {\n          // `v-if=\"false\"` or commented node\n          return\n        }\n        return c.children\n      } else if (c.type.name === 'ContentSlot') {\n        return c.ctx.slots.default?.()\n      }\n      return c\n    }).filter(Boolean)\n  }\n  return children || []\n}\n\n/**\n * \"123-foo\" will be parsed to 123\n * This is used for the .number modifier in v-model\n */\nexport function looseToNumber (val: any): any {\n  const n = parseFloat(val)\n  return isNaN(n) ? val : n\n}\n\nexport function omit<T extends Record<string, any>, K extends keyof T> (\n    object: T,\n    keysToOmit: K[] | any[]\n  ): Pick<T, Exclude<keyof T, K>> {\n    const result = { ...object }\n  \n    for (const key of keysToOmit) {\n      delete result[key]\n    }\n  \n    return result\n  }\n  \n  export function get (object: Record<string, any>, path: (string | number)[] | string, defaultValue?: any): any {\n    if (typeof path === 'string') {\n      path = path.split('.').map(key => {\n        const numKey = Number(key)\n        return isNaN(numKey) ? key : numKey\n      })\n    }\n  \n    let result: any = object\n  \n    for (const key of path) {\n      if (result === undefined || result === null) {\n        return defaultValue\n      }\n  \n      result = result[key]\n    }\n  \n    return result !== undefined ? result : defaultValue\n  }\n\n  export function useId(prefix?: string, length: number = 10): string {\n    let result = '';\n    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n    const charactersLength = characters.length;\n    let counter = 0;\n    while (counter < length) {\n      result += characters.charAt(Math.floor(Math.random() * charactersLength));\n      counter += 1;\n    }\n    return prefix ? prefix.concat(result) : result;\n  }\nexport function slugify (string: string): string {\n  const a = 'àáäâãåăæąçćčđďèéěėëêęğǵḧìíïîįłḿǹńňñòóöôœøṕŕřßşśšșťțùúüûǘůűūųẃẍÿýźžż·/_,:;'\n  const b = 'aaaaaaaaacccddeeeeeeegghiiiiilmnnnnooooooprrsssssttuuuuuuuuuwxyyzzz------'\n  const p = new RegExp(a.split('').join('|'), 'g')\n\n  return string.toString().toLowerCase()\n      .replace(/\\s+/g, '-') // Replace spaces with -\n      .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters\n      .replace(/&/g, '-and-') // Replace & with 'and'\n      .replace(/[^\\w-]+/g, '') // Remove all non-word characters\n      .replace(/--+/g, '-') // Replace multiple - with single -\n      .replace(/^-+/, '') // Trim - from start of text\n      .replace(/-+$/, '') // Trim - from end of text\n}"
  },
  {
    "path": "resources/js/Elements/Course.vue",
    "content": "<script setup lang=\"ts\">\nimport { Course } from \"@/types\";\nimport Button from \"@/Components/Button.vue\";\n\ndefineProps<{\n  course: Course\n}>();\n\n</script>\n<template>\n    <div class=\"w-full max-w-sm mx-auto rounded-md shadow-md overflow-hidden\">\n        <div class=\"flex items-end justify-end h-56 w-full bg-cover\"\n            style=\"background-image: url('https://picsum.photos/750/80')\">\n            <button\n                class=\"p-2 rounded-full bg-blue-600 text-white mx-5 -mb-4 hover:bg-blue-500 focus:outline-none focus:bg-blue-500\">\n                <svg class=\"h-5 w-5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n                    viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                    <path\n                        d=\"M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z\">\n                    </path>\n                </svg>\n            </button>\n        </div>\n        <div class=\"px-5 py-1\">\n            <h3 class=\"text-gray-700\">{{ course.title }}</h3>\n        </div>\n        <div class=\"px-5 pb-2 flex justify-between items-center\">\n            <span class=\"text-gray-700 mt-2\">${{ course.price }}</span>\n            <slot name=\"button\"  :course=\"course\">\n                <Button is=\"a\" :href=\"course.permalink\">\n                    view\n                </Button>\n            </slot>\n        </div>\n    </div>\n</template>"
  },
  {
    "path": "resources/js/Elements/Description.vue",
    "content": "<template>\n    <p id=\"\">\n        {{ showFullText ? description : description.substring(0, numberOfChar) }}\n        <a class=\"inline-block text-gray-700 dark:text-gray-500\" v-if=\"!showFullText\" @click.prevent=\"showFullText = true\">...more</a>\n        <a class=\"inline-block text-red-300 dark:text-red-500\" v-if=\"showFullText\" @click.prevent=\"showFullText = false\">(hide)</a>\n    </p>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref  } from 'vue';\nconst props = withDefaults(defineProps<{\n    description: string;\n    numberOfChar?: number;\n    fullText?: boolean\n}>(),\n{\n    numberOfChar: 50,\n    fullText: false\n})\n\nconst showFullText = ref(props.fullText);\n\n</script>"
  },
  {
    "path": "resources/js/Elements/Lesson/Question.vue",
    "content": "<template>\n    <div\n        class=\"card-body px-5\"\n    >\n        <div\n\n            class=\"row mt-5\"\n        >\n            <div class=\"col-12 d-flex justify-content-between\">\n                <strong>Mark : {{ question.mark }}</strong>\n                <strong>Nagative Mark: {{ question.nmark }}</strong>\n            </div>\n            <div class=\"col-12\">\n                <div class=\"question d-flex\">\n                    {{ question.question }}\n                </div>\n            </div>\n        </div>\n\n        <div\n\n            class=\"row mt-5\"\n        >\n            <div class=\"col\">\n                <div\n                    v-for=\"option in question.options\"\n                    :key=\"option.id\"\n                    class=\"custom-control custom-checkbox\"\n                >\n                    <input\n                        :id=\"option.id\"\n                        v-model=\"answer\"\n                        :value=\"option.id\"\n                        type=\"checkbox\"\n                        class=\"custom-control-input\"\n                    >\n                    <label\n                        class=\"custom-control-label\"\n                        :for=\"option.id\"\n                    >{{ option.option }}</label>\n                </div>\n            </div>\n        </div>\n        <div\n            v-if=\"question.hint\"\n            class=\"row mt-3\"\n        >\n            <div class=\"col\">\n                <div class=\"hint\">\n                    <strong>Hint:</strong>\n                    <p>{{ question.hint }}.</p>\n                </div>\n            </div>\n        </div>\n\n        <div class=\"row mt-5\">\n            <div class=\"col\">\n                <div class=\"next-button\">\n                    <button\n                        type=\"button\"\n                        class=\"btn btn-outline-success\"\n                        @click=\"previous\"\n                    >\n                        previous\n                    </button>\n                    <button\n                        type=\"button\"\n                        class=\"btn btn-outline-success\"\n                        @click=\"next\"\n                    >\n                        Next\n                    </button>\n                    <button\n                        type=\"button\"\n                        class=\"btn btn-outline-dark\"\n                        @click=\"clearAns\"\n                    >\n                        Clear Ans\n                    </button>\n                    <button\n                        type=\"button\"\n                        class=\"btn btn-outline-danger\"\n                        @click=\"finish\"\n                    >\n                        Finish\n                    </button>\n                </div>\n            </div>\n        </div>\n    </div>\n</template>\n\n<script>\nexport default {\n    props: {\n        question: {\n            type: Object,\n            required: true\n        },\n        answers: {\n            type: Array,\n            required: true\n        }\n    },\n    data: () => ({\n        answer: []\n    }),\n    mounted () {\n        this.answer = this.answers.find(a => a.id === this.question.id).answer || []\n    },\n    methods: {\n        clearAns () {\n            this.answer = []\n        },\n        previous () {\n            const ans = {}\n            ans[this.question.id] = this.answer\n            this.$emit('previous', ans)\n        },\n        next () {\n            const ans = {}\n            ans[this.question.id] = this.answer\n            this.$emit('next', ans)\n        },\n        finish () {\n            const ans = {}\n            ans[this.question.id] = this.answer\n            this.$emit('finish', ans)\n        }\n\n    }\n}\n</script>\n\n<style>\n\n</style>\n"
  },
  {
    "path": "resources/js/Elements/Lesson/Session.vue",
    "content": "<template>\n    <div class=\"card\">\n        <a\n            class=\"card-header\"\n            href=\"\"\n            @click.prevent=\"collapse = !collapse\"\n        >\n            <h5 class=\"mb-0\">\n                {{ session.title }}\n            </h5>\n        </a>\n\n        <ul\n            v-show=\"collapse\"\n            class=\"list-group list-group-flush\"\n        >\n            <li\n                v-for=\"(resource, i) in session.resources\"\n                :key=\"i\"\n                class=\"list-group-item list-group-item-action\"\n            >\n                <RouterLink\n                    v-if=\"isLesson(resource)\"\n                    :to=\"{name: 'singleLesson', params: { course: $route.params.course, lesson: resource.id}}\"\n                >\n                    <i class=\"fas fa-book-reader\" />\n                    {{ resource.title }}\n                </RouterLink>\n                <RouterLink\n                    v-if=\"isExam(resource)\"\n                    :to=\"{name: 'singleExam', params: { course: $route.params.course, exam: resource.id}}\"\n                >\n                    <i class=\"fas fa-graduation-cap\" />\n                    {{ resource.title }}\n                </RouterLink>\n            </li>\n        </ul>\n    </div>\n</template>\n\n<script>\nexport default {\n    props: {\n        session: {\n            type: Object,\n            required: true\n        }\n    },\n    data: () => ({\n        collapse: true\n    }),\n    computed: {\n\n    },\n    methods: {\n        isLesson (resource) {\n            return resource.pivot.sessionable_type === 'App\\\\Models\\\\Lesson'\n        },\n        isExam (resource) {\n            return resource.pivot.sessionable_type === 'App\\\\Models\\\\Exam'\n        }\n    }\n\n}\n</script>\n\n<style>\n\n</style>\n"
  },
  {
    "path": "resources/js/Elements/Lesson/SingleExam.vue",
    "content": "<template>\n    <div\n       \n        class=\"single-exam exam\"\n    >\n        <section\n            v-if=\"startTime\"\n            class=\"exam-bord\"\n        >\n            <div class=\"card\">\n                <div class=\"card-header d-flex justify-content-between\">\n                    <h4>REASONING : QUESTION 1 OF 16</h4>\n                    <div\n                        v-if=\"startTime\"\n                        class=\"time d-flex flex-column\"\n                    >\n                        <strong>Rmaining Time: {{ parseInt(examRemainingTime/60) }}: {{ parseInt(examRemainingTime%60) }}</strong>\n                        <strong>Total Time : {{ exam.duration }}</strong>\n                    </div>\n                </div>\n                <Question\n                    v-for=\"question in questions\"\n                    v-show=\"showQuestionNumber === question.id\"\n                    :key=\"question.id\"\n                    :question=\"question\"\n                    :answers=\"answers\"\n                    @previous=\"previousQuestion\"\n                    @next=\"nextQuestion\"\n                    @finish=\"finishExam\"\n                />\n\n                <div class=\"card-body\">\n                    <div class=\"row mt-5\">\n                        <div class=\"col-12\">\n                            <div>\n                                <h5>QUESTIONS</h5>\n                            </div>\n                        </div>\n                        <div class=\"col-12\">\n                            <div\n                                class=\"btn-toolbar\"\n                                role=\"toolbar\"\n                                aria-label=\"Toolbar with button groups\"\n                            >\n                                <button\n                                    v-for=\"(question, i ) in questions\"\n                                    :key=\"question.id\"\n                                    type=\"button\"\n                                    class=\"btn btn-primary mr-1\"\n                                    :class=\"{'answered': hasAnswer(question.id), 'active': showQuestionNumber === question.id}\"\n                                    @click.prevent=\"showQuestionNumber = question.id\"\n                                >\n                                    {{ i + 1 }}\n                                </button>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </section>\n        <section class=\"details\">\n            <div class=\"row\">\n                <div class=\"col-12\">\n                    <div class=\"card\">\n                        <div class=\"card-header\">\n                            <div class=\"list-group list-group-horizontal-lg\">\n                                <a class=\"list-group-item\">\n                                    Overview\n                                </a>\n                                <a class=\"list-group-item\">\n                                    Author\n                                </a>\n                            </div>\n                        </div>\n\n                        <div class=\"card-body p-5\">\n                            <div class=\"overview\">\n                                <h5 class=\"text-uppercase\">\n                                    ABOUT THIS EXAM\n                                </h5>\n                                <strong>{{ exam.title }}</strong>\n                                <table class=\"table table-bordered mt-4\">\n                                    <tbody>\n                                        <tr>\n                                            <th scope=\"row\">\n                                                Total Time\n                                            </th>\n                                            <td>{{ exam.duration }}</td>\n                                        </tr>\n                                        <tr>\n                                            <th scope=\"row\">\n                                                Number of Questions\n                                            </th>\n                                            <td>{{ exam.number_of_questions }}</td>\n                                        </tr>\n                                        <tr>\n                                            <th scope=\"row\">\n                                                Pass Mark\n                                            </th>\n                                            <td>\n                                                {{ exam.pass_mark }}\n                                            </td>\n                                        </tr>\n                                        <tr>\n                                            <th scope=\"row\">\n                                                Difficulty Level\n                                            </th>\n                                            <td>\n                                                {{ exam.difficulty }}\n                                            </td>\n                                        </tr>\n                                        <tr>\n                                            <th scope=\"row\">\n                                                Cirtificate\n                                            </th>\n                                            <td>\n                                                {{ exam.certification }}\n                                            </td>\n                                        </tr>\n                                        <tr v-if=\"exam.meta\">\n                                            <th scope=\"row\">\n                                                Retake After\n                                            </th>\n                                            <td>\n                                                {{ exam.meta.retake }} Days\n                                            </td>\n                                        </tr>\n                                    </tbody>\n                                </table>\n                                <div\n                                    v-if=\"result\"\n                                    class=\"card border-0\"\n                                >\n                                    <div class=\"card-header border-0\">\n                                        <h4>Result</h4>\n                                    </div>\n                                    <div class=\"card-body p-0\">\n                                        <table class=\"table table-bordered mt-4\">\n                                            <tbody>\n                                                <tr>\n                                                    <th scope=\"row\">\n                                                        Obtain Mark\n                                                    </th>\n                                                    <td>\n                                                        {{ result.obtain_mark }}\n                                                    </td>\n                                                </tr>\n                                                <tr>\n                                                    <th scope=\"row\">\n                                                        Pass Mark\n                                                    </th>\n                                                    <td>\n                                                        {{ result.is_pass }}\n                                                    </td>\n                                                </tr>\n                                                <tr>\n                                                    <th scope=\"row\">\n                                                        Time Taken\n                                                    </th>\n                                                    <td>\n                                                        {{ result.time_taken }}\n                                                    </td>\n                                                </tr>\n                                                <tr>\n                                                    <th scope=\"row\">\n                                                        Exam Date\n                                                    </th>\n                                                    <td>\n                                                        {{ fromNow(result.created_at ) }}\n                                                    </td>\n                                                </tr>\n                                                <tr v-if=\"timeToHeldExam>0\">\n                                                    <th scope=\"row\">\n                                                        Retry After\n                                                    </th>\n                                                    <td>\n                                                        {{ timeToHeldExam }} Days\n                                                    </td>\n                                                </tr>\n                                            </tbody>\n                                        </table>\n                                        <div class=\"question-button\">\n                                            <a\n                                                v-if=\"questions.length\"\n                                                href=\"#\"\n                                                class=\"btn btn-primary\"\n                                                @click.prevent=\"showAnswerdQuestion = !showAnswerdQuestion\"\n                                            >Show Question</a>\n                                        </div>\n                                    </div>\n                                </div>\n\n                                <h5 class=\"text-uppercase mt-3\">\n                                    Details\n                                </h5>\n\n                                <div>{{ exam.description }}</div>\n\n                                <a\n                                    v-if=\"canStartExam\"\n                                    href=\"#\"\n                                    class=\"btn btn-primary mt-5\"\n                                    @click.prevent=\"start\"\n                                >Start Exam</a>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </section>\n    </div>\n</template>\n<script>\nimport Question from './Question.vue'\nexport default {\n    components: {\n        Question\n    },\n    data: () => ({\n        loading: false,\n        startTime: null,\n        exam: {},\n        questions: [],\n        examRemainingTime: null,\n        showQuestionNumber: null,\n        answers: [],\n        result: null,\n        showAnswerdQuestion: false\n    }),\n    computed: {\n        isExamRunning () {\n            return this.startTime\n        },\n\n        canStartExam () {\n            if (!this.examRetakeRemainingDays) {\n                return true\n            }\n            if (this.exam.meta && parseInt(this.exam.meta.retake) < this.examRetakeRemainingDays) {\n                return true\n            }\n            return false\n        },\n        examRetakeRemainingDays () {\n            return this.result && moment.utc().diff(moment.utc(this.result.created_at), 'days', true)\n        },\n        timeToHeldExam () {\n            return Math.ceil(this.exam.meta && parseInt(this.exam.meta.retake) - this.examRetakeRemainingDays)\n        }\n    },\n    watch: {\n        '$route' () {\n            this.getExam()\n        },\n        startTime () {\n            this.remainingTime()\n        }\n    },\n    created () {\n        this.getExam()\n    },\n    mounted () {\n\n    },\n    methods: {\n        getExam () {\n            if (this.loading) {\n                return\n            }\n            this.loading = true\n\n            const params = {\n                id: this.$route.params.exam\n            }\n\n            axios.get(`/api/take-exam/${params.id}`, { params })\n                .then(res => {\n                    this.exam = res.data.exam\n                    this.startTime = res.data.time\n                    this.result = res.data.result\n                    this.questions = res.data.questions\n\n                    this.loading = false\n                    if (this.startTime) {\n                        this.start()\n                    }\n                })\n        },\n\n        start () {\n            if (this.loading) {\n                return\n            }\n            this.loading = true\n\n            const params = {\n                id: this.$route.params.exam\n            }\n\n            axios.post(`/api/start-exam/${params.id}`, { params })\n                .then(res => {\n                    this.questions = res.data.questions\n                    this.startTime = res.data.time\n                    this.showQuestionNumber = res.data.questions[0].id\n                    this.answers = res.data.answers\n                })\n                .finally(() => {\n                    this.loading = false\n                })\n        },\n        remainingTime () {\n            this.examRemainingTime = moment.utc(this.startTime).add(this.exam.duration, 'minutes').diff(moment.utc(), 'seconds')\n            if (this.examRemainingTime / 60 <= 0) {\n                this.complete()\n                return\n            }\n\n            setTimeout(() => {\n                this.remainingTime()\n            }, 1000)\n        },\n        storeAnswer (ans) {\n            return new Promise((resolve, reject) => {\n                axios.post(`/api/answer/${this.exam.id}`, ans)\n                    .then(res => {\n                        resolve(res.data)\n                    })\n                    .catch((error) => {\n                        reject(error)\n                    })\n            })\n        },\n        nextQuestion (ans) {\n            this.storeAnswer(ans)\n                .then(res => {\n                    this.answers = res.answers\n                    const i = this.questions.findIndex(q => this.showQuestionNumber === q.id)\n                    if (i + 1 === this.questions.length) {\n                        this.showQuestionNumber = this.questions[0].id\n                    } else {\n                        this.showQuestionNumber = this.questions[i + 1].id\n                    }\n                })\n        },\n        previousQuestion (ans) {\n            this.storeAnswer(ans)\n                .then(res => {\n                    this.answers = res.answers\n                    const i = this.questions.findIndex(q => this.showQuestionNumber === q.id)\n                    if (i === 0) {\n                        this.showQuestionNumber = this.questions[this.questions.length - 1].id\n                    } else {\n                        this.showQuestionNumber = this.questions[i - 1].id\n                    }\n                })\n        },\n        finishExam (ans) {\n            this.storeAnswer(ans)\n                .then(res => {\n                    this.complete()\n                })\n        },\n        complete () {\n            axios.post(`/api/complete-exam/${this.exam.id}`)\n                .then(res => {\n                    this.result = res.data.result\n                    this.startTime = null\n                    window.location.reload()\n                })\n        },\n        hasAnswer (id) {\n            const answer = this.answers.find(a => a.id === id)\n            return answer && typeof answer.answer !== 'undefined'\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "resources/js/Elements/Lesson/SingleLesson.vue",
    "content": "<template>\n    <div class=\"single-lesson\">\n        <section v-if=\"lesson.type == 'Video'\" class=\"video\">\n            <VideoPreview :file=\"lesson.object\" />\n        </section>\n\n        <section class=\"details mt-8\">\n                <Tabs :items=\"items\" class=\"w-full\">\n                    <template #overview>\n                        <Card>\n                            <h3 class=\"text-uppercase\">ABOUT THIS Lesson</h3>\n                            <strong>{{ lesson.title }}</strong>\n                            <p>{{ lesson.short_text }}</p>\n\n                            <h3 class=\"text-uppercase\">Details</h3>\n\n                            <div>{{ lesson.full_text }}</div>\n                        </Card>\n                    </template>\n                </Tabs>\n        </section>\n    </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Tabs from '@/Components/Tabs.vue'\nimport Card from '@/Components/Card.vue';\nimport { Lesson } from '@/types';\n// import VideoPreview from './../../common/dropzone/VideoPreview'\n\ndefineProps<{\n    lesson: Lesson\n}>()\n\nconst items = [\n    {\n        slot: \"overview\",\n        label: \"Overview\",\n    },\n    {\n        slot: \"descussions\",\n        label: \"Descussions\",\n    },\n    {\n        slot: \"author\",\n        label: \"Author\",\n    },\n];\n\n</script>\n"
  },
  {
    "path": "resources/js/Elements/Lesson/SingleResource.vue",
    "content": "<template>\n    <div class=\"resource-single sidebar\">\n        <div\n            v-if=\"!loading\"\n            class=\"session\"\n        >\n            <div class=\"row\">\n                <div class=\"col-12\">\n                    <div\n                        v-for=\"session in sessions\"\n                        :key=\"session.id\"\n                    >\n                        <Session :session=\"session\" />\n                    </div>\n                </div>\n            </div>\n        </div>\n        <Loading\n            v-if=\"loading\"\n            spinner\n        />\n        <div v-else-if=\"!hasResource\">\n            <p>Can not find any exam or lesson on this course</p>\n        </div>\n        <RouterView v-else />\n    </div>\n</template>\n<script>\nimport Session from './Session'\nexport default {\n    components: {\n        Session\n    },\n    data: () => ({\n        loading: false,\n        sessions: []\n    }),\n    computed: {\n        hasResource () {\n            let hasResource = false\n            for (let index = 0; index < this.sessions.length; index++) {\n                if (this.sessions[index].resources.length) {\n                    hasResource = true\n                    break\n                }\n            }\n\n            return hasResource\n        },\n        firstResource () {\n            let firstResource = false\n            for (let index = 0; index < this.sessions.length; index++) {\n                if (this.sessions[index].resources.length) {\n                    firstResource = this.sessions[index].resources[0]\n                    break\n                }\n            }\n\n            return firstResource\n        }\n    },\n    created () {\n        this.getSessions()\n    },\n    methods: {\n        getSessions () {\n            if (this.loading) {\n                return\n            }\n            this.loading = true\n            const params = {\n                id: this.$route.params.course\n            }\n            axios.get(`/api/courses/${params.id}/sessions`)\n                .then(res => {\n                    this.sessions = res.data.data\n                    if (this.$route.name === 'singleResource') {\n                        this.redirectFirstResource()\n                    }\n                })\n                .finally(() => {\n                    this.loading = false\n                })\n        },\n        redirectFirstResource () {\n            if (this.firstResource.pivot.sessionable_type.indexOf('Lesson') !== -1) {\n                this.$router.push({\n                    name: 'singleLesson',\n                    params: {\n                        course: this.$route.params.course,\n                        lesson: this.firstResource.id\n                    }\n                })\n            } else {\n                this.$router.push({\n                    name: 'singleExam',\n                    params: {\n                        course: this.$route.params.course,\n                        exam: this.firstResource.id\n                    }\n                })\n            }\n        }\n    }\n}\n</script>\n"
  },
  {
    "path": "resources/js/Elements/admin/AdminFooter.vue",
    "content": "<template>\n  <footer :class=\"footerClass\">\n\n    <div class=\"border-t py-4\" :class=\"borderClass\">\n        <div class=\"text-center\">\n          <GHButtons\n            show-follow\n            show-star\n            show-fork\n            show-issue\n            show-watch\n            show-sponsor\n            show-download\n            show-count\n            show-tips\n          />\n        </div>\n      <p\n        class=\"text-center text-sm leading-6 text-slate-500 dark:text-gray-300\"\n      >\n        &copy; {{ theYear }} {{ company }}. All rights reserved.\n      </p>\n    </div>\n  </footer>\n</template>\n\n<script>\nimport GHButtons from '@/Elements/admin/GHButtons.vue';\nexport default {\n  name: 'AdminFooter',\n  components: {\n    GHButtons\n  },\n  props: {\n    footerClass: {\n      type: String,\n      default: 'max-w-container mx-auto mt-32 w-full px-4 sm:px-6 lg:px-8',\n    },\n    borderClass: {\n      type: String,\n      default: 'border-slate-900/5 dark:border-slate-700',\n    },\n  },\n  setup() {\n    return {};\n  },\n  data() {\n    return {\n      company: 'Examinee',\n    };\n  },\n  computed: {\n    theYear() {\n      const startYear = '2022';\n      const currentYear = new Date().getFullYear();\n      if (currentYear == startYear) {\n        return currentYear;\n      }\n      return `${startYear}-${currentYear}`;\n    },\n  },\n  watch: {},\n  created() {},\n  mounted() {},\n  beforeUnmount() {},\n  updated() {},\n  methods: {},\n};\n</script>\n\n<style scoped></style>\n\n<style lang=\"scss\" scoped></style>\n"
  },
  {
    "path": "resources/js/Elements/admin/AdminNavBar.vue",
    "content": "<template>\n  <div class=\"sticky top-0 z-40\">\n    <div\n      class=\"flex h-20 w-full items-center justify-between border-b bg-white px-6 dark:bg-slate-800\"\n    >\n      <div class=\"flex\">\n        <div class=\"mr-4 inline-block flex items-center lg:hidden\">\n          <button\n            class=\"navbar-burger rounded text-gray-600 hover:border-white hover:text-gray-500 focus:outline-none dark:bg-slate-800 dark:hover:bg-slate-800\"\n            :class=\"\n              sideBarOpen ? 'bg-slate-100 text-gray-900 dark:text-gray-100' : ''\n            \"\n            @click.prevent=\"toggleSidebar()\"\n          >\n            <span v-if=\"!sideBarOpen\" class=\"sr-only\">Open menu</span>\n            <span v-if=\"sideBarOpen\" class=\"sr-only\">CLose menu</span>\n            <Bars3Icon v-if=\"!sideBarOpen\" class=\"h-6 w-6\" aria-hidden=\"true\" />\n            <XMarkIcon v-if=\"sideBarOpen\" class=\"h-6 w-6\" aria-hidden=\"true\" />\n          </button>\n        </div>\n\n        \n\n        <div class=\"hidden lg:inline-flex\">\n          <div class=\"mr-4 inline-block flex items-center\">\n            <button\n              class=\"navbar-burger rounded text-gray-600 hover:border-white hover:text-gray-500 focus:outline-none dark:bg-slate-800 dark:hover:bg-slate-800\"\n              @click=\"toggleFullScreenSidebar()\"\n            >\n              <span v-if=\"!fullScreenSideBarOpen\" class=\"sr-only\"\n                >Open menu</span\n              >\n              <span v-if=\"fullScreenSideBarOpen\" class=\"sr-only\"\n                >CLose menu</span\n              >\n              <Bars3Icon\n                v-if=\"!fullScreenSideBarOpen\"\n                class=\"h-6 w-6\"\n                aria-hidden=\"true\"\n              />\n              <Bars3BottomLeftIcon\n                v-if=\"fullScreenSideBarOpen\"\n                class=\"h-6 w-6\"\n                aria-hidden=\"true\"\n              />\n            </button>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"relative flex items-center\">\n        <div class=\"my-1 mr-3 mt-2 w-full py-2 sm:flex sm:items-center\">\n          <span\n            v-tippy=\"'Toggle Theme ' + (isDark ? 'Light' : 'Dark')\"\n            @click=\"toggleDark()\"\n          >\n            <Switch\n              :class=\"isDark ? 'bg-gray-500' : 'bg-gray-400'\"\n              class=\"relative inline-flex h-[26px] w-[48px] shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75\"\n            >\n              <span class=\"sr-only\">Toggle Theme</span>\n              <span\n                aria-hidden=\"true\"\n                :class=\"\n                  isDark\n                    ? 'translate-x-5 bg-gray-800'\n                    : 'translate-x-0 bg-white'\n                \"\n                class=\"pointer-events-none inline-block h-[22px] w-[24px] transform rounded-full shadow-lg ring-0 transition duration-200 ease-in-out\"\n              />\n            </Switch>\n          </span>\n        </div>\n\n        <!--<img\n          v-if=\"user && user.avatar\"\n          :src=\"user.avatar\"\n          :alt=\"user.name\"\n          class=\"h-8 w-8 cursor-pointer rounded-full border shadow-lg\"\n          @click=\"dropDownOpen = !dropDownOpen\"\n        /> -->\n        <UserCircleIcon\n          class=\"float-right ml-1 mt-0 h-16 w-16 cursor-pointer\"\n          @click=\"dropDownOpen = !dropDownOpen\"\n        />\n      </div>\n    </div>\n\n    <div ref=\"dropMenu\" class=\"relative mt-1\">\n      <div\n        v-show=\"dropDownOpen\"\n        class=\"absolute right-5 z-10 flex w-auto flex-col whitespace-nowrap rounded border bg-white shadow-md dark:bg-slate-900\"\n        @click=\"dropDownOpen = !dropDownOpen\"\n      >\n        <Link\n            :href=\"route('logout')\"\n            method=\"post\"\n            as=\"button\"\n            class=\"flex cursor-pointer items-center rounded-b p-4 pr-10 pl-8 text-gray-700 hover:bg-slate-800 hover:text-white\"\n        >\n          <ArrowLeftEndOnRectangleIcon\n            class=\"mr-2 h-6 w-6\"\n          ></ArrowLeftEndOnRectangleIcon>\n            Log Out\n        </Link>\n\n      </div>\n    </div>\n  </div>\n</template>\n\n<script lang=\"ts\">\nimport { Link } from \"@inertiajs/vue3\";\nimport {\n  Bars3Icon,\n  HomeIcon,\n  BuildingLibraryIcon,\n  InformationCircleIcon,\n  XMarkIcon,\n  CogIcon,\n  ArrowLeftEndOnRectangleIcon,\n  Bars3BottomLeftIcon,\n  UserCircleIcon,\n} from '@heroicons/vue/24/outline';\nimport { Switch, Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue';\nimport useAuth from '@/Composables/useAuth';\nimport { useDark, useToggle } from '@vueuse/core'\nimport { useSidebarState } from '@/Composables/useSidebarState'\n\nexport default {\n  name: 'AdminNavBar',\n  components: {\n    HomeIcon,\n    BuildingLibraryIcon,\n    InformationCircleIcon,\n    Bars3Icon,\n    XMarkIcon,\n    CogIcon,\n    Link,\n    ArrowLeftEndOnRectangleIcon,\n    UserCircleIcon,\n    Bars3BottomLeftIcon,\n    Switch,\n    Menu,\n    MenuButton,\n    MenuItems,\n    MenuItem\n  },\n  props: {},\n  setup() {\n    const { user, roles, authenticated } = useAuth();\n    const isDark = useDark()\n    const toggleDark = useToggle(isDark)\n    const { sideBarOpen, toggleSidebar, fullScreenSideBarOpen, toggleFullScreenSidebar  } = useSidebarState()\n\n    return {\n      user,\n      roles,\n      authenticated,\n      isDark,\n      toggleDark,\n      sideBarOpen,\n      toggleSidebar,\n      fullScreenSideBarOpen,\n      toggleFullScreenSidebar\n    };\n  },\n  data() {\n    return {\n      dropDownOpen: false,\n    };\n  },\n  computed: {\n\n  },\n  watch: {},\n  created() {},\n\n  beforeUnmount() {},\n  updated() {},\n  methods: {\n\n    closeDrop() {\n      this.dropDownOpen = false;\n    },\n    openDrop() {\n      this.dropDownOpen = true;\n    }\n  },\n};\n</script>"
  },
  {
    "path": "resources/js/Elements/admin/AdminSidebar.vue",
    "content": "<template>\n  <!-- give the sidebar z-50 class so its higher than the navbar if you want to see the logo -->\n  <!-- you will need to add a little \"X\" button next to the logo in order to close it though -->\n  <div\n    id=\"main-nav\"\n    class=\"fixed z-30 h-screen w-1/2 border-r bg-white dark:bg-slate-800 mdhrefp-0 md:left-0 md:w-1/3 lg:w-64 transition-all duration-200\"\n    :class=\"sideBarOpen ? '' : 'hidden'\"\n  >\n    <div class=\"mb-8 flex h-20 w-full items-center border-b px-4\">\n      <div class=\"flex justify-center lg:w-0 lg:flex-1\">\n        <Link :href=\"route('home')\">\n          <svg\n            viewBox=\"0 0 50 31\"\n            class=\"h-6 w-auto text-indigo-500 dark:text-indigo-300\"\n          >\n            <path\n              fill-rule=\"evenodd\"\n              clip-rule=\"evenodd\"\n              d=\"M25.517 0C18.712 0 14.46 3.382 12.758 10.146c2.552-3.382 5.529-4.65 8.931-3.805 1.941.482 3.329 1.882 4.864 3.432 2.502 2.524 5.398 5.445 11.722 5.445 6.804 0 11.057-3.382 12.758-10.145-2.551 3.382-5.528 4.65-8.93 3.804-1.942-.482-3.33-1.882-4.865-3.431C34.736 2.92 31.841 0 25.517 0zM12.758 15.218C5.954 15.218 1.701 18.6 0 25.364c2.552-3.382 5.529-4.65 8.93-3.805 1.942.482 3.33 1.882 4.865 3.432 2.502 2.524 5.397 5.445 11.722 5.445 6.804 0 11.057-3.381 12.758-10.145-2.552 3.382-5.529 4.65-8.931 3.805-1.941-.483-3.329-1.883-4.864-3.432-2.502-2.524-5.398-5.446-11.722-5.446z\"\n              fill=\"currentColor\"\n            ></path>\n          </svg>\n          <p class=\"sr-only text-3xl font-semibold text-blue-400\">\n            {{ appName }}\n          </p>\n        </Link>\n      </div>\n    </div>\n\n    <div class=\"mb-4 px-4\">\n      <!-- <p class=\"mb-1 pl-4 text-sm font-semibold dark:text-gray-100\">MAIN</p> -->\n\n      <Link\n        v-for=\"item in navigation\"\n        :key=\"item.name\"\n        v-if=\"authenticated && roles && (roles.admin || roles.superAdmin)\"\n        :href=\"item.href\"\n      >\n        <div\n          class=\"flex h-10 w-full items-center rounded-lg pl-4 text-blue-400\"\n          :class=\"\n            item.current\n              ? 'cursor-default bg-gray-200 text-blue-600 hover:bg-gray-200 dark:bg-gray-900 dark:text-blue-200 dark:hover:bg-gray-900'\n              : 'cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700'\n          \"\n        >\n          <component :is=\"item.icon\" class=\"mr-2 mb-1 h-6 w-6\" />\n          <span class=\"\">{{ item.name }}</span>\n        </div>\n      </Link>  \n    </div>\n\n    \n\n\n\n    \n  </div>\n</template>\n\n<script lang=\"ts\">\nimport { Link } from \"@inertiajs/vue3\";\nimport useAuth from '@/Composables/useAuth';\nimport { useSidebarState } from '@/Composables/useSidebarState'\nimport {\n  UsersIcon,\n  BuildingLibraryIcon,\n  ShieldCheckIcon,\n  ShieldExclamationIcon,\n  CogIcon,\n  ServerStackIcon,\n} from '@heroicons/vue/24/outline';\n\nexport default {\n  name: 'AdminSidebar',\n  components: {\n    UsersIcon,\n    BuildingLibraryIcon,\n    ShieldCheckIcon,\n    ShieldExclamationIcon,\n    ServerStackIcon,\n    CogIcon,\n    Link\n  },\n  props: {\n    appName: { type: String, default: 'Workflow' },\n  },\n  setup() {\n    const { user, roles, authenticated } = useAuth();\n    const { sideBarOpen, fullScreenSideBarOpen } = useSidebarState()\n    const navigation = [\n        { name: \"Admin\", icon: BuildingLibraryIcon,  href: route('admin.dashboard'), current: route().current(\"admin.dashboard\") },\n        { name: \"Users\", icon: UsersIcon,  href: route('admin.users.index'), current: route().current(\"admin.users.index\") },\n        { name: \"Roles\", icon: ShieldCheckIcon, href: route('admin.roles.index'), current: route().current(\"admin.roles.index\") },\n        { name: \"Subjects\", icon: ShieldCheckIcon, href: route('admin.subjects.index'), current: route().current(\"admin.subjects.index\") },\n        { name: \"Topics\", icon: ShieldExclamationIcon, href: route('admin.topics.index'), current: route().current(\"admin.topics.index\") },\n        { name: \"Courses\", icon: ShieldExclamationIcon, href: route('admin.courses.index'), current: route().current(\"admin.courses.index\") },\n        { name: \"Exams\", icon: ShieldExclamationIcon, href: route('admin.exams.index'), current: route().current(\"admin.exams.index\") },\n        { name: \"Server Info\", icon: ServerStackIcon, href: route('admin.server-info'), current: route().current('admin.server-info') },\n        { name: \"App Settings\", icon: CogIcon, href: \"#\", current: false },\n    ];\n    return {\n      user,\n      roles,\n      authenticated,\n      navigation,\n      sideBarOpen,\n      fullScreenSideBarOpen\n    };\n  },\n  data() {\n    return {\n      isActive: true\n    };\n  },\n  computed: {\n    \n\n  },\n  watch: {},\n  created() {},\n  mounted() {},\n  beforeUnmount() {},\n  updated() {},\n  methods: {\n  },\n};\n</script>\n\n<style scoped></style>\n<style lang=\"scss\" scoped></style>\n"
  },
  {
    "path": "resources/js/Elements/admin/GHButtons.vue",
    "content": "<template>\n  <div class=\"github-buttons\">\n    <github-button\n      v-if=\"showFollow && ghUser\"\n      :href=\"ghBaseUrl + ghUser\"\n      :data-color-scheme=\"darkTheme ? darkVariant : lightVariant\"\n      :data-size=\"size\"\n      :data-show-count=\"showCountString\"\n      :aria-label=\"followTitle + ghUser + ' on ' + serviceName\"\n      class=\"gh-button mr-1\"\n      @click=\"track('Clicked ' + followTitle + ghUser + ' on ' + serviceName)\"\n    >\n      {{ followTitle }}{{ ghUser }}\n    </github-button>\n    <github-button\n      v-if=\"showStar && ghUser && ghRepo\"\n      v-tippy=\"\n        showTips\n          ? starTitle +\n            ' ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' on ' +\n            serviceName\n          : null\n      \"\n      :href=\"ghBaseUrl + ghUser + '/' + ghRepo\"\n      :data-color-scheme=\"darkTheme ? darkVariant : lightVariant\"\n      :data-icon=\"starIcon\"\n      :data-size=\"size\"\n      :data-show-count=\"showCountString\"\n      :aria-label=\"\n        starTitle +\n        ' ' +\n        ghBaseUrl +\n        ghUser +\n        '/' +\n        ghRepo +\n        ' on ' +\n        serviceName\n      \"\n      class=\"gh-button mr-1\"\n      @click=\"\n        track(\n          'Clicked ' +\n            starTitle +\n            ' ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' on ' +\n            serviceName,\n        )\n      \"\n    >\n      {{ starTitle }}\n    </github-button>\n    <github-button\n      v-if=\"showFork && ghUser && ghRepo\"\n      v-tippy=\"\n        showTips\n          ? starTitle +\n            ' ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' on ' +\n            serviceName\n          : null\n      \"\n      :href=\"ghBaseUrl + ghUser + '/' + ghRepo + '/fork'\"\n      :data-color-scheme=\"darkTheme ? darkVariant : lightVariant\"\n      :data-icon=\"forkIcon\"\n      :data-size=\"size\"\n      :data-show-count=\"showCountString\"\n      :aria-label=\"\n        forkTitle +\n        ' ' +\n        ghBaseUrl +\n        ghUser +\n        '/' +\n        ghRepo +\n        ' on ' +\n        serviceName\n      \"\n      class=\"gh-button mr-1\"\n      @click=\"\n        track(\n          'Clicked ' +\n            forkTitle +\n            ' ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' on ' +\n            serviceName,\n        )\n      \"\n    >\n      {{ forkTitle }}\n    </github-button>\n    <github-button\n      v-if=\"showIssue && ghUser && ghRepo\"\n      v-tippy=\"\n        showTips\n          ? 'Show ' +\n            issueTitle +\n            ' for ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' on ' +\n            serviceName\n          : null\n      \"\n      :href=\"ghBaseUrl + ghUser + '/' + ghRepo + '/issues'\"\n      :data-color-scheme=\"darkTheme ? darkVariant : lightVariant\"\n      :data-icon=\"issueIcon\"\n      :data-size=\"size\"\n      :data-show-count=\"showCountString\"\n      :aria-label=\"\n        issueTitle +\n        ' ' +\n        ghBaseUrl +\n        ghUser +\n        '/' +\n        ghRepo +\n        ' on ' +\n        serviceName\n      \"\n      class=\"gh-button mr-1\"\n      @click=\"\n        track(\n          'Clicked ' +\n            issueTitle +\n            ' ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' on ' +\n            serviceName,\n        )\n      \"\n    >\n      {{ issueTitle }}\n    </github-button>\n    <github-button\n      v-if=\"showWatch && ghUser && ghRepo\"\n      v-tippy=\"\n        showTips\n          ? watchTitle +\n            ' ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' on ' +\n            serviceName\n          : null\n      \"\n      :href=\"ghBaseUrl + ghUser + '/' + ghRepo + '/subscription'\"\n      :data-color-scheme=\"darkTheme ? darkVariant : lightVariant\"\n      :data-icon=\"watchIcon\"\n      :data-size=\"size\"\n      :data-show-count=\"showCountString\"\n      :aria-label=\"\n        watchTitle +\n        ' ' +\n        ghBaseUrl +\n        ghUser +\n        '/' +\n        ghRepo +\n        ' on ' +\n        serviceName\n      \"\n      class=\"gh-button mr-1\"\n      @click=\"\n        track(\n          'Clicked ' +\n            watchTitle +\n            ' ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' on ' +\n            serviceName,\n        )\n      \"\n    >\n      {{ watchTitle }}\n    </github-button>\n\n    <github-button\n      v-if=\"showSponsor && ghUser\"\n      v-tippy=\"showTips ? 'Sponsor @' + ghUser + ' on GitHub' : null\"\n      :href=\"ghBaseUrl + 'sponsors/' + ghUser\"\n      :data-icon=\"sponsorIcon\"\n      :data-size=\"size\"\n      :aria-label=\"'Sponsor @' + ghUser + ' on GitHub'\"\n      class=\"gh-button mr-1\"\n      @click=\"\n        track(\n          'Clicked ' + sponsorTitle + ' ' + ghBaseUrl + 'sponsors/' + ghUser,\n        )\n      \"\n    >\n      {{ sponsorTitle }}\n    </github-button>\n\n    <github-button\n      v-if=\"showDownload && ghUser && ghRepo\"\n      v-tippy=\"\n        showTips\n          ? downloadTitle +\n            ' ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' directly from ' +\n            serviceName\n          : null\n      \"\n      :href=\"ghBaseUrl + ghUser + '/' + ghRepo + '/archive/HEAD.zip'\"\n      :data-color-scheme=\"darkTheme ? darkVariant : lightVariant\"\n      :data-icon=\"downloadIcon\"\n      :data-size=\"size\"\n      :data-show-count=\"showCountString\"\n      :aria-label=\"\n        downloadTitle +\n        ' ' +\n        ghBaseUrl +\n        ghUser +\n        '/' +\n        ghRepo +\n        ' directly from ' +\n        serviceName\n      \"\n      class=\"gh-button mr-1\"\n      @click=\"\n        track(\n          'Clicked ' +\n            downloadTitle +\n            ' ' +\n            ghBaseUrl +\n            ghUser +\n            '/' +\n            ghRepo +\n            ' directly from ' +\n            serviceName,\n        )\n      \"\n    >\n      {{ downloadTitle }}\n    </github-button>\n  </div>\n</template>\n\n<script lang=\"ts\">\nimport { track } from '@/Composables/analytics';\nimport GithubButton from 'vue-github-button';\n// https://buttons.github.io/\n\nexport default {\n  name: 'GHButtons',\n  components: { GithubButton },\n  props: {\n    serviceName: { type: String, default: 'GitHub' },\n    lightVariant: { type: String, default: 'light' }, // light_high_contrast\n    darkVariant: { type: String, default: 'dark_high_contrast' }, // dark dark_dimmed\n    ghBaseUrl: { type: String, default: 'https://github.com/' },\n    ghUser: { type: String, default: 'mshossain110' },\n    ghRepo: { type: String, default: 'examinee' },\n    size: { type: String, default: 'large' },\n    showTips: { type: Boolean, default: false },\n    showCount: { type: Boolean, default: false },\n    showFollow: { type: Boolean, default: false },\n    showStar: { type: Boolean, default: false },\n    showFork: { type: Boolean, default: false },\n    showIssue: { type: Boolean, default: false },\n    showWatch: { type: Boolean, default: false },\n    showSponsor: { type: Boolean, default: false },\n    showDownload: { type: Boolean, default: false },\n    followTitle: { type: String, default: 'Follow @' },\n    starIcon: { type: String, default: 'octicon-star' },\n    starTitle: { type: String, default: 'Star' },\n    forkIcon: { type: String, default: 'octicon-repo-forked' },\n    forkTitle: { type: String, default: 'Fork' },\n    issueIcon: { type: String, default: 'octicon-issue-opened' },\n    issueTitle: { type: String, default: 'Issue' },\n    watchIcon: { type: String, default: 'octicon-eye' },\n    watchTitle: { type: String, default: 'Watch' },\n    downloadIcon: { type: String, default: 'octicon-download' },\n    downloadTitle: { type: String, default: 'Download' },\n    sponsorTitle: { type: String, default: 'Sponsor' },\n    sponsorIcon: { type: String, default: 'octicon-heart' },\n    frequency: { type: String, default: 'recurring' }, // one-time\n  },\n  computed: {\n    darkTheme() {\n      // if (this.user && this.user.theme_dark) {\n      //   return true;\n      // }\n      return false;\n    },\n    showCountString() {\n      return this.showCount.toString();\n    },\n  },\n  methods: {\n    track,\n  },\n};\n</script>\n\n<style scoped></style>\n<style lang=\"scss\" scoped></style>\n"
  },
  {
    "path": "resources/js/Elements/course/CourseForm.vue",
    "content": "<template>\n    <Card>\n        <template #header>\n            <h1>{{ props.course?.id ? \"Update Course\" : \"Create Course\" }}</h1>\n        </template>\n        <form @submit.prevent=\"submit\">\n            <div class=\"grid grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Title\" name=\"title\" size=\"lg\">\n                    <Input v-model=\"form.title\" size=\"lg\" />\n                </Label>\n                <Label label=\"Slug\" name=\"slug\" size=\"lg\">\n                    <Input v-model=\"form.slug\" :readonly=\"editslug\" size=\"lg\" >\n                        <template #trailing>\n                            <a href=\"\" @click.prevent=\"editslug = !editslug\" class=\"inline-block p-3 bg-gray-500\">\n                                <Icon v-if=\"editslug\" name=\"EyeSlashIcon\" class=\"w-6 h-6 \" />\n                                <Icon v-else name=\"EyeIcon\" class=\"w-6 h-6 \" />\n                            </a>\n                        </template>\n                    </Input>\n                    \n                </Label>\n                <Label label=\"Subtitle\" name=\"subtitle\" size=\"lg\">\n                    <Input v-model=\"form.subtitle\" size=\"lg\" />\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Description\" name=\"description\">\n                    <textarea\n                        v-model=\"form.description\"\n                        name=\"description\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Requirements\" name=\"requirements\">\n                    <textarea\n                        v-model=\"form.requirements\"\n                        name=\"requirements\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Features\" name=\"features\">\n                    <textarea\n                        v-model=\"form.features\"\n                        name=\"features\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                <Label label=\"Status\" name=\"status\">\n                    <Select\n                        :options=\"[\n                            { label: 'Published', value: 1 },\n                            { label: 'Pending', value: 2 },\n                        ]\"\n                        v-model=\"form.status\"\n                    ></Select>\n                </Label>\n                <Label\n                    label=\"Price\"\n                    name=\"price\"\n                >\n                    <Input v-model=\"form.price\" type=\"number\" />\n                </Label>\n                <Label\n                    label=\"Discount\"\n                    name=\"discount\"\n                    help=\"Discount will be calculate in %\"\n                >\n                    <Input v-model=\"form.discount\" type=\"number\" step=\".2\" />\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-4 gap-4 mb-2\">\n                <Checkbox v-model=\"form.certified\" label=\"Certified\" />\n            </div>\n            <Button>\n                {{ props.course?.id ? \"Update Course\" : \"Create Course\" }}\n            </Button>\n        </form>\n    </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { useForm } from \"@inertiajs/vue3\";\nimport { Course } from \"@/types\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\nimport Label from \"@/Components/Form/Label.vue\";\nimport Input from \"@/Components/Form/Input.vue\";\nimport Checkbox from \"@/Components/Form/Checkbox.vue\";\nimport Select from \"@/Components/Form/Select.vue\";\nimport Icon from '@/Components/Icon.vue'\n\nconst props = defineProps<{\n    course?: Course;\n}>();\n\nconst form = useForm({\n    title: props.course?.title,\n    subtitle: props.course?.subtitle,\n    slug: props.course?.slug,\n    description: props.course?.description,\n    requirements: props.course?.requirements,\n    status: props.course?.status,\n    thumbnail: props.course?.thumbnail,\n    start_date: props.course?.start_date,\n    features: props.course?.features,\n    certified: props.course?.certified,\n    price: props.course?.price,\n    discount: props.course?.discount,\n});\n\nconst editslug = ref(false);\n\nfunction submit() {\n    if (props.course.id) {\n        form.put(route(\"admin.courses.update\", props.course.id));\n    } else {\n        form.post(route(\"admin.courses.store\"));\n    }\n}\n</script>\n"
  },
  {
    "path": "resources/js/Elements/course/CourseLayout.vue",
    "content": "<template>\n    <div class=\"grid grid-cols-12 gap-6\">\n        <div\n            class=\"col-span-12 flex flex-col-reverse lg:col-span-4 lg:block 2xl:col-span-3\"\n        >\n            <aside aria-label=\"Sidebar\">\n                <div\n                    class=\"px-3 py-4 overflow-y-auto rounded bg-gray-50 dark:bg-gray-800\"\n                >\n                    <ul class=\"space-y-2\">\n                        <li>\n                            <a\n                                :href=\"\n                                    course?.id\n                                        ? route('admin.courses.edit', course.id)\n                                        : route('admin.courses.create')\n                                \"\n                                class=\"flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700\"\n                                :class=\"[\n                                    {\n                                        'bg-gray-300': route().current(\n                                            'admin.courses.*',\n                                            course?.id\n                                        ),\n                                    },\n                                ]\"\n                            >\n                                <span class=\"ml-3\">{{\n                                    course?.id ? \"Edit\" : \"Create\"\n                                }}</span>\n                            </a>\n                        </li>\n                        <template v-if=\"course?.id\">\n                            <li>\n                                <Link\n                                    :href=\"\n                                        route('admin.sections.index', course.id)\n                                    \"\n                                    class=\"flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700\"\n                                    :class=\"[\n                                        {\n                                            'bg-gray-300': route().current(\n                                                'admin.sections.*',\n                                                course.id\n                                            ),\n                                        },\n                                    ]\"\n                                >\n                                    <span class=\"flex-1 ml-3 whitespace-nowrap\">\n                                        Sections\n                                    </span>\n                                </Link>\n                                <Link\n                                    :href=\"\n                                        route('admin.course-student', course.id)\n                                    \"\n                                    class=\"flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700\"\n                                    :class=\"[\n                                        {\n                                            'bg-gray-300': route().current(\n                                                'admin.course-student',\n                                                course.id\n                                            ),\n                                        },\n                                    ]\"\n                                >\n                                    <span class=\"flex-1 ml-3 whitespace-nowrap\">\n                                        Student\n                                    </span>\n                                </Link>\n                            </li>\n                        </template>\n                    </ul>\n                </div>\n            </aside>\n        </div>\n        <div class=\"col-span-12 lg:col-span-8 2xl:col-span-9\">\n            <slot></slot>\n        </div>\n    </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { Course } from \"@/types\";\nimport { Link } from \"@inertiajs/vue3\";\n\ndefineProps<{\n    course?: Course;\n}>();\n</script>\n"
  },
  {
    "path": "resources/js/Elements/course/Exam.vue",
    "content": "<template>\n    <li\n        class=\"relative rounded-lg border border-gray-300 px-6 py-5 shadow-sm items-center space-x-3 hover:border-gray-400 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500\"\n    >\n        <div class=\"flex\">\n            <div class=\"flex-shrink-0 mr-3\">\n                <Icon name=\"AcademicCapIcon\" class=\"w-6 h-6\" />\n            </div>\n            <div class=\"flex-1 min-w-0\">\n                {{ exam.title }}\n            </div>\n            <div class=\"flex-shrink-0\">\n                <a :href=\"route('admin.exams.edit', exam.id)\" class=\"inline-block\">\n                    <Icon name=\"PencilIcon\" class=\"w-6 h-6\" />\n                </a>\n            </div>\n        </div>\n    </li>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { Exam } from '@/types';\nimport LessonForm from './LessonForm.vue';\nimport Icon from '@/Components/Icon.vue';\n\ndefineProps<{\n    exam: Exam\n}>()\n\nconst showForm = ref(false)\n</script>\n"
  },
  {
    "path": "resources/js/Elements/course/Lesson.vue",
    "content": "<template>\n    <li\n        class=\"relative rounded-lg border border-gray-300 px-6 py-5 shadow-sm items-center space-x-3 hover:border-gray-400 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500\"\n    >\n        <div class=\"flex\">\n            <div class=\"flex-shrink-0 mr-3\">\n                <Icon name=\"BookOpenIcon\" class=\"w-6 h-6\" />\n            </div>\n            <div class=\"flex-1 min-w-0\">\n                {{ lesson.title }}\n            </div>\n            <div class=\"flex-shrink-0\">\n                <a href=\"\" @click.prevent=\"showForm = !showForm\" class=\"inline-block\">\n                    <Icon name=\"PencilIcon\" class=\"w-6 h-6\" />\n                </a>\n            </div>\n        </div>\n        \n        <LessonForm v-if=\"showForm\" :lesson=\"lesson\"></LessonForm>\n    </li>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { Lesson } from '@/types';\nimport LessonForm from './LessonForm.vue';\nimport Icon from '@/Components/Icon.vue';\n\ndefineProps<{\n    lesson: Lesson\n}>()\n\nconst showForm = ref(false)\n</script>\n"
  },
  {
    "path": "resources/js/Elements/course/LessonForm.vue",
    "content": "<template>\n        <Card>\n        <template #header>\n            <h1>{{ lesson?.id ? \"Update Lesson\" : \"Create Lesson\" }}</h1>\n        </template>\n        <form @submit.prevent=\"submit\">\n            <div class=\"grid grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Title\" name=\"title\" size=\"lg\">\n                    <Input v-model=\"form.title\" size=\"lg\" />\n                </Label>\n                <Label label=\"Slug\" name=\"slug\" size=\"lg\">\n                    <Input v-model=\"form.slug\" :readonly=\"editslug\" size=\"lg\" >\n                        <template #trailing>\n                            <a href=\"\" @click.prevent=\"editslug = !editslug\" class=\"inline-block p-3 bg-gray-500\">\n                                <Icon v-if=\"editslug\" name=\"EyeSlashIcon\" class=\"w-6 h-6 \" />\n                                <Icon v-else name=\"EyeIcon\" class=\"w-6 h-6 \" />\n                            </a>\n                        </template>\n                    </Input>\n                    \n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Short text\" name=\"short_text\">\n                    <textarea\n                        v-model=\"form.short_text\"\n                        name=\"short_text\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Full text\" name=\"full_text\" help=\"This will be a full tutorial\">\n                    <textarea\n                        v-model=\"form.full_text\"\n                        name=\"full_text\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                <Label label=\"Status\" name=\"status\">\n                    <Select\n                        :options=\"[\n                            { label: 'Free', value: 1 },\n                            { label: 'Subscriber', value: 2 },\n                            { label: 'Paid', value: 3 },\n                        ]\"\n                        v-model=\"form.status\"\n                    ></Select>\n                </Label>\n                <Label label=\"Lesson Type\" name=\"type\">\n                    <Select\n                        :options=\"[\n                            { label: 'Text', value: 1 },\n                            { label: 'Vedio', value: 2 },\n                            { label: 'Audio', value: 3 },\n                            { label: 'PDF', value: 4 },\n                        ]\"\n                        v-model=\"form.type\"\n                    ></Select>\n                </Label>\n            </div>\n            <Button>\n                {{ props.lesson?.id ? \"Update Lesson\" : \"Create Lesson\" }}\n            </Button>\n        </form>\n    </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { useForm } from \"@inertiajs/vue3\";\nimport { Course, Lesson } from \"@/types\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\nimport Label from \"@/Components/Form/Label.vue\";\nimport Input from \"@/Components/Form/Input.vue\";\nimport Checkbox from \"@/Components/Form/Checkbox.vue\";\nimport Select from \"@/Components/Form/Select.vue\";\nimport Icon from '@/Components/Icon.vue'\n\n\nconst props = defineProps<{\n    lesson?: Lesson\n}>();\n\nconst form = useForm({\n    title: props.lesson?.title,\n    slug: props.lesson?.slug,\n    short_text: props.lesson?.short_text,\n    full_text: props.lesson?.full_text,\n    type: props.lesson?.slug,\n    object: props.lesson?.slug,\n    status: props.lesson?.slug,\n});\n\nconst editslug = ref(false);\n\nfunction submit() {\n    if (props.lesson?.id) {\n        form.put(route(\"admin.lessons.update\",  props.lesson?.id));\n    } else {\n        form.post(route(\"admin.lessons.store\"));\n    }\n}\n</script>"
  },
  {
    "path": "resources/js/Elements/course/SectionForm.vue",
    "content": "<template>\n    <Card>\n        <template #header v-if=\"!section\">\n            <h1 class=\"text-lg\">{{ section?.id ? \"Update Section\" : \"Create Section\" }}</h1>\n        </template>\n        <form @submit.prevent=\"submit\">\n            <div class=\"grid grid-cols-1  gap-4 mb-2\">\n                <Label label=\"Title\" name=\"title\">\n                    <Input v-model=\"form.title\" />\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Description\" name=\"description\">\n                    <textarea\n                        v-model=\"form.description\"\n                        name=\"description\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <Button type=\"submit\">\n                {{ props.section?.id ? \"Update Section\" : \"Create Section\" }}\n            </Button>\n        </form>\n    </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport Label from \"@/Components/Form/Label.vue\";\nimport Input from \"@/Components/Form/Input.vue\";\nimport { Course, Section } from \"@/types\";\nimport { useForm } from \"@inertiajs/vue3\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\n\nconst props = defineProps<{\n    course: Course\n    section?: Section\n}>()\n\nconst form = useForm({\n    title: props.section.title,\n    description: props.section.description,\n});\n\nfunction submit() {\n    if ( props.section) {\n        form.put(route(\"admin.sections.update\", [props.course.id, props.section.id]));\n    } else {\n        form.put(route(\"admin.sections.store\", [props.course.id]));\n    }\n}\n</script>\n"
  },
  {
    "path": "resources/js/Elements/course/SingleSection.vue",
    "content": "<template>\n    <Card class=\"mb-4\">\n        <template #header>\n            <div class=\"grid grid-cols-12 justify-between items-center\">\n                <div class=\"col-span-8\">\n                    <h1 class=\"text-lg\">{{ section.title }}</h1>\n                    <Description :description=\"section.description\" />\n                </div>\n                <div class=\"col-span-4 flex justify-end\">\n                    <Button @click.prevent=\"editSection = !editSection\">\n                        <Icon name=\"PencilIcon\" class=\"w-4 h-4\"></Icon>\n                    </Button>\n                </div>\n            </div>\n        </template>\n\n        <SectionForm :section=\"section\" :course=\"course\" v-if=\"editSection\" />\n\n        <ul class=\"grid grid-cols-1 space-y-2\">\n            <template v-for=\"lesson in section.lessons\" :key=\"'lesson-' + lesson.id\">\n                <Lesson :lesson=\"lesson\" />\n            </template>\n            <template v-for=\"exam in section.exams\" :key=\"'exam-' + exam.id\">\n                <Exam :exam=\"exam\" />\n            </template>\n        </ul>\n\n        <template #footer>\n            <div class=\"flex justify-center items-center space-x-4 mb-4\">\n                <Button @click.prevent=\"lessonForm = !lessonForm; examForm = false; \">Create Lesson</Button>\n                <Button @click.prevent=\"examForm = !examForm; lessonForm = false; \">Create Exam</Button>\n            </div>\n            <div class=\"flex w-full\">\n                <LessonForm v-if=\"lessonForm && !examForm\"/>\n                <CreateExam v-if=\"examForm && !lessonForm\"/>\n            </div>\n        </template>\n    </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from \"vue\";\nimport { Course, Section } from \"@/types\";\nimport Card from \"@/Components/Card.vue\";\nimport Icon from \"@/Components/Icon.vue\";\nimport Button from \"@/Components/Button.vue\";\nimport SectionForm from \"./SectionForm.vue\";\nimport Description from \"../Description.vue\";\nimport Lesson from \"./Lesson.vue\";\nimport Exam from \"./Exam.vue\";\nimport LessonForm from \"@/Elements/course/LessonForm.vue\";\nimport CreateExam from \"@/Elements/exam/CreateExam.vue\";\n\nconst props = defineProps<{\n    course: Course;\n    section: Section;\n}>();\n\nconst editSection = ref(false);\nconst lessonForm = ref(false);\nconst examForm = ref(false);\n\n</script>\n"
  },
  {
    "path": "resources/js/Elements/exam/CreateExam.vue",
    "content": "<template>\n    <Card>\n        <template #header>\n            <h1>{{ props.exam?.id ? \"Update Exam\" : \"Create Exam\" }}</h1>\n        </template>\n        <form @submit.prevent=\"submit\">\n            <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                <Label label=\"Title\" name=\"title\">\n                    <Input v-model=\"form.title\" />\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Description\" name=\"description\">\n                    <textarea\n                        v-model=\"form.description\"\n                        name=\"description\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                <Label label=\"Status\" name=\"status\">\n                    <Select\n                        :options=\"[\n                            { label: 'Free', value: 1 },\n                            { label: 'Course', value: 2 },\n                            { label: 'Course &amp; Paid', value: 3 },\n                            { label: 'Paid', value: 4 },\n                        ]\"\n                        v-model=\"form.status\"\n                    ></Select>\n                </Label>\n                <Label\n                    label=\"Price\"\n                    name=\"price\"\n                    v-if=\"form.status == 3 || form.status == 4\"\n                >\n                    <Input v-model=\"form.price\" type=\"number\" step=\"1\" />\n                </Label>\n                <Label label=\"Duration\" name=\"duration\">\n                    <Input\n                        v-model=\"form.duration\"\n                        type=\"number\"\n                        min=\"10\"\n                        max=\"120\"\n                        step=\"1\"\n                    />\n                </Label>\n                <Label label=\"Pass mark\" name=\"pass_mark\">\n                    <Input v-model=\"form.pass_mark\" type=\"number\" />\n                </Label>\n                <Label label=\"Difficulty\" name=\"difficulty\">\n                    <Input\n                        v-model=\"form.difficulty\"\n                        type=\"number\"\n                        min=\"1\"\n                        max=\"4\"\n                    />\n                </Label>\n                <Label label=\"Number of questions\" name=\"number_of_questions\">\n                    <Input v-model=\"form.number_of_questions\" type=\"number\" />\n                </Label>\n                <Label\n                    label=\"Retake After\"\n                    name=\"number_of_questions\"\n                    :hint=\"`Examinee can retake the exam after ${form.meta.retake} days`\"\n                >\n                    <Input v-model=\"form.meta.retake\" type=\"number\" />\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-4 gap-4 mb-2\">\n                <Checkbox v-model=\"form.certification\" label=\"Certification\" />\n                <Checkbox\n                    v-model=\"form.random_questions\"\n                    label=\"Random question\"\n                />\n                <Checkbox v-model=\"form.meta.show_hint\" label=\"Show hint\" />\n                <Checkbox\n                    v-model=\"form.meta.show_question\"\n                    label=\"Show Question\"\n                />\n                <Checkbox\n                    v-model=\"form.meta.show_explanation\"\n                    label=\"Show Explanation\"\n                />\n                <Checkbox\n                    v-model=\"form.meta.negative_mark\"\n                    label=\"Negative Mark\"\n                />\n                <Checkbox v-model=\"form.meta.show_answer\" label=\"Show Answer\" />\n            </div>\n            <Button>\n                {{ props.exam?.id ? \"Update Exam\" : \"Create Exam\" }}\n            </Button>\n        </form>\n    </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport { useForm } from \"@inertiajs/vue3\";\nimport { Exam } from \"@/types\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\nimport Label from \"@/Components/Form/Label.vue\";\nimport Input from \"@/Components/Form/Input.vue\";\nimport Checkbox from \"@/Components/Form/Checkbox.vue\";\nimport Select from \"@/Components/Form/Select.vue\";\n\nconst props = defineProps<{\n    exam?: Exam;\n}>();\n\nconst form = useForm({\n    title: props.exam?.title,\n    description: props.exam?.description,\n    status: props.exam?.status,\n    price: props.exam?.price,\n    duration: props.exam?.duration,\n    pass_mark: props.exam?.pass_mark,\n    number_of_questions: props.exam?.number_of_questions,\n    random_questions: props.exam?.random_questions,\n    certification: props.exam?.certification,\n    difficulty: props.exam?.difficulty,\n    meta: {\n        retake: props.exam?.meta?.retake,\n        show_hint: props.exam?.meta?.show_hint,\n        show_question: props.exam?.meta?.show_question,\n        show_explanation: props.exam?.meta?.show_explanation,\n        negative_mark: props.exam?.meta?.negative_mark,\n        show_answer: props.exam?.meta?.show_answer,\n    },\n});\n\nfunction submit() {\n    if (props.exam.id) {\n        form.put(route(\"admin.exams.update\", props.exam.id));\n    } else {\n        form.post(route(\"admin.exams.store\"));\n    }\n}\n</script>\n"
  },
  {
    "path": "resources/js/Elements/exam/CreateQuestion.vue",
    "content": "<template>\n    <Card>\n        <template #header>\n            <h1>{{ question?.id ? \"Update Question\" : \"Create Question\" }}</h1>\n        </template>\n        <form @submit.prevent=\"submit\">\n            <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                <Label label=\"Question type\" name=\"qtype\">\n                    <Select\n                        :options=\"[\n                            { label: 'Objective', value: 'Objective' },\n                            { label: 'True/False', value: 'TrueFalse' },\n                        ]\"\n                        v-model=\"form.qtype\"\n                    ></Select>\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Question\" name=\"question\">\n                    <textarea\n                        v-model=\"form.question\"\n                        name=\"question\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-12 gap-y-2 gap-x-2 mb-2\">\n                <strong class=\"text-md col-span-1\">Correct Answer</strong>\n                <strong class=\"text-md col-span-10\">Option</strong>\n                <strong class=\"text-md col-span-1\"></strong>\n                <template v-for=\"(op, index) in questionOptions\" :key=\"'qoi-'+ index\">\n                    <Checkbox\n                        v-model=\"questionOptions[index].answer\"\n                        label=\"\"\n                        class=\"col-span-1\"\n                    />\n                    <textarea\n                        v-model=\"questionOptions[index].option\"\n                        name=\"question\"\n                        cols=\"40\"\n                        rows=\"8\"\n                        class=\"relative col-span-10 block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                    <Button class=\"col-span-1 justify-center h-10\" @click.prevent=\"removeOption(index)\" color=\"red\">Remove</Button>\n                </template>\n                \n            </div>\n            <div class=\"grid grid-cols-1 mb-2 w-40\">\n                <Button class=\"justify-center\" @click.prevent=\"addMoreOption\" color=\"gray\">Add More Option</Button>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                <Label label=\"Mark\" name=\"mark\">\n                    <Input\n                        v-model=\"form.mark\"\n                        type=\"number\"\n                    />\n                </Label>\n                <Label label=\"Nagative Mark\" name=\"nmark\">\n                    <Input\n                        v-model=\"form.nmark\"\n                        type=\"number\"\n                    />\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-2\">\n                <Label label=\"hint\" name=\"hint\">\n                    <textarea\n                        v-model=\"form.hint\"\n                        name=\"hint\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <div class=\"grid grid-cols-1 md:grid-cols-1 gap-4 mb-2\">\n                <Label label=\"Answer Explanation\" name=\"explanation\">\n                    <textarea\n                        v-model=\"form.explanation\"\n                        name=\"hint\"\n                        cols=\"80\"\n                        rows=\"8\"\n                        class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                    ></textarea>\n                </Label>\n            </div>\n            <Button>\n                {{ props.question?.id ? \"Update Question\" : \"Create Question\" }}\n            </Button>\n        </form>\n    </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onBeforeMount } from 'vue';\nimport { useForm } from \"@inertiajs/vue3\";\nimport Card from \"@/Components/Card.vue\";\nimport { Exam, Question, QuestionOption } from '@/types'\nimport Button from \"@/Components/Button.vue\";\nimport Label from \"@/Components/Form/Label.vue\";\nimport Input from \"@/Components/Form/Input.vue\";\nimport Checkbox from \"@/Components/Form/Checkbox.vue\";\nimport Select from \"@/Components/Form/Select.vue\";\nimport { useId } from '@/Composables/utils';\n\nconst props = defineProps<{\n    exam: Exam,\n    question?: Question\n}>()\n\nconst form = useForm({\n    qtype: props.question?.qtype,\n    question: props.question?.question,\n    options: props.question?.options,\n    answers: props.question?.answers,\n    hint: props.question?.hint,\n    mark: props.question?.mark,\n    nmark: props.question?.nmark,\n    explanation: props.question?.explanation\n})\n\nconst questionOptions = ref<QuestionOption[]>([]);\n\nfunction submit() {\n    form.answers = [];\n    form.options = [];\n    questionOptions.value.map(qo => {\n        if (qo.answer) {\n            form.answers.push(qo.id)\n        }\n        delete qo.answer;\n        form.options.push(qo)\n    })\n\n    if (props.question?.id) {\n        form.put(route(\"admin.questions.update\", [props.exam.id, props.question.id]));\n    } else {\n        form.post(route(\"admin.questions.store\", props.exam.id));\n    }\n}\n\nonBeforeMount(() => {\n    if (props.question?.options.length) {\n        props.question.options.map(qo => {\n            console.log(props.question.answers.indexOf(qo.id))\n            questionOptions.value.push({\n                option: qo.option,\n                answer: props.question.answers.indexOf(qo.id) !== -1,\n                id: qo.id\n            })\n        })\n    } else {\n        addMoreOption()\n    }\n})\n\nfunction addMoreOption () {\n    questionOptions.value.push({ answer: false, option: '', id: useId('qo', 10) })\n}\n\nfunction removeOption (index: number) {\n    questionOptions.value.splice(index, 1)\n}\n\n</script>"
  },
  {
    "path": "resources/js/Elements/exam/ExamLayout.vue",
    "content": "<template>\n    <div class=\"grid grid-cols-12 gap-6\">\n        <div\n            class=\"col-span-12 flex flex-col-reverse lg:col-span-4 lg:block 2xl:col-span-3\"\n        >\n            <aside aria-label=\"Sidebar\">\n                <div\n                    class=\"px-3 py-4 overflow-y-auto rounded bg-gray-50 dark:bg-gray-800\"\n                >\n                    <ul class=\"space-y-2\">\n                        <li>\n                            <a\n                                :href=\"exam?.id ? route('admin.exams.edit', exam.id) : route('admin.exams.create')\"\n                                class=\"flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700\"\n                                :class=\"[ {'bg-gray-300' : route().current('admin.exams.*', exam?.id)}]\"\n                            >\n                                <span class=\"ml-3\">{{ exam?.id ? 'Edit' : 'Create' }}</span>\n                            </a>\n                        </li>\n                        <template v-if=\"exam?.id \">\n                            <li>\n                                <a\n                                    :href=\"route('admin.questions.index', exam.id)\"\n                                    class=\"flex items-center p-2 text-base font-normal text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700\"\n                                    :class=\"[ {'bg-gray-300' : route().current('admin.questions.*',  exam.id)}]\"\n                                >\n                                    <span class=\"flex-1 ml-3 whitespace-nowrap\"\n                                        >Questions</span\n                                    >\n                                </a>\n                            </li>\n                        </template>\n                    </ul>\n                </div>\n            </aside>\n        </div>\n        <div class=\"col-span-12 lg:col-span-8 2xl:col-span-9\">\n            <slot></slot>\n        </div>\n    </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { Exam, Question } from '@/types';\nimport { Link } from '@inertiajs/vue3';\n\ndefineProps<{\n    exam?: Exam,\n    question?: Question\n}>()\n</script>"
  },
  {
    "path": "resources/js/Elements/exam/QuestionTable.vue",
    "content": "<template>\n    <div id=\"question-lists\">\n        <Card class=\"mb-5\">\n            <div class=\"flex justify-between items-center\">\n                <div>\n                    <h1>Questions</h1>\n                    <Breadcrumb :items=\"breadcrumb\" />\n                </div>\n                <div>\n                    <Button is=\"a\" :href=\"route('admin.questions.create', exam.id)\">\n                        Create Question\n                    </Button>\n                </div>\n            </div>\n        </Card>\n        <Card>\n            <DataTable :rows=\"questions\" :columns=\"columns\">\n                <template #actions-data=\"{ row }\">\n                    <div class=\"flex justify-end\">\n                        <Link\n                            :href=\"route('admin.questions.edit', [exam.id, row.id])\"\n                        >\n                            <Icon\n                                class=\"mr-2 h-6 w-6 text-gray-300\"\n                                name=\"PencilIcon\"\n                            ></Icon>\n                        </Link>\n                        <Link @click=\"deleteQuestion(row)\" as=\"button\" href=\"\">\n                            <Icon\n                                class=\"mr-2 h-6 w-6 text-red-500\"\n                                name=\"TrashIcon\"\n                            ></Icon>\n                        </Link>\n                    </div>\n                </template>\n            </DataTable>\n        </Card>\n    </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { Link, router } from \"@inertiajs/vue3\";\nimport Card from \"@/Components/Card.vue\";\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport DataTable from \"@/Components/Datatable/Table.vue\";\nimport Icon from \"@/Components/Icon.vue\";\nimport { Exam, Question, LinkType } from \"@/types\";\nimport Button from \"@/Components/Button.vue\";\n\nconst props = defineProps<{\n    exam: Exam;\n    questions: Question[];\n}>();\n\nconst columns = [\n    {\n        key: \"qtype\",\n        label: \"Type\",\n    },\n    {\n        key: \"question\",\n        label: \"Question\",\n    },\n    {\n        key: \"mark\",\n        label: \"Mark\",\n    },\n    {\n        key: \"nmark\",\n        label: \"Nagative mark\",\n    },\n    {\n        key: \"actions\",\n    },\n];\n\nconst breadcrumb: LinkType[] = [\n                {\n                    name: \"Exams\",\n                    href: route(\"admin.exams.index\"),\n                    current: route().current(\"admin.exams.index\"),\n                },\n                {\n                    name: \"Questions\",\n                    href: route(\"admin.questions.index\", [props.exam.id]),\n                    current: route().current(\"admin.questions.*\"),\n                },\n            ];\n    \nfunction deleteQuestion(question: Question) {\n    if (confirm(\"Are you sure you want to delete this item?\")) {\n        router.delete(route(\"admin.questions.destroy\", [props.exam.id, question.id]));\n    }\n}\n</script>\n"
  },
  {
    "path": "resources/js/Elements/roles/RolesBadges.vue",
    "content": "<template>\n  <div v-if=\"roles\">\n    <span\n      v-if=\"roles.superAdmin\"\n      class=\"mr-2 cursor-default rounded bg-blue-100 px-2.5 py-0.5 text-sm font-medium text-blue-800 dark:bg-blue-200 dark:text-blue-800\"\n      >Super Admin</span\n    >\n    <span\n      v-if=\"roles.admin\"\n      class=\"mr-2 cursor-default rounded bg-gray-100 px-2.5 py-0.5 text-sm font-medium text-gray-800 dark:bg-gray-700 dark:text-gray-300\"\n      >Admin</span\n    >\n    <span\n      v-if=\"roles.moderator\"\n      class=\"mr-2 cursor-default rounded bg-red-100 px-2.5 py-0.5 text-sm font-medium text-red-800 dark:bg-red-200 dark:text-red-900\"\n      >Moderator</span\n    >\n    <span\n      v-if=\"roles.editor\"\n      class=\"mr-2 cursor-default rounded bg-green-100 px-2.5 py-0.5 text-sm font-medium text-green-800 dark:bg-green-200 dark:text-green-900\"\n      >Editor</span\n    >\n    <span\n      v-if=\"roles.user\"\n      class=\"mr-2 cursor-default rounded bg-yellow-100 px-2.5 py-0.5 text-sm font-medium text-yellow-800 dark:bg-yellow-200 dark:text-yellow-900\"\n      >User</span\n    >\n  </div>\n</template>\n\n<script lang=\"ts\">\nexport default {\n  name: 'RolesBadges',\n  components: {},\n  props: {\n    roles: { type: Object, required: true },\n  },\n  setup() {\n    return {};\n  },\n  data() {\n    return {\n      //\n    };\n  },\n  computed: {},\n  watch: {},\n  created() {},\n  mounted() {},\n  beforeUnmount() {},\n  updated() {},\n  methods: {},\n};\n</script>\n\n<style scoped></style>\n<style lang=\"scss\" scoped></style>\n"
  },
  {
    "path": "resources/js/Layouts/AdminLayout.vue",
    "content": "<template>\n  <div id=\"main-body\" class=\"leading-normal tracking-normal\">\n    <div class=\"flex flex-wrap\">\n      <AdminSidebar :class=\"fullScreenSideBarOpen ? '' : 'lg:hidden'\" />\n      <div\n        id=\"main-content\"\n        class=\"min-h-screen w-full bg-white pl-0 dark:bg-slate-800 transition-all duration-200\"\n        :class=\"\n          (sideBarOpen ? 'overlay ' : ' ') +\n          (fullScreenSideBarOpen ? 'lg:pl-64' : '')\n        \"\n      >\n        <AdminNavBar />\n        <div class=\"mb-20 p-4 bg-white dark:bg-slate-800 dark:text-gray-200\">\n          <slot />\n        </div>\n        <!-- <AdminFooter\n          class=\"sticky top-[100vh] w-full\"\n          footer-class=\"border-slate-900/5 dark:border-slate-700\"\n          border-class=\"\"\n        /> -->\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport AdminNavBar from '@/Elements/admin/AdminNavBar.vue';\nimport AdminSidebar from '@/Elements/admin/AdminSidebar.vue';\n// import AdminFooter from '@/Elements/admin/AdminFooter.vue';\nimport { useSidebarState } from '@/Composables/useSidebarState'\n\nexport default {\n  name: 'AdminLayout',\n  components: {\n    AdminNavBar,\n    AdminSidebar,\n    // AdminFooter,\n  },\n  props: {},\n  setup() {\n    const { sideBarOpen, fullScreenSideBarOpen } = useSidebarState()\n    return {sideBarOpen, fullScreenSideBarOpen}\n  },\n  watch: {},\n  created() {},\n  mounted() {},\n  beforeUnmount() {},\n  updated() {},\n  methods: {},\n};\n</script>\n"
  },
  {
    "path": "resources/js/Layouts/AuthenticatedLayout.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport ApplicationLogo from '@/Components/ApplicationLogo.vue';\nimport Dropdown from '@/Components/Dropdown.vue';\nimport DropdownLink from '@/Components/DropdownLink.vue';\nimport NavLink from '@/Components/NavLink.vue';\nimport ResponsiveNavLink from '@/Components/ResponsiveNavLink.vue';\nimport { Link } from '@inertiajs/vue3';\n\nconst showingNavigationDropdown = ref(false);\n</script>\n\n<template>\n    <div>\n        <div class=\"min-h-screen bg-gray-100 dark:bg-gray-900\">\n            <nav class=\"bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700\">\n                <!-- Primary Navigation Menu -->\n                <div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n                    <div class=\"flex justify-between h-16\">\n                        <div class=\"flex\">\n                            <!-- Logo -->\n                            <div class=\"shrink-0 flex items-center\">\n                                <Link :href=\"route('dashboard')\">\n                                    <ApplicationLogo\n                                        class=\"block h-9 w-auto fill-current text-gray-800 dark:text-gray-200\"\n                                    />\n                                </Link>\n                            </div>\n\n                            <!-- Navigation Links -->\n                            <div class=\"hidden space-x-8 sm:-my-px sm:ms-10 sm:flex\">\n                                <NavLink :href=\"route('dashboard')\" :active=\"route().current('dashboard')\">\n                                    Dashboard\n                                </NavLink>\n                            </div>\n                        </div>\n\n                        <div class=\"hidden sm:flex sm:items-center sm:ms-6\">\n                            <!-- Settings Dropdown -->\n                            <div class=\"ms-3 relative\">\n                                <Dropdown align=\"right\" width=\"48\">\n                                    <template #trigger>\n                                        <span class=\"inline-flex rounded-md\">\n                                            <button\n                                                type=\"button\"\n                                                class=\"inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150\"\n                                            >\n                                                {{ $page.props.auth.user.name }}\n\n                                                <svg\n                                                    class=\"ms-2 -me-0.5 h-4 w-4\"\n                                                    xmlns=\"http://www.w3.org/2000/svg\"\n                                                    viewBox=\"0 0 20 20\"\n                                                    fill=\"currentColor\"\n                                                >\n                                                    <path\n                                                        fill-rule=\"evenodd\"\n                                                        d=\"M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z\"\n                                                        clip-rule=\"evenodd\"\n                                                    />\n                                                </svg>\n                                            </button>\n                                        </span>\n                                    </template>\n\n                                    <template #content>\n                                        <DropdownLink :href=\"route('profile.edit')\"> Profile </DropdownLink>\n                                        <DropdownLink :href=\"route('logout')\" method=\"post\" as=\"button\">\n                                            Log Out\n                                        </DropdownLink>\n                                    </template>\n                                </Dropdown>\n                            </div>\n                        </div>\n\n                        <!-- Hamburger -->\n                        <div class=\"-me-2 flex items-center sm:hidden\">\n                            <button\n                                @click=\"showingNavigationDropdown = !showingNavigationDropdown\"\n                                class=\"inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out\"\n                            >\n                                <svg class=\"h-6 w-6\" stroke=\"currentColor\" fill=\"none\" viewBox=\"0 0 24 24\">\n                                    <path\n                                        :class=\"{\n                                            hidden: showingNavigationDropdown,\n                                            'inline-flex': !showingNavigationDropdown,\n                                        }\"\n                                        stroke-linecap=\"round\"\n                                        stroke-linejoin=\"round\"\n                                        stroke-width=\"2\"\n                                        d=\"M4 6h16M4 12h16M4 18h16\"\n                                    />\n                                    <path\n                                        :class=\"{\n                                            hidden: !showingNavigationDropdown,\n                                            'inline-flex': showingNavigationDropdown,\n                                        }\"\n                                        stroke-linecap=\"round\"\n                                        stroke-linejoin=\"round\"\n                                        stroke-width=\"2\"\n                                        d=\"M6 18L18 6M6 6l12 12\"\n                                    />\n                                </svg>\n                            </button>\n                        </div>\n                    </div>\n                </div>\n\n                <!-- Responsive Navigation Menu -->\n                <div\n                    :class=\"{ block: showingNavigationDropdown, hidden: !showingNavigationDropdown }\"\n                    class=\"sm:hidden\"\n                >\n                    <div class=\"pt-2 pb-3 space-y-1\">\n                        <ResponsiveNavLink :href=\"route('dashboard')\" :active=\"route().current('dashboard')\">\n                            Dashboard\n                        </ResponsiveNavLink>\n                    </div>\n\n                    <!-- Responsive Settings Options -->\n                    <div class=\"pt-4 pb-1 border-t border-gray-200 dark:border-gray-600\">\n                        <div class=\"px-4\">\n                            <div class=\"font-medium text-base text-gray-800 dark:text-gray-200\">\n                                {{ $page.props.auth.user.name }}\n                            </div>\n                            <div class=\"font-medium text-sm text-gray-500\">{{ $page.props.auth.user.email }}</div>\n                        </div>\n\n                        <div class=\"mt-3 space-y-1\">\n                            <ResponsiveNavLink :href=\"route('profile.edit')\"> Profile </ResponsiveNavLink>\n                            <ResponsiveNavLink :href=\"route('logout')\" method=\"post\" as=\"button\">\n                                Log Out\n                            </ResponsiveNavLink>\n                        </div>\n                    </div>\n                </div>\n            </nav>\n\n            <!-- Page Heading -->\n            <header class=\"bg-white dark:bg-gray-800 shadow\" v-if=\"$slots.header\">\n                <div class=\"max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8\">\n                    <slot name=\"header\" />\n                </div>\n            </header>\n\n            <!-- Page Content -->\n            <main>\n                <slot />\n            </main>\n        </div>\n    </div>\n</template>\n"
  },
  {
    "path": "resources/js/Layouts/GuestLayout.vue",
    "content": "<script setup lang=\"ts\">\nimport ApplicationLogo from '@/Components/ApplicationLogo.vue';\nimport { Link } from '@inertiajs/vue3';\n</script>\n\n<template>\n    <div class=\"min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900\">\n        <div>\n            <Link href=\"/\">\n                <ApplicationLogo class=\"w-20 h-20 fill-current text-gray-500\" />\n            </Link>\n        </div>\n\n        <div\n            class=\"w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden sm:rounded-lg\"\n        >\n            <slot />\n        </div>\n    </div>\n</template>\n"
  },
  {
    "path": "resources/js/Layouts/MainLayout.vue",
    "content": "<script setup lang=\"ts\">\nimport { User } from \"@/types\";\nimport {\n    Disclosure,\n    DisclosureButton,\n    DisclosurePanel,\n    Menu,\n    MenuButton,\n    MenuItem,\n    MenuItems,\n} from \"@headlessui/vue\";\nimport {\n    Bars3Icon,\n    BellIcon,\n    XMarkIcon,\n    UserCircleIcon,\n} from \"@heroicons/vue/24/outline\";\nimport { Link } from \"@inertiajs/vue3\";\nimport { usePage } from \"@inertiajs/vue3\";\n\n\nconst page = usePage();\n\nconst user = page.props.auth.user;\n\nconst navigation = [\n    { name: \"Home\", href: route(\"home\"), current: route().current(\"home\") },\n    { name: \"Team\", href: \"#\", current: false },\n    { name: \"Projects\", href: \"#\", current: false },\n    { name: \"Calendar\", href: \"#\", current: false },\n    { name: \"Reports\", href: \"#\", current: false },\n];\n\nconst userNavigation = [\n    { name: \"Your Profile\", href: route(\"profile.edit\") },\n    { name: \"Settings\", href: \"#\" },\n];\n\nif (user) {\n    userNavigation.splice(1, 0, { name: \"Courses\", href: route(\"instructor.courses\", {user: user.name}) })\n    userNavigation.splice(2, 0, { name: \"My Learning\", href: route(\"learning.courses\") })\n}\n</script>\n\n<template>\n    <div class=\"min-h-full\">\n        <Disclosure as=\"nav\" class=\"bg-gray-800\" v-slot=\"{ open }\">\n            <div class=\"mx-auto max-w-7xl px-4 sm:px-6 lg:px-8\">\n                <div class=\"flex h-16 items-center justify-between\">\n                    <div class=\"flex items-center\">\n                        <div class=\"flex-shrink-0\">\n                            <div class=\"flex lg:justify-center lg:col-start-2\">\n                                <img src=\"/images/logo.svg\" />\n                            </div>\n                        </div>\n                        <div class=\"hidden md:block\">\n                            <div class=\"ml-10 flex items-baseline space-x-4\">\n                                <a\n                                    v-for=\"item in navigation\"\n                                    :key=\"item.name\"\n                                    :href=\"item.href\"\n                                    :class=\"[\n                                        item.current\n                                            ? 'bg-gray-900 text-white'\n                                            : 'text-gray-300 hover:bg-gray-700 hover:text-white',\n                                        'rounded-md px-3 py-2 text-sm font-medium',\n                                    ]\"\n                                    :aria-current=\"\n                                        item.current ? 'page' : undefined\n                                    \"\n                                    >{{ item.name }}</a\n                                >\n                            </div>\n                        </div>\n                    </div>\n                    <div class=\"hidden md:block\" v-if=\"user\">\n                        <div class=\"ml-4 flex items-center md:ml-6\">\n                            <button\n                                type=\"button\"\n                                class=\"relative rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\"\n                            >\n                                <span class=\"absolute -inset-1.5\" />\n                                <span class=\"sr-only\">View notifications</span>\n                                <BellIcon class=\"h-6 w-6\" aria-hidden=\"true\" />\n                            </button>\n\n                            <!-- Profile dropdown -->\n                            <Menu as=\"div\" class=\"relative ml-3\">\n                                <div>\n                                    <MenuButton\n                                        class=\"relative flex max-w-xs items-center rounded-full bg-gray-800 text-gray-400 hover:text-white text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\"\n                                    >\n                                        <span class=\"absolute -inset-1.5\" />\n                                        <span class=\"sr-only\"\n                                            >Open user menu</span\n                                        >\n                                        <UserCircleIcon\n                                            class=\"h-6 w-6\"\n                                            aria-hidden=\"true\"\n                                        />\n                                    </MenuButton>\n                                </div>\n                                <transition\n                                    enter-active-class=\"transition ease-out duration-100\"\n                                    enter-from-class=\"transform opacity-0 scale-95\"\n                                    enter-to-class=\"transform opacity-100 scale-100\"\n                                    leave-active-class=\"transition ease-in duration-75\"\n                                    leave-from-class=\"transform opacity-100 scale-100\"\n                                    leave-to-class=\"transform opacity-0 scale-95\"\n                                >\n                                    <MenuItems\n                                        class=\"absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none\"\n                                    >\n                                        <MenuItem\n                                            v-for=\"item in userNavigation\"\n                                            :key=\"item.name\"\n                                            v-slot=\"{ active }\"\n                                        >\n                                            <a\n                                                :href=\"item.href\"\n                                                :class=\"[\n                                                    active ? 'bg-gray-100' : '',\n                                                    'block px-4 py-2 text-sm text-gray-700',\n                                                ]\"\n                                                >{{ item.name }}</a\n                                            >\n                                        </MenuItem>\n\n                                        <MenuItem>\n                                            <Link\n                                                :href=\"route('logout')\"\n                                                method=\"post\"\n                                                as=\"button\"\n                                                class=\"ui-active:bg-gray-100 w-full block px-4 py-2 text-sm text-gray-700 text-left\"\n                                            >\n                                                Log Out\n                                            </Link>\n                                        </MenuItem>\n                                    </MenuItems>\n                                </transition>\n                            </Menu>\n                        </div>\n                    </div>\n                    <div class=\"hidden md:block\" v-else>\n                        <div class=\"ml-10 flex items-baseline space-x-4\">\n                            <Link\n                                :href=\"route('login')\"\n                                class=\"rounded-md px-3 py-2 text-gray-300 ring-1 ring-transparent transition hover:bg-gray-700 hover:text-white focus:outline-none focus-visible:ring-[#FF2D20] dark:text-white dark:hover:text-white/80 dark:focus-visible:ring-white\"\n                            >\n                                Log in\n                            </Link>\n\n                            <Link\n                                :href=\"route('register')\"\n                                class=\"rounded-md px-3 py-2 text-gray-300 ring-1 ring-transparent transition hover:bg-gray-700 hover:text-white focus:outline-none focus-visible:ring-[#FF2D20] dark:text-white dark:hover:text-white/80 dark:focus-visible:ring-white\"\n                            >\n                                Register\n                            </Link>\n                        </div>\n                    </div>\n                    <div class=\"-mr-2 flex md:hidden\">\n                        <!-- Mobile menu button -->\n                        <DisclosureButton\n                            class=\"relative inline-flex items-center justify-center rounded-md bg-gray-800 p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\"\n                        >\n                            <span class=\"absolute -inset-0.5\" />\n                            <span class=\"sr-only\">Open main menu</span>\n                            <Bars3Icon\n                                v-if=\"!open\"\n                                class=\"block h-6 w-6\"\n                                aria-hidden=\"true\"\n                            />\n                            <XMarkIcon\n                                v-else\n                                class=\"block h-6 w-6\"\n                                aria-hidden=\"true\"\n                            />\n                        </DisclosureButton>\n                    </div>\n                </div>\n            </div>\n\n            <DisclosurePanel class=\"md:hidden\">\n                <div class=\"space-y-1 px-2 pb-3 pt-2 sm:px-3\">\n                    <DisclosureButton\n                        v-for=\"item in navigation\"\n                        :key=\"item.name\"\n                        as=\"a\"\n                        :href=\"item.href\"\n                        :class=\"[\n                            item.current\n                                ? 'bg-gray-900 text-white'\n                                : 'text-gray-300 hover:bg-gray-700 hover:text-white',\n                            'block rounded-md px-3 py-2 text-base font-medium',\n                        ]\"\n                        :aria-current=\"item.current ? 'page' : undefined\"\n                        >{{ item.name }}</DisclosureButton\n                    >\n                </div>\n                <div class=\"border-t border-gray-700 pb-3 pt-4\" v-if=\"user\">\n                    <div class=\"flex items-center px-5\">\n                        <div class=\"flex-shrink-0\">\n                            <UserCircleIcon\n                                class=\"h-6 w-6\"\n                                aria-hidden=\"true\"\n                            />\n                        </div>\n                        <div class=\"ml-3\">\n                            <div\n                                class=\"text-base font-medium leading-none text-white\"\n                            >\n                                {{ user.name }}\n                            </div>\n                            <div\n                                class=\"text-sm font-medium leading-none text-gray-400\"\n                            >\n                                {{ user.email }}\n                            </div>\n                        </div>\n                        <button\n                            type=\"button\"\n                            class=\"relative ml-auto flex-shrink-0 rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\"\n                        >\n                            <span class=\"absolute -inset-1.5\" />\n                            <span class=\"sr-only\">View notifications</span>\n                            <BellIcon class=\"h-6 w-6\" aria-hidden=\"true\" />\n                        </button>\n                    </div>\n                    <div class=\"mt-3 space-y-1 px-2\">\n                        <DisclosureButton\n                            v-for=\"item in userNavigation\"\n                            :key=\"item.name\"\n                            as=\"a\"\n                            :href=\"item.href\"\n                            class=\"block rounded-md px-3 py-2 text-base font-medium text-gray-400 hover:bg-gray-700 hover:text-white\"\n                        >\n                            {{ item.name }}</DisclosureButton\n                        >\n                        <Link\n                            :href=\"route('logout')\"\n                            method=\"post\"\n                            as=\"button\"\n                            class=\"block rounded-md px-3 py-2 text-base font-medium text-gray-400 hover:bg-gray-700 hover:text-white\"\n                        >\n                            Log Out\n                        </Link>\n                    </div>\n                </div>\n                <div class=\"space-y-1 px-2 pb-3 pt-2 sm:px-3\" v-else>\n                    <DisclosureButton\n                        as=\"a\"\n                        :href=\"route('login')\"\n                        :class=\"[\n                            route().current('login') ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white',\n                            'block rounded-md px-3 py-2 text-base font-medium',\n                        ]\"\n                        :aria-current=\"route().current('login') ? 'page' : undefined\"\n                        >\n                          Log in\n                    </DisclosureButton>\n                    <DisclosureButton\n                        as=\"a\"\n                        :href=\"route('register')\"\n                        :class=\"[\n                            route().current('register') ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white',\n                            'block rounded-md px-3 py-2 text-base font-medium',\n                        ]\"\n                        :aria-current=\"route().current('register') ? 'page' : undefined\"\n                        >\n                          Register\n                    </DisclosureButton>\n                </div>\n            </DisclosurePanel>\n        </Disclosure>\n\n        <!-- Page Heading -->\n        <header class=\"bg-white dark:bg-gray-800 shadow\" v-if=\"$slots.header\">\n            <div class=\"max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8\">\n                <slot name=\"header\" />\n            </div>\n        </header>\n\n        <main>\n            <div class=\"mx-auto\">\n                <slot />\n            </div>\n        </main>\n    </div>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Auth/ConfirmPassword.vue",
    "content": "<script setup lang=\"ts\">\nimport GuestLayout from '@/Layouts/GuestLayout.vue';\nimport Label from '@/Components/Form/Label.vue';\nimport Input from '@/Components/Form/Input.vue';\nimport Button from '@/Components/Button.vue';\nimport { Head, useForm } from '@inertiajs/vue3';\n\nconst form = useForm({\n    password: '',\n});\n\nconst submit = () => {\n    form.post(route('password.confirm'), {\n        onFinish: () => {\n            form.reset();\n        },\n    });\n};\n</script>\n\n<template>\n    <GuestLayout>\n        <Head title=\"Confirm Password\" />\n\n        <div class=\"mb-4 text-sm text-gray-600 dark:text-gray-400\">\n            This is a secure area of the application. Please confirm your password before continuing.\n        </div>\n\n        <form @submit.prevent=\"submit\">\n            <div>\n                <Label label=\"Password\" required :error=\"form.errors.password\" >\n                    <Input\n                        id=\"password\"\n                        type=\"password\"\n                        v-model=\"form.password\"\n                        required\n                        autocomplete=\"current-password\"\n                        autofocus\n                    />\n                </Label>\n            </div>\n\n            <div class=\"flex justify-end mt-4\">\n                <Button class=\"ms-4\" size=\"lg\" :class=\"{ 'opacity-25': form.processing }\" :disabled=\"form.processing\">\n                    Confirm\n                </Button>\n            </div>\n        </form>\n    </GuestLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Auth/ForgotPassword.vue",
    "content": "<script setup lang=\"ts\">\nimport GuestLayout from '@/Layouts/GuestLayout.vue';\nimport Label from '@/Components/Form/Label.vue';\nimport Button from '@/Components/Button.vue';\nimport Input from '@/Components/Form/Input.vue';\nimport { Head, useForm } from '@inertiajs/vue3';\n\ndefineProps<{\n    status?: string;\n}>();\n\nconst form = useForm({\n    email: '',\n});\n\nconst submit = () => {\n    form.post(route('password.email'));\n};\n</script>\n\n<template>\n    <GuestLayout>\n        <Head title=\"Forgot Password\" />\n\n        <div class=\"mb-4 text-sm text-gray-600 dark:text-gray-400\">\n            Forgot your password? No problem. Just let us know your email address and we will email you a password reset\n            link that will allow you to choose a new one.\n        </div>\n\n        <div v-if=\"status\" class=\"mb-4 font-medium text-sm text-green-600 dark:text-green-400\">\n            {{ status }}\n        </div>\n\n        <form @submit.prevent=\"submit\">\n            <div>\n                <Label label=\"Email\" :error=\"form.errors.email\" required>\n\n                <Input\n                    id=\"email\"\n                    type=\"email\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.email\"\n                    required\n                    autofocus\n                    autocomplete=\"username\"\n                />\n                </Label>\n\n            </div>\n\n            <div class=\"flex items-center justify-end mt-4\">\n                <Button :class=\"{ 'opacity-25': form.processing }\" size=\"lg\" :disabled=\"form.processing\">\n                    Email Password Reset Link\n                </Button>\n            </div>\n        </form>\n    </GuestLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Auth/Login.vue",
    "content": "<script setup lang=\"ts\">\nimport Checkbox from '@/Components/Checkbox.vue';\nimport GuestLayout from '@/Layouts/GuestLayout.vue';\nimport Label from '@/Components/Form/Label.vue';\nimport Input from '@/Components/Form/Input.vue';\nimport Button from '@/Components/Button.vue';\nimport { Head, Link, useForm } from '@inertiajs/vue3';\nimport { usePage } from '@inertiajs/vue3';\nimport SocialiteLogins from '@/Components/SocialiteLogins.vue'\n\nconst page = usePage();\nconst isDevEnv = ['local', 'development'].includes((page.props as any).appEnv as string);\n\ndefineProps<{\n    canResetPassword?: boolean;\n    status?: string;\n}>();\n\nconst form = useForm({\n    email: '',\n    password: '',\n    remember: false,\n});\n\nconst submit = () => {\n    form.post(route('login'), {\n        onFinish: () => {\n            form.reset('password');\n        },\n    });\n};\n\nconst demoUsers = [\n    { label: 'Admin',   email: 'admin@admin.com',   password: 'password', color: 'bg-red-100 text-red-700 hover:bg-red-200 border-red-200' },\n    { label: 'Teacher', email: 'teacher@admin.com', password: 'password', color: 'bg-blue-100 text-blue-700 hover:bg-blue-200 border-blue-200' },\n    { label: 'Student', email: 'student@admin.com', password: 'password', color: 'bg-green-100 text-green-700 hover:bg-green-200 border-green-200' },\n];\n\nfunction loginAs(email: string, password: string) {\n    form.email = email;\n    form.password = password;\n    form.post(route('login'), {\n        onFinish: () => form.reset('password'),\n    });\n}\n</script>\n\n<template>\n    <GuestLayout>\n        <Head title=\"Log in\" />\n\n        <div v-if=\"status\" class=\"mb-4 font-medium text-sm text-green-600\">\n            {{ status }}\n        </div>\n\n        <form @submit.prevent=\"submit\">\n            <div>\n                <Label label=\"Email\" :error=\"form.errors.email\">\n\n                <Input\n                    id=\"email\"\n                    type=\"email\"\n                    v-model=\"form.email\"\n                    required\n                    autofocus\n                    autocomplete=\"username\"\n                />\n                </Label>\n            </div>\n\n            <div class=\"mt-4\">\n                <Label label=\"Password\" :error=\"form.errors.password\">\n\n                    <Input\n                        id=\"password\"\n                        type=\"password\"\n                        class=\"mt-1 block w-full\"\n                        v-model=\"form.password\"\n                        required\n                        autocomplete=\"current-password\"\n                    />\n                </Label>\n            </div>\n\n            <div class=\"block mt-4\">\n                <label class=\"flex items-center\">\n                    <Checkbox name=\"remember\" v-model:checked=\"form.remember\" />\n                    <span class=\"ms-2 text-sm text-gray-600 dark:text-gray-400\">Remember me</span>\n                </label>\n            </div>\n\n            <div class=\"flex items-center justify-end mt-4\">\n                <Link\n                    v-if=\"canResetPassword\"\n                    :href=\"route('password.request')\"\n                    class=\"underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800\"\n                >\n                    Forgot your password?\n                </Link>\n\n                <Button class=\"ms-4\" size=\"lg\" :class=\"{ 'opacity-25': form.processing }\" :disabled=\"form.processing\">\n                    Log in\n                </Button>\n            </div>\n        </form>\n        <SocialiteLogins />\n\n        <!-- Demo quick-login (dev / local only) -->\n        <div v-if=\"isDevEnv\" class=\"mt-6 border-t border-dashed border-gray-300 pt-5\">\n            <p class=\"text-xs text-center text-gray-400 mb-3 font-medium uppercase tracking-wide\">Demo Login Shortcuts</p>\n            <div class=\"flex gap-2 justify-center\">\n                <button\n                    v-for=\"demo in demoUsers\"\n                    :key=\"demo.label\"\n                    type=\"button\"\n                    :class=\"['flex-1 text-xs font-semibold py-2 px-3 rounded-lg border transition-colors', demo.color]\"\n                    :disabled=\"form.processing\"\n                    @click=\"loginAs(demo.email, demo.password)\"\n                >\n                    {{ demo.label }}\n                </button>\n            </div>\n        </div>\n    </GuestLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Auth/Register.vue",
    "content": "<script setup lang=\"ts\">\nimport GuestLayout from '@/Layouts/GuestLayout.vue';\nimport Label from '@/Components/Form/Label.vue';\nimport Button from '@/Components/Button.vue';\nimport Input from '@/Components/Form/Input.vue';\nimport { Head, Link, useForm } from '@inertiajs/vue3';\n\nconst form = useForm({\n    name: '',\n    email: '',\n    password: '',\n    password_confirmation: '',\n});\n\nconst submit = () => {\n    form.post(route('register'), {\n        onFinish: () => {\n            form.reset('password', 'password_confirmation');\n        },\n    });\n};\n</script>\n\n<template>\n    <GuestLayout>\n        <Head title=\"Register\" />\n\n        <form @submit.prevent=\"submit\">\n            <div>\n                <Label label=\"Name\" :error=\"form.errors.name\" required>\n\n                <Input\n                    id=\"name\"\n                    type=\"text\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.name\"\n                    required\n                    autofocus\n                    autocomplete=\"name\"\n                />\n                </Label>\n            </div>\n\n            <div class=\"mt-4\">\n                <Label label=\"Email\" :error=\"form.errors.email\" required >\n\n                <Input\n                    id=\"email\"\n                    type=\"email\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.email\"\n                    required\n                    autocomplete=\"username\"\n                />\n\n                </Label>\n            </div>\n\n            <div class=\"mt-4\">\n                <Label label=\"Password\" :error=\"form.errors.password\" required>\n\n                <Input\n                    id=\"password\"\n                    type=\"password\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.password\"\n                    required\n                    autocomplete=\"new-password\"\n                />\n\n                </Label>\n            </div>\n\n            <div class=\"mt-4\">\n                <Label label=\"Confirm Password\" :error=\"form.errors.password_confirmation\" required>\n\n                <Input\n                    id=\"password_confirmation\"\n                    type=\"password\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.password_confirmation\"\n                    required\n                    autocomplete=\"new-password\"\n                />\n\n                </Label>\n            </div>\n\n            <div class=\"flex items-center justify-end mt-4\">\n                <Link\n                    :href=\"route('login')\"\n                    class=\"underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800\"\n                >\n                    Already registered?\n                </Link>\n\n                <Button class=\"ms-4\" :class=\"{ 'opacity-25': form.processing }\" :disabled=\"form.processing\">\n                    Register\n                </Button>\n            </div>\n        </form>\n    </GuestLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Auth/ResetPassword.vue",
    "content": "<script setup lang=\"ts\">\nimport GuestLayout from '@/Layouts/GuestLayout.vue';\nimport Label from '@/Components/Form/Label.vue';\nimport Button from '@/Components/Button.vue';\nimport { Head, useForm } from '@inertiajs/vue3';\n\nconst props = defineProps<{\n    email: string;\n    token: string;\n}>();\n\nconst form = useForm({\n    token: props.token,\n    email: props.email,\n    password: '',\n    password_confirmation: '',\n});\n\nconst submit = () => {\n    form.post(route('password.store'), {\n        onFinish: () => {\n            form.reset('password', 'password_confirmation');\n        },\n    });\n};\n</script>\n\n<template>\n    <GuestLayout>\n        <Head title=\"Reset Password\" />\n\n        <form @submit.prevent=\"submit\">\n            <div>\n                <Label label=\"Email\" :error=\"form.errors.email\">\n\n                <Input\n                    id=\"email\"\n                    type=\"email\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.email\"\n                    required\n                    autofocus\n                    autocomplete=\"username\"\n                />\n\n                </Label>\n            </div>\n\n            <div class=\"mt-4\">\n                <Label label=\"Password\" :error=\"form.errors.password\">\n\n                <Input\n                    id=\"password\"\n                    type=\"password\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.password\"\n                    required\n                    autocomplete=\"new-password\"\n                />\n\n                </Label>\n            </div>\n\n            <div class=\"mt-4\">\n                <Label label=\"Confirm Password\" :error=\"form.errors.password_confirmation\" >\n\n                <Input\n                    id=\"password_confirmation\"\n                    type=\"password\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.password_confirmation\"\n                    required\n                    autocomplete=\"new-password\"\n                />\n\n                </Label>\n            </div>\n\n            <div class=\"flex items-center justify-end mt-4\">\n                <Button :class=\"{ 'opacity-25': form.processing }\" :disabled=\"form.processing\">\n                    Reset Password\n                </Button>\n            </div>\n        </form>\n    </GuestLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Auth/VerifyEmail.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport GuestLayout from '@/Layouts/GuestLayout.vue';\nimport Button from '@/Components/Button.vue';\nimport { Head, Link, useForm } from '@inertiajs/vue3';\n\nconst props = defineProps<{\n    status?: string;\n}>();\n\nconst form = useForm({});\n\nconst submit = () => {\n    form.post(route('verification.send'));\n};\n\nconst verificationLinkSent = computed(() => props.status === 'verification-link-sent');\n</script>\n\n<template>\n    <GuestLayout>\n        <Head title=\"Email Verification\" />\n\n        <div class=\"mb-4 text-sm text-gray-600 dark:text-gray-400\">\n            Thanks for signing up! Before getting started, could you verify your email address by clicking on the link\n            we just emailed to you? If you didn't receive the email, we will gladly send you another.\n        </div>\n\n        <div class=\"mb-4 font-medium text-sm text-green-600 dark:text-green-400\" v-if=\"verificationLinkSent\">\n            A new verification link has been sent to the email address you provided during registration.\n        </div>\n\n        <form @submit.prevent=\"submit\">\n            <div class=\"mt-4 flex items-center justify-between\">\n                <Button :class=\"{ 'opacity-25': form.processing }\" :disabled=\"form.processing\">\n                    Resend Verification Email\n                </Button>\n\n                <Link\n                    :href=\"route('logout')\"\n                    method=\"post\"\n                    as=\"button\"\n                    class=\"underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800\"\n                    >Log Out</Link\n                >\n            </div>\n        </form>\n    </GuestLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Course/Course.vue",
    "content": "<script setup lang=\"ts\">\nimport { Head, Link, usePage } from \"@inertiajs/vue3\";\nimport MainLayout from \"@/Layouts/MainLayout.vue\";\nimport { computed } from \"vue\";\nimport { Course } from \"@/types\";\nimport { ref } from \"vue\";\nimport Instractor from \"./Partials/Instractor.vue\";\nimport Pricing from \"./Partials/Pricing.vue\";\n\nconst page = usePage();\n\nconst user = computed(() => page.props.auth.user);\n\nconst props = defineProps<{\n    course: Course;\n}>();\n\nconst stats = [\n    { name: \"Number of student\", value: props.course.students_count },\n    { name: \"Number of section\", value: props.course.sections_count },\n    { name: \"Number of exams\", value: props.course.exams_count },\n    { name: \"Number of lessons\", value: props.course.lessons_count },\n];\n\nlet loading = ref(false);\nfunction startLearning(): void {\n    if (!user) {\n        return;\n    }\n    if (loading) {\n        return;\n    }\n\n    loading = ref(true);\n\n    window.axios\n        .post(route(`course.subscribe`, { course: props.course.id }))\n        .then((res) => {\n            window.location.replace(\"/learning/my-courses\");\n        })\n        .catch((error) => {\n            if (error.response.status === 401) {\n                window.location.replace(\"/login\");\n            }\n        })\n        .finally(() => {\n            loading = ref(false);\n        });\n}\n</script>\n<template>\n    <MainLayout>\n        <Head title=\"Course\" />\n        <div\n            class=\"relative isolate overflow-hidden bg-gray-900 py-24 sm:py-32\"\n        >\n            <img\n                src=\"https://images.unsplash.com/photo-1521737604893-d14cc237f11d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&crop=focalpoint&fp-y=.8&w=2830&h=1500&q=80&blend=111827&sat=-100&exp=15&blend-mode=multiply\"\n                alt=\"\"\n                class=\"absolute inset-0 -z-10 h-full w-full object-cover object-right md:object-center\"\n            />\n            <div\n                class=\"hidden sm:absolute sm:-top-10 sm:right-1/2 sm:-z-10 sm:mr-10 sm:block sm:transform-gpu sm:blur-3xl\"\n                aria-hidden=\"true\"\n            >\n                <div\n                    class=\"aspect-[1097/845] w-[68.5625rem] bg-gradient-to-tr from-[#ff4694] to-[#776fff] opacity-20\"\n                    style=\"\n                        clip-path: polygon(\n                            74.1% 44.1%,\n                            100% 61.6%,\n                            97.5% 26.9%,\n                            85.5% 0.1%,\n                            80.7% 2%,\n                            72.5% 32.5%,\n                            60.2% 62.4%,\n                            52.4% 68.1%,\n                            47.5% 58.3%,\n                            45.2% 34.5%,\n                            27.5% 76.7%,\n                            0.1% 64.9%,\n                            17.9% 100%,\n                            27.6% 76.8%,\n                            76.1% 97.7%,\n                            74.1% 44.1%\n                        );\n                    \"\n                />\n            </div>\n            <div\n                class=\"absolute -top-52 left-1/2 -z-10 -translate-x-1/2 transform-gpu blur-3xl sm:top-[-28rem] sm:ml-16 sm:translate-x-0 sm:transform-gpu\"\n                aria-hidden=\"true\"\n            >\n                <div\n                    class=\"aspect-[1097/845] w-[68.5625rem] bg-gradient-to-tr from-[#ff4694] to-[#776fff] opacity-20\"\n                    style=\"\n                        clip-path: polygon(\n                            74.1% 44.1%,\n                            100% 61.6%,\n                            97.5% 26.9%,\n                            85.5% 0.1%,\n                            80.7% 2%,\n                            72.5% 32.5%,\n                            60.2% 62.4%,\n                            52.4% 68.1%,\n                            47.5% 58.3%,\n                            45.2% 34.5%,\n                            27.5% 76.7%,\n                            0.1% 64.9%,\n                            17.9% 100%,\n                            27.6% 76.8%,\n                            76.1% 97.7%,\n                            74.1% 44.1%\n                        );\n                    \"\n                />\n            </div>\n            <div class=\"mx-auto container px-6 lg:px-8\">\n                <div class=\"mx-auto max-w-2xl lg:mx-0\">\n                    <h2\n                        class=\"text-2xl font-bold tracking-tight text-white sm:text-4xl\"\n                    >\n                        {{ course.title }}\n                    </h2>\n                    <p class=\"mt-6 text-lg leading-8 text-gray-300\">\n                        {{ course.description }}\n                    </p>\n                </div>\n\n                <div class=\"mx-auto mt-10 max-w-2xl lg:mx-0 lg:max-w-none\">\n                    <button\n                        class=\"block py-3 px-6 text-center rounded-md text-white font-medium bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600\"\n                        type=\"button\"\n                        @click.prevent=\"startLearning\"\n                        v-if=\"user\"\n                    >\n                        Start Learning\n                    </button>\n                    <dl\n                        class=\"mt-16 grid grid-cols-1 gap-8 sm:mt-20 sm:grid-cols-2 lg:grid-cols-4\"\n                    >\n                        <div\n                            v-for=\"stat in stats\"\n                            :key=\"stat.name\"\n                            class=\"flex flex-col-reverse\"\n                        >\n                            <dt class=\"text-base leading-7 text-gray-300\">\n                                {{ stat.name }}\n                            </dt>\n                            <dd\n                                class=\"text-2xl font-bold leading-9 tracking-tight text-white\"\n                            >\n                                {{ stat.value }}\n                            </dd>\n                        </div>\n                    </dl>\n                </div>\n            </div>\n        </div>\n        <div class=\"mx-auto container px-6 py-14 lg:px-8\">\n            <div class=\"grid grid-cols-3 gap-6\">\n                <div class=\"col-span-2\">\n                    <div class=\"px-4 sm:px-0\">\n                        <h3\n                            class=\"text-base font-semibold leading-7 text-gray-900\"\n                        >\n                            Course Information\n                        </h3>\n                    </div>\n                    <div class=\"mt-6 border-t border-gray-100\">\n                        <dl class=\"divide-y divide-gray-100\">\n                            <div\n                                class=\"px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0\"\n                            >\n                                <dt\n                                    class=\"text-sm font-medium leading-6 text-gray-900\"\n                                >\n                                    Features\n                                </dt>\n                                <dd\n                                    class=\"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0\"\n                                >\n                                    {{ course.features }}\n                                </dd>\n                            </div>\n                            <div\n                                class=\"px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0\"\n                            >\n                                <dt\n                                    class=\"text-sm font-medium leading-6 text-gray-900\"\n                                >\n                                    Requirements\n                                </dt>\n                                <dd\n                                    class=\"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0\"\n                                >\n                                    {{ course.requirements }}\n                                </dd>\n                            </div>\n                            <div\n                                class=\"px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0\"\n                            >\n                                <dt\n                                    class=\"text-sm font-medium leading-6 text-gray-900\"\n                                >\n                                    Start date\n                                </dt>\n                                <dd\n                                    class=\"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0\"\n                                >\n                                    {{ course.start_date }}\n                                </dd>\n                            </div>\n                            <div\n                                class=\"px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0\"\n                            >\n                                <dt\n                                    class=\"text-sm font-medium leading-6 text-gray-900\"\n                                >\n                                    Certified\n                                </dt>\n                                <dd\n                                    class=\"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0\"\n                                >\n                                    Yes\n                                </dd>\n                            </div>\n                            <div\n                                class=\"px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0\"\n                            >\n                                <dt\n                                    class=\"text-sm font-medium leading-6 text-gray-900\"\n                                >\n                                    Subjects\n                                </dt>\n                                <dd\n                                    class=\"mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0\"\n                                ></dd>\n                            </div>\n                            <div\n                                class=\"px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0\"\n                            >\n                                <dt\n                                    class=\"text-sm font-medium leading-6 text-gray-900\"\n                                >\n                                    Topics\n                                </dt>\n                                <dd\n                                    class=\"mt-2 text-sm text-gray-900 sm:col-span-2 sm:mt-0\"\n                                >\n                                    <dl\n                                        class=\"max-w-md text-gray-900 divide-y divide-gray-200 dark:divide-gray-700\"\n                                    >\n                                        <div\n                                            class=\"flex flex-col pb-3\"\n                                            v-for=\"topic in course.topics\"\n                                            :key=\"topic.id\"\n                                        >\n                                            <dt class=\"mb-1\">\n                                                {{ topic.title }}\n                                            </dt>\n                                            <dd class=\"\">\n                                                {{ topic.description }}\n                                            </dd>\n                                        </div>\n                                    </dl>\n                                </dd>\n                            </div>\n                        </dl>\n                    </div>\n\n                    <template\n                        v-for=\"teacher in course.teachers\"\n                        :key=\"teacher.id\"\n                    >\n                        <Instractor :user=\"teacher\" />\n                    </template>\n                </div>\n                <div class=\"col-span-1\">\n                    <Pricing :course=\"course\" />\n                </div>\n            </div>\n        </div>\n    </MainLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Course/Partials/Instractor.vue",
    "content": "<script setup lang=\"ts\">\nimport { User } from \"@/types\";\n\nconst props = defineProps<{\n    user: User;\n}>();\n</script>\n\n<template>\n    <!-- User Profile Tab Card -->\n    <div class=\"flex flex-row rounded-lg border border-gray-200/80 bg-white p-6\">\n        <!-- Avaar Container -->\n        <div class=\"relative\">\n            <!-- User Avatar -->\n            <img class=\"w-40 h-40 rounded-md object-cover\"\n                src=\"https://png.pngtree.com/png-vector/20220709/ourmid/pngtree-businessman-user-avatar-wearing-suit-with-red-tie-png-image_5809521.png\"\n                alt=\"User\" />\n\n            <!-- Online Status Dot -->\n            <div class=\"absolute -right-3 bottom-5 h-5 w-5 sm:top-2 rounded-full border-4 border-white bg-green-400 sm:invisible md:visible\"\n                title=\"User is online\"></div>\n        </div>\n\n        <!-- Meta Body -->\n        <div class=\"flex flex-col overflow-hidden px-6\">\n            <!-- Username Container -->\n            <div class=\"flex h-8 flex-row\">\n                <!-- Username -->\n                <a href=\"https://github.com/EgoistDeveloper/\" target=\"_blank\">\n                    <h2 class=\"text-lg font-semibold\">\n                        EgoistDeveloper\n                    </h2>\n                </a>\n\n                <!-- User Verified -->\n                <svg class=\"my-auto ml-2 h-5 fill-blue-400\" xmlns=\"http://www.w3.org/2000/svg\"\n                    xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n                    <path\n                        d=\"M23,12L20.56,9.22L20.9,5.54L17.29,4.72L15.4,1.54L12,3L8.6,1.54L6.71,4.72L3.1,5.53L3.44,9.21L1,12L3.44,14.78L3.1,18.47L6.71,19.29L8.6,22.47L12,21L15.4,22.46L17.29,19.28L20.9,18.46L20.56,14.78L23,12M10,17L6,13L7.41,11.59L10,14.17L16.59,7.58L18,9L10,17Z\" />\n                </svg>\n            </div>\n\n            <!-- Meta Badges -->\n            <div class=\"my-2 flex flex-row space-x-2\">\n                <!-- Badge Role -->\n                <div class=\"flex flex-row\">\n                    <svg class=\"mr-2 h-4 w-4 fill-gray-500/80\" xmlns=\"http://www.w3.org/2000/svg\"\n                        xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\"\n                        viewBox=\"0 0 24 24\">\n                        <path\n                            d=\"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M7.07,18.28C7.5,17.38 10.12,16.5 12,16.5C13.88,16.5 16.5,17.38 16.93,18.28C15.57,19.36 13.86,20 12,20C10.14,20 8.43,19.36 7.07,18.28M18.36,16.83C16.93,15.09 13.46,14.5 12,14.5C10.54,14.5 7.07,15.09 5.64,16.83C4.62,15.5 4,13.82 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,13.82 19.38,15.5 18.36,16.83M12,6C10.06,6 8.5,7.56 8.5,9.5C8.5,11.44 10.06,13 12,13C13.94,13 15.5,11.44 15.5,9.5C15.5,7.56 13.94,6 12,6M12,11A1.5,1.5 0 0,1 10.5,9.5A1.5,1.5 0 0,1 12,8A1.5,1.5 0 0,1 13.5,9.5A1.5,1.5 0 0,1 12,11Z\" />\n                    </svg>\n\n                    <div class=\"text-xs text-gray-400/80 hover:text-gray-400\">\n                        Fullstack Developer\n                    </div>\n                </div>\n\n                <!-- Badge Location -->\n                <div class=\"flex flex-row\">\n                    <svg class=\"mr-2 h-4 w-4 fill-gray-500/80\" xmlns=\"http://www.w3.org/2000/svg\"\n                        xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\"\n                        viewBox=\"0 0 24 24\">\n                        <path\n                            d=\"M12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5M12,2A7,7 0 0,1 19,9C19,14.25 12,22 12,22C12,22 5,14.25 5,9A7,7 0 0,1 12,2M12,4A5,5 0 0,0 7,9C7,10 7,12 12,18.71C17,12 17,10 17,9A5,5 0 0,0 12,4Z\" />\n                    </svg>\n\n                    <div class=\"text-xs text-gray-400/80 hover:text-gray-400\">\n                        Istanbul\n                    </div>\n                </div>\n\n                <!-- Badge Email-->\n                <div class=\"flex flex-row\">\n                    <svg class=\"mr-2 h-4 w-4 fill-gray-500/80\" xmlns=\"http://www.w3.org/2000/svg\"\n                        xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\"\n                        viewBox=\"0 0 24 24\">\n                        <path\n                            d=\"M12,15C12.81,15 13.5,14.7 14.11,14.11C14.7,13.5 15,12.81 15,12C15,11.19 14.7,10.5 14.11,9.89C13.5,9.3 12.81,9 12,9C11.19,9 10.5,9.3 9.89,9.89C9.3,10.5 9,11.19 9,12C9,12.81 9.3,13.5 9.89,14.11C10.5,14.7 11.19,15 12,15M12,2C14.75,2 17.1,3 19.05,4.95C21,6.9 22,9.25 22,12V13.45C22,14.45 21.65,15.3 21,16C20.3,16.67 19.5,17 18.5,17C17.3,17 16.31,16.5 15.56,15.5C14.56,16.5 13.38,17 12,17C10.63,17 9.45,16.5 8.46,15.54C7.5,14.55 7,13.38 7,12C7,10.63 7.5,9.45 8.46,8.46C9.45,7.5 10.63,7 12,7C13.38,7 14.55,7.5 15.54,8.46C16.5,9.45 17,10.63 17,12V13.45C17,13.86 17.16,14.22 17.46,14.53C17.76,14.84 18.11,15 18.5,15C18.92,15 19.27,14.84 19.57,14.53C19.87,14.22 20,13.86 20,13.45V12C20,9.81 19.23,7.93 17.65,6.35C16.07,4.77 14.19,4 12,4C9.81,4 7.93,4.77 6.35,6.35C4.77,7.93 4,9.81 4,12C4,14.19 4.77,16.07 6.35,17.65C7.93,19.23 9.81,20 12,20H17V22H12C9.25,22 6.9,21 4.95,19.05C3,17.1 2,14.75 2,12C2,9.25 3,6.9 4.95,4.95C6.9,3 9.25,2 12,2Z\" />\n                    </svg>\n\n                    <div class=\"text-xs text-gray-400/80 hover:text-gray-400\">\n                        who@am.i\n                    </div>\n                </div>\n            </div>\n\n            <!-- Mini Cards -->\n            <div class=\"mt-2 flex flex-row items-center space-x-5\">\n                <!-- Comments -->\n                <a href=\"#\"\n                    class=\"flex h-20 w-40 flex-col items-center justify-center rounded-md border border-dashed border-gray-200 transition-colors duration-100 ease-in-out hover:border-gray-400/80\">\n                    <div class=\"flex flex-row items-center justify-center\">\n                        <svg class=\"mr-3 fill-gray-500/95\" xmlns=\"http://www.w3.org/2000/svg\"\n                            xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\"\n                            viewBox=\"0 0 24 24\">\n                            <path\n                                d=\"M12,23A1,1 0 0,1 11,22V19H7A2,2 0 0,1 5,17V7A2,2 0 0,1 7,5H21A2,2 0 0,1 23,7V17A2,2 0 0,1 21,19H16.9L13.2,22.71C13,22.89 12.76,23 12.5,23H12M13,17V20.08L16.08,17H21V7H7V17H13M3,15H1V3A2,2 0 0,1 3,1H19V3H3V15M9,9H19V11H9V9M9,13H17V15H9V13Z\" />\n                        </svg>\n\n                        <span class=\"font-bold text-gray-600\">\n                            4.6K\n                        </span>\n                    </div>\n\n                    <div class=\"mt-2 text-sm text-gray-400\">\n                        Comments\n                    </div>\n                </a>\n\n                <!-- Projects -->\n                <a href=\"#\"\n                    class=\"flex h-20 w-40 flex-col items-center justify-center rounded-md border border-dashed border-gray-200 transition-colors duration-100 ease-in-out hover:border-gray-400/80\">\n                    <div class=\"flex flex-row items-center justify-center\">\n                        <svg class=\"mr-3 fill-gray-500/95\" xmlns=\"http://www.w3.org/2000/svg\"\n                            xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\"\n                            viewBox=\"0 0 24 24\">\n                            <path\n                                d=\"M2.5 19.6L3.8 20.2V11.2L1.4 17C1 18.1 1.5 19.2 2.5 19.6M15.2 4.8L20.2 16.8L12.9 19.8L7.9 7.9V7.8L15.2 4.8M15.3 2.8C15 2.8 14.8 2.8 14.5 2.9L7.1 6C6.4 6.3 5.9 7 5.9 7.8C5.9 8 5.9 8.3 6 8.6L11 20.5C11.3 21.3 12 21.7 12.8 21.7C13.1 21.7 13.3 21.7 13.6 21.6L21 18.5C22 18.1 22.5 16.9 22.1 15.9L17.1 4C16.8 3.2 16 2.8 15.3 2.8M10.5 9.9C9.9 9.9 9.5 9.5 9.5 8.9S9.9 7.9 10.5 7.9C11.1 7.9 11.5 8.4 11.5 8.9S11.1 9.9 10.5 9.9M5.9 19.8C5.9 20.9 6.8 21.8 7.9 21.8H9.3L5.9 13.5V19.8Z\" />\n                        </svg>\n\n                        <span class=\"font-bold text-gray-600\">\n                            45\n                        </span>\n                    </div>\n\n                    <div class=\"mt-2 text-sm text-gray-400\">\n                        Projects\n                    </div>\n                </a>\n\n                <!-- Projects -->\n                <a href=\"#\"\n                    class=\"flex h-20 w-40 flex-col items-center justify-center rounded-md border border-dashed border-gray-200 transition-colors duration-100 ease-in-out hover:border-gray-400/80\">\n                    <div class=\"flex flex-row items-center justify-center\">\n                        <svg class=\"mr-3 fill-gray-500/95\" xmlns=\"http://www.w3.org/2000/svg\"\n                            xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\"\n                            viewBox=\"0 0 24 24\">\n                            <path\n                                d=\"M5.68,19.74C7.16,20.95 9,21.75 11,21.95V19.93C9.54,19.75 8.21,19.17 7.1,18.31M13,19.93V21.95C15,21.75 16.84,20.95 18.32,19.74L16.89,18.31C15.79,19.17 14.46,19.75 13,19.93M18.31,16.9L19.74,18.33C20.95,16.85 21.75,15 21.95,13H19.93C19.75,14.46 19.17,15.79 18.31,16.9M15,12A3,3 0 0,0 12,9A3,3 0 0,0 9,12A3,3 0 0,0 12,15A3,3 0 0,0 15,12M4.07,13H2.05C2.25,15 3.05,16.84 4.26,18.32L5.69,16.89C4.83,15.79 4.25,14.46 4.07,13M5.69,7.1L4.26,5.68C3.05,7.16 2.25,9 2.05,11H4.07C4.25,9.54 4.83,8.21 5.69,7.1M19.93,11H21.95C21.75,9 20.95,7.16 19.74,5.68L18.31,7.1C19.17,8.21 19.75,9.54 19.93,11M18.32,4.26C16.84,3.05 15,2.25 13,2.05V4.07C14.46,4.25 15.79,4.83 16.9,5.69M11,4.07V2.05C9,2.25 7.16,3.05 5.68,4.26L7.1,5.69C8.21,4.83 9.54,4.25 11,4.07Z\" />\n                        </svg>\n\n                        <span class=\"font-bold text-gray-600\">\n                            120K\n                        </span>\n                    </div>\n\n                    <div class=\"mt-2 text-sm text-gray-400\">\n                        Downloads\n                    </div>\n                </a>\n            </div>\n        </div>\n\n        <!-- Right Actions Container -->\n        <div class=\"w-100 flex flex-grow flex-col items-end justify-start\">\n            <div class=\"flex flex-row space-x-3\">\n                <!-- Follow Button -->\n                <button\n                    class=\"flex rounded-md bg-blue-500 py-2 px-4 text-white transition-all duration-150 ease-in-out hover:bg-blue-600\">\n                    <svg class=\"mr-2 fill-current\" xmlns=\"http://www.w3.org/2000/svg\"\n                        xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\"\n                        viewBox=\"0 0 24 24\">\n                        <path d=\"M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z\" />\n                    </svg>\n\n                    Follow\n                </button>\n\n                <!-- More Actions Button -->\n                <button\n                    class=\"flex rounded-md bg-gray-100 py-2 px-1 text-white transition-all duration-150 ease-in-out hover:bg-gray-200\">\n                    <svg class=\"fill-gray-500\" xmlns=\"http://www.w3.org/2000/svg\"\n                        xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"24\" height=\"24\"\n                        viewBox=\"0 0 24 24\">\n                        <path\n                            d=\"M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z\" />\n                    </svg>\n                </button>\n            </div>\n        </div>\n    </div>\n</template>"
  },
  {
    "path": "resources/js/Pages/Course/Partials/Pricing.vue",
    "content": "<script setup lang=\"ts\">\nimport { Course } from '@/types'\nimport { computed, ref } from \"vue\";\nimport { usePage } from \"@inertiajs/vue3\";\n\nconst page = usePage();\n\nconst user = computed(() => page.props.auth.user);\n\nconst props = defineProps<{\n    course: Course\n}>()\n\nlet loading = ref(false);\nfunction startLearning():void {\n    if (!user) {\n        return;\n    }\n    if (loading) {\n        return;\n    }\n\n    loading = ref(true);\n\n    window.axios\n        .post(route(`course.subscribe`, { course: props.course.id }))\n        .then((res) => {\n            window.location.replace(\"/learning/my-courses\");\n        })\n        .catch((error) => {\n            if (error.response.status === 401) {\n                window.location.replace(\"/login\");\n            }\n        })\n        .finally(() => {\n            loading = ref(false);\n        });\n}\n\n</script>\n\n<template>\n    <div class=\"bg-gray-800 rounded-lg shadow-lg p-6 transform hover:scale-105 transition duration-300\">\n        <div class=\"mb-8\">\n            <h3 class=\"text-2xl font-semibold text-white\">\n                Pro\n            </h3>\n            <p class=\"mt-4 text-gray-400\">\n                Ideal for growing businesses and enterprises.\n            </p>\n        </div>\n        <div class=\"mb-8\">\n            <span class=\"text-5xl font-extrabold text-white\">${{ course.price }}</span>\n        </div>\n        <h3 class=\"text-2xl text-white\">\n            This course includes:\n        </h3>\n        <ul class=\"mb-8 space-y-4 text-gray-400\">\n            <li class=\"flex items-center\">\n                <svg class=\"h-6 w-6 text-green-500 mr-2\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n                    viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                    <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n                </svg>\n                <span>9.5 hours on-demand video</span>\n            </li>\n            <li class=\"flex items-center\">\n                <svg class=\"h-6 w-6 text-green-500 mr-2\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n                    viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                    <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n                </svg>\n                <span>95 downloadable resources</span>\n            </li>\n            <li class=\"flex items-center\">\n                <svg class=\"h-6 w-6 text-green-500 mr-2\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n                    viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                    <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n                </svg>\n                <span>Access on mobile and TV</span>\n            </li>\n            <li class=\"flex items-center\">\n                <svg class=\"h-6 w-6 text-green-500 mr-2\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n                    viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                    <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n                </svg>\n                <span>Full lifetime access</span>\n            </li>\n            <li class=\"flex items-center\">\n                <svg class=\"h-6 w-6 text-green-500 mr-2\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n                    viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n                    <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\" />\n                </svg>\n                <span>Certificate of completion</span>\n            </li>\n        </ul>\n        <button\n            class=\"block w-full py-3 px-6 text-center rounded-md text-white font-medium bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600\"\n            type=\"button\" @click.prevent=\"startLearning\" v-if=\"user\">\n            Start Learning\n        </button>\n    </div>\n</template>"
  },
  {
    "path": "resources/js/Pages/Home/Home.vue",
    "content": "<script setup lang=\"ts\">\nimport { Course, Subject } from \"@/types\";\nimport { Head, Link } from \"@inertiajs/vue3\";\nimport { ref, onMounted, onUnmounted, computed } from \"vue\";\nimport { usePage } from \"@inertiajs/vue3\";\nimport {\n    Menu,\n    MenuButton,\n    MenuItem,\n    MenuItems,\n} from \"@headlessui/vue\";\nimport {\n    Bars3Icon,\n    XMarkIcon,\n    AcademicCapIcon,\n    BookOpenIcon,\n    ClipboardDocumentCheckIcon,\n    TrophyIcon,\n    UserGroupIcon,\n    ChatBubbleLeftRightIcon,\n    EnvelopeIcon,\n    ChevronRightIcon,\n    UserCircleIcon,\n} from \"@heroicons/vue/24/outline\";\n\nconst props = defineProps<{\n    subjects: Subject[];\n    featuredCourses: Course[];\n}>();\n\nconst page = usePage();\nconst user = computed(() => page.props.auth?.user);\n\n// Mobile menu\nconst mobileMenuOpen = ref(false);\n\n// Hero slides\nconst slides = [\n    {\n        heading: \"Master New Skills Online\",\n        sub: \"Learn from expert instructors with hands-on courses and real certifications\",\n        cta: \"Explore Courses\",\n        ctaHref: \"#courses\",\n    },\n    {\n        heading: \"Earn Industry Certifications\",\n        sub: \"Prove your expertise with recognized certificates upon completing exams\",\n        cta: \"View Exams\",\n        ctaHref: \"#subjects\",\n    },\n    {\n        heading: \"Learn at Your Own Pace\",\n        sub: \"Access courses and exams any time, anywhere, on any device\",\n        cta: \"Get Started Free\",\n        ctaHref: \"/register\",\n    },\n];\n\nconst currentSlide = ref(0);\nlet slideInterval: ReturnType<typeof setInterval>;\n\nonMounted(() => {\n    slideInterval = setInterval(() => {\n        currentSlide.value = (currentSlide.value + 1) % slides.length;\n    }, 5000);\n});\n\nonUnmounted(() => {\n    clearInterval(slideInterval);\n});\n\n// Testimonials\nconst testimonials = [\n    {\n        name: \"Sarah Johnson\",\n        role: \"Software Engineer\",\n        avatar: \"https://i.pravatar.cc/80?img=47\",\n        text: \"The courses here are incredibly well-structured. I landed my dream job just 3 months after completing the web development track!\",\n    },\n    {\n        name: \"Michael Chen\",\n        role: \"Data Analyst\",\n        avatar: \"https://i.pravatar.cc/80?img=12\",\n        text: \"The certification exams are challenging but fair. Having this certification on my resume made a huge difference in my job search.\",\n    },\n    {\n        name: \"Amara Osei\",\n        role: \"UX Designer\",\n        avatar: \"https://i.pravatar.cc/80?img=32\",\n        text: \"Excellent learning experience! The combination of course content and hands-on exams really helped me build practical skills.\",\n    },\n];\n\n// Emoji icons for subjects\nconst subjectEmojis = [\n    \"💻\", \"📊\", \"🎨\", \"🔬\", \"📱\", \"🌐\",\n    \"🤖\", \"📈\", \"🎯\", \"⚙️\", \"📝\", \"🏆\",\n    \"🧠\", \"🔐\", \"📡\", \"🖥️\",\n];\nfunction getSubjectEmoji(index: number): string {\n    return subjectEmojis[index % subjectEmojis.length];\n}\n\nfunction starsFilled(rating: number | string): number {\n    return Math.round(Number(rating) || 0);\n}\n\n// Contact form\nconst contactForm = ref({ name: \"\", email: \"\", message: \"\" });\nfunction submitContact() {\n    // placeholder — wire up your controller when ready\n    alert(\"Message sent! We'll get back to you soon.\");\n    contactForm.value = { name: \"\", email: \"\", message: \"\" };\n}\n\n// Course card helpers\nfunction discountedPrice(course: Course): number {\n    if (!course.discount || course.discount <= 0) return course.price;\n    return Math.round(course.price / (1 - course.discount / 100));\n}\n</script>\n\n<template>\n    <div class=\"min-h-screen bg-white\">\n        <Head title=\"Welcome — Learn, Exam & Get Certified\" />\n\n        <!-- ===================== NAVIGATION ===================== -->\n        <header class=\"bg-white border-b border-gray-200 sticky top-0 z-50 shadow-sm\">\n            <div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n                <div class=\"flex items-center justify-between h-16\">\n\n                    <!-- Logo + Desktop Nav -->\n                    <div class=\"flex items-center gap-8\">\n                        <Link :href=\"route('home')\" class=\"flex-shrink-0\">\n                            <img src=\"/images/logo.svg\" alt=\"Examinee\" class=\"h-8 w-auto\" />\n                        </Link>\n                        <nav class=\"hidden md:flex items-center space-x-1\">\n                            <a href=\"#courses\"\n                                class=\"text-gray-700 hover:text-purple-700 font-medium px-3 py-2 rounded-md text-sm transition-colors\">Courses</a>\n                            <a href=\"#subjects\"\n                                class=\"text-gray-700 hover:text-purple-700 font-medium px-3 py-2 rounded-md text-sm transition-colors\">Subjects</a>\n                            <a href=\"#certifications\"\n                                class=\"text-gray-700 hover:text-purple-700 font-medium px-3 py-2 rounded-md text-sm transition-colors\">Certifications</a>\n                            <a href=\"#contact\"\n                                class=\"text-gray-700 hover:text-purple-700 font-medium px-3 py-2 rounded-md text-sm transition-colors\">Contact</a>\n                        </nav>\n                    </div>\n\n                    <!-- Right actions -->\n                    <div class=\"flex items-center gap-3\">\n                        <template v-if=\"user\">\n                            <Link :href=\"route('learning.courses')\"\n                                class=\"hidden md:block text-sm text-gray-700 hover:text-purple-700 font-medium px-3 py-2 transition-colors\">\n                                My Learning\n                            </Link>\n                            <Menu as=\"div\" class=\"relative\">\n                                <MenuButton\n                                    class=\"flex items-center gap-2 text-sm text-gray-700 hover:text-purple-700 font-medium px-3 py-2 rounded-full border border-gray-200 hover:border-purple-300 transition-colors\">\n                                    <UserCircleIcon class=\"h-5 w-5\" />\n                                    <span class=\"hidden sm:block max-w-[120px] truncate\">{{ user.name }}</span>\n                                </MenuButton>\n                                <transition enter-active-class=\"transition ease-out duration-100\"\n                                    enter-from-class=\"transform opacity-0 scale-95\"\n                                    enter-to-class=\"transform opacity-100 scale-100\"\n                                    leave-active-class=\"transition ease-in duration-75\"\n                                    leave-from-class=\"transform opacity-100 scale-100\"\n                                    leave-to-class=\"transform opacity-0 scale-95\">\n                                    <MenuItems\n                                        class=\"absolute right-0 mt-2 w-48 origin-top-right bg-white border border-gray-200 rounded-xl shadow-lg py-1 focus:outline-none\">\n                                        <MenuItem v-slot=\"{ active }\">\n                                        <Link :href=\"route('profile.edit')\"\n                                            :class=\"[active ? 'bg-gray-50' : '', 'block px-4 py-2 text-sm text-gray-700']\">\n                                            Profile\n                                        </Link>\n                                        </MenuItem>\n                                        <MenuItem v-slot=\"{ active }\">\n                                        <Link :href=\"route('learning.courses')\"\n                                            :class=\"[active ? 'bg-gray-50' : '', 'block px-4 py-2 text-sm text-gray-700']\">\n                                            My Learning\n                                        </Link>\n                                        </MenuItem>\n                                        <MenuItem v-slot=\"{ active }\">\n                                        <Link :href=\"route('logout')\" method=\"post\" as=\"button\"\n                                            :class=\"[active ? 'bg-gray-50' : '', 'w-full text-left block px-4 py-2 text-sm text-gray-700']\">\n                                            Log Out\n                                        </Link>\n                                        </MenuItem>\n                                    </MenuItems>\n                                </transition>\n                            </Menu>\n                        </template>\n                        <template v-else>\n                            <Link :href=\"route('login')\"\n                                class=\"hidden md:inline-flex text-sm font-medium text-purple-700 border border-purple-300 px-4 py-2 rounded-lg hover:bg-purple-50 transition-colors\">\n                                Log In\n                            </Link>\n                            <Link :href=\"route('register')\"\n                                class=\"inline-flex text-sm font-semibold text-white bg-purple-700 hover:bg-purple-800 px-4 py-2 rounded-lg transition-colors shadow-sm\">\n                                Sign Up Free\n                            </Link>\n                        </template>\n                        <!-- Mobile toggle -->\n                        <button @click=\"mobileMenuOpen = !mobileMenuOpen\"\n                            class=\"md:hidden p-2 rounded-lg text-gray-500 hover:bg-gray-100 transition-colors\">\n                            <XMarkIcon v-if=\"mobileMenuOpen\" class=\"h-6 w-6\" />\n                            <Bars3Icon v-else class=\"h-6 w-6\" />\n                        </button>\n                    </div>\n                </div>\n            </div>\n\n            <!-- Mobile menu -->\n            <div v-show=\"mobileMenuOpen\" class=\"md:hidden border-t border-gray-100 bg-white px-4 py-3 space-y-1\">\n                <a href=\"#courses\" @click=\"mobileMenuOpen = false\"\n                    class=\"block px-3 py-2 text-sm font-medium text-gray-700 hover:bg-purple-50 hover:text-purple-700 rounded-md\">Courses</a>\n                <a href=\"#subjects\" @click=\"mobileMenuOpen = false\"\n                    class=\"block px-3 py-2 text-sm font-medium text-gray-700 hover:bg-purple-50 hover:text-purple-700 rounded-md\">Subjects</a>\n                <a href=\"#certifications\" @click=\"mobileMenuOpen = false\"\n                    class=\"block px-3 py-2 text-sm font-medium text-gray-700 hover:bg-purple-50 hover:text-purple-700 rounded-md\">Certifications</a>\n                <a href=\"#contact\" @click=\"mobileMenuOpen = false\"\n                    class=\"block px-3 py-2 text-sm font-medium text-gray-700 hover:bg-purple-50 hover:text-purple-700 rounded-md\">Contact</a>\n                <div class=\"pt-2 border-t border-gray-100 flex gap-2\" v-if=\"!user\">\n                    <Link :href=\"route('login')\"\n                        class=\"flex-1 text-center text-sm font-medium text-purple-700 border border-purple-300 px-4 py-2 rounded-lg\">\n                        Log In\n                    </Link>\n                    <Link :href=\"route('register')\"\n                        class=\"flex-1 text-center text-sm font-semibold text-white bg-purple-700 px-4 py-2 rounded-lg\">\n                        Sign Up\n                    </Link>\n                </div>\n            </div>\n        </header>\n\n        <!-- ===================== HERO SECTION ===================== -->\n        <section\n            class=\"relative bg-gradient-to-br from-purple-950 via-indigo-900 to-blue-900 text-white overflow-hidden\">\n            <!-- Decorative blobs -->\n            <div class=\"absolute inset-0 overflow-hidden pointer-events-none\">\n                <div\n                    class=\"absolute -top-20 -left-20 w-96 h-96 bg-purple-500 rounded-full opacity-10 blur-3xl animate-pulse\">\n                </div>\n                <div\n                    class=\"absolute -bottom-10 -right-20 w-[500px] h-[500px] bg-indigo-400 rounded-full opacity-10 blur-3xl\">\n                </div>\n            </div>\n\n            <div class=\"relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 lg:py-32\">\n                <!-- Slide transition area -->\n                <transition name=\"hero-fade\" mode=\"out-in\">\n                    <div :key=\"currentSlide\" class=\"max-w-3xl\">\n                        <div\n                            class=\"inline-flex items-center gap-2 bg-white/10 backdrop-blur-sm rounded-full px-4 py-1.5 text-sm text-purple-200 font-medium mb-6 border border-white/20\">\n                            <AcademicCapIcon class=\"h-4 w-4 flex-shrink-0\" />\n                            <span>Trusted by 10,000+ learners worldwide</span>\n                        </div>\n                        <h1 class=\"text-4xl sm:text-5xl lg:text-6xl font-extrabold leading-tight tracking-tight mb-6\">\n                            {{ slides[currentSlide].heading }}\n                        </h1>\n                        <p class=\"text-xl text-purple-100 mb-10 leading-relaxed max-w-2xl\">\n                            {{ slides[currentSlide].sub }}\n                        </p>\n                        <div class=\"flex flex-wrap gap-4\">\n                            <a :href=\"slides[currentSlide].ctaHref\"\n                                class=\"inline-flex items-center gap-2 bg-white text-purple-900 font-bold px-8 py-4 rounded-xl hover:bg-purple-50 transition-colors shadow-lg text-lg\">\n                                {{ slides[currentSlide].cta }}\n                                <ChevronRightIcon class=\"h-5 w-5\" />\n                            </a>\n                            <a href=\"#courses\"\n                                class=\"inline-flex items-center gap-2 border-2 border-white/40 text-white font-semibold px-8 py-4 rounded-xl hover:bg-white/10 transition-colors text-lg\">\n                                Browse All Courses\n                            </a>\n                        </div>\n                    </div>\n                </transition>\n\n                <!-- Slide indicators -->\n                <div class=\"flex gap-2 mt-12\">\n                    <button v-for=\"(_, i) in slides\" :key=\"i\" @click=\"currentSlide = i\"\n                        :class=\"['h-2.5 rounded-full transition-all duration-300', currentSlide === i ? 'bg-white w-8' : 'bg-white/40 w-2.5']\"\n                        :aria-label=\"`Slide ${i + 1}`\">\n                    </button>\n                </div>\n            </div>\n\n            <!-- Stats bar -->\n            <div class=\"relative border-t border-white/10 bg-white/5 backdrop-blur-sm\">\n                <div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6\">\n                    <div class=\"grid grid-cols-2 md:grid-cols-4 gap-6 text-center\">\n                        <div>\n                            <div class=\"text-3xl font-bold text-white\">500+</div>\n                            <div class=\"text-purple-200 text-sm mt-1\">Courses Available</div>\n                        </div>\n                        <div>\n                            <div class=\"text-3xl font-bold text-white\">10K+</div>\n                            <div class=\"text-purple-200 text-sm mt-1\">Active Students</div>\n                        </div>\n                        <div>\n                            <div class=\"text-3xl font-bold text-white\">200+</div>\n                            <div class=\"text-purple-200 text-sm mt-1\">Exams &amp; Tests</div>\n                        </div>\n                        <div>\n                            <div class=\"text-3xl font-bold text-white\">98%</div>\n                            <div class=\"text-purple-200 text-sm mt-1\">Satisfaction Rate</div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </section>\n\n        <!-- ===================== FEATURED COURSES ===================== -->\n        <section id=\"courses\" class=\"py-20 bg-gray-50\">\n            <div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n                <div class=\"flex items-end justify-between mb-10\">\n                    <div>\n                        <span\n                            class=\"text-purple-700 font-semibold text-sm uppercase tracking-wider\">Featured</span>\n                        <h2 class=\"text-3xl lg:text-4xl font-bold text-gray-900 mt-1\">Top Courses to Get You\n                            Started</h2>\n                    </div>\n                    <a href=\"#subjects\"\n                        class=\"hidden md:inline-flex items-center gap-1 text-purple-700 font-semibold hover:text-purple-900 transition-colors text-sm\">\n                        View all <ChevronRightIcon class=\"h-4 w-4\" />\n                    </a>\n                </div>\n\n                <!-- 2-row grid of 4 columns = 8 cards -->\n                <div v-if=\"featuredCourses && featuredCourses.length\"\n                    class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6\">\n                    <div v-for=\"course in featuredCourses.slice(0, 8)\" :key=\"course.id\"\n                        class=\"bg-white rounded-2xl shadow-sm hover:shadow-xl transition-all duration-300 overflow-hidden group border border-gray-100 flex flex-col\">\n                        <!-- Thumbnail -->\n                        <div\n                            class=\"relative h-44 bg-gradient-to-br from-purple-100 to-indigo-100 overflow-hidden flex-shrink-0\">\n                            <img v-if=\"course.thumbnail\" :src=\"course.thumbnail\" :alt=\"course.title\"\n                                class=\"w-full h-full object-cover group-hover:scale-105 transition-transform duration-300\" />\n                            <div v-else class=\"w-full h-full flex items-center justify-center\">\n                                <BookOpenIcon class=\"h-14 w-14 text-purple-300\" />\n                            </div>\n                            <div v-if=\"course.certified\"\n                                class=\"absolute top-3 left-3 bg-amber-400 text-amber-900 text-xs font-bold px-2 py-0.5 rounded-full\">\n                                CERTIFIED\n                            </div>\n                            <div v-if=\"course.discount && course.discount > 0\"\n                                class=\"absolute top-3 right-3 bg-red-500 text-white text-xs font-bold px-2 py-0.5 rounded-full\">\n                                {{ course.discount }}% OFF\n                            </div>\n                        </div>\n\n                        <!-- Card body -->\n                        <div class=\"p-4 flex flex-col flex-1\">\n                            <h3\n                                class=\"font-semibold text-gray-900 text-sm leading-snug line-clamp-2 mb-1 group-hover:text-purple-700 transition-colors\">\n                                {{ course.title }}\n                            </h3>\n                            <p v-if=\"course.subtitle\" class=\"text-xs text-gray-500 line-clamp-1 mb-2\">\n                                {{ course.subtitle }}\n                            </p>\n\n                            <!-- Rating -->\n                            <div v-if=\"course.rating\" class=\"flex items-center gap-1 mb-2\">\n                                <span class=\"text-amber-500 font-bold text-xs\">{{ Number(course.rating).toFixed(1)\n                                    }}</span>\n                                <div class=\"flex gap-0.5\">\n                                    <span v-for=\"i in 5\" :key=\"i\"\n                                        :class=\"['text-sm', i <= starsFilled(Number(course.rating)) ? 'text-amber-400' : 'text-gray-200']\">★</span>\n                                </div>\n                                <span class=\"text-xs text-gray-500\">({{ course.students_count ?? 0\n                                    }})</span>\n                            </div>\n\n                            <!-- Lesson count -->\n                            <div v-if=\"course.lessons_count\"\n                                class=\"flex items-center gap-1 text-xs text-gray-500 mb-3\">\n                                <BookOpenIcon class=\"h-3.5 w-3.5\" />\n                                <span>{{ course.lessons_count }} lessons</span>\n                            </div>\n\n                            <!-- Price & CTA -->\n                            <div class=\"mt-auto flex items-center justify-between gap-2\">\n                                <div class=\"flex items-baseline gap-1\">\n                                    <span class=\"text-base font-bold text-gray-900\">${{ course.price }}</span>\n                                    <span v-if=\"course.discount && course.discount > 0\"\n                                        class=\"text-xs text-gray-400 line-through\">${{ discountedPrice(course)\n                                        }}</span>\n                                </div>\n                                <Link :href=\"course.permalink\"\n                                    class=\"flex-shrink-0 text-xs font-semibold text-white bg-purple-700 hover:bg-purple-800 px-3 py-1.5 rounded-lg transition-colors\">\n                                    Enroll\n                                </Link>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n\n                <!-- Empty state -->\n                <div v-else class=\"text-center py-16 text-gray-400\">\n                    <BookOpenIcon class=\"h-12 w-12 mx-auto mb-3 text-gray-300\" />\n                    <p class=\"text-lg font-medium text-gray-500\">Courses coming soon!</p>\n                    <p class=\"text-sm mt-1\">We're preparing great content for you. Check back shortly.</p>\n                </div>\n            </div>\n        </section>\n\n        <!-- ===================== OFFER / CTA BLOCK ===================== -->\n        <section id=\"certifications\"\n            class=\"py-20 bg-gradient-to-r from-purple-800 via-purple-900 to-indigo-900\">\n            <div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n                <div class=\"grid lg:grid-cols-2 gap-16 items-center\">\n                    <!-- Left: copy -->\n                    <div>\n                        <h2 class=\"text-3xl lg:text-4xl font-bold text-white leading-tight mb-4\">\n                            Ready to Start Your Learning Journey?\n                        </h2>\n                        <p class=\"text-purple-200 text-lg mb-8 leading-relaxed\">\n                            Join thousands of students already building skills on our platform. Get unlimited access\n                            to courses, sit exams, and earn certifications that advance your career.\n                        </p>\n                        <ul class=\"space-y-3 mb-10\">\n                            <li v-for=\"benefit in [\n                                'Lifetime access to all enrolled courses',\n                                'Industry-recognized certifications',\n                                'Expert-crafted exams with detailed feedback',\n                                'Learn at your own schedule, on any device',\n                            ]\" :key=\"benefit\" class=\"flex items-center gap-3 text-white text-sm\">\n                                <span\n                                    class=\"flex-shrink-0 w-5 h-5 bg-white/20 rounded-full flex items-center justify-center\">\n                                    <svg class=\"w-3 h-3 text-white\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n                                        <path fill-rule=\"evenodd\"\n                                            d=\"M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z\"\n                                            clip-rule=\"evenodd\" />\n                                    </svg>\n                                </span>\n                                {{ benefit }}\n                            </li>\n                        </ul>\n                        <div class=\"flex flex-wrap gap-4\">\n                            <Link :href=\"route('register')\"\n                                class=\"inline-flex items-center gap-2 bg-white text-purple-900 font-bold px-8 py-4 rounded-xl hover:bg-purple-50 transition-colors shadow-lg text-base\">\n                                Get Started Free\n                                <ChevronRightIcon class=\"h-5 w-5\" />\n                            </Link>\n                            <a href=\"#courses\"\n                                class=\"inline-flex items-center gap-2 border-2 border-white/40 text-white font-semibold px-8 py-4 rounded-xl hover:bg-white/10 transition-colors text-base\">\n                                Browse Courses\n                            </a>\n                        </div>\n                    </div>\n\n                    <!-- Right: feature cards -->\n                    <div class=\"hidden lg:grid grid-cols-2 gap-4\">\n                        <div class=\"space-y-4\">\n                            <div\n                                class=\"bg-white/10 backdrop-blur-sm rounded-2xl p-6 border border-white/20 hover:bg-white/15 transition-colors\">\n                                <AcademicCapIcon class=\"h-10 w-10 text-purple-200 mb-3\" />\n                                <h3 class=\"text-white font-semibold mb-1\">Guided Courses</h3>\n                                <p class=\"text-purple-200 text-sm\">Structured learning paths curated by experts</p>\n                            </div>\n                            <div\n                                class=\"bg-white/10 backdrop-blur-sm rounded-2xl p-6 border border-white/20 hover:bg-white/15 transition-colors\">\n                                <UserGroupIcon class=\"h-10 w-10 text-purple-200 mb-3\" />\n                                <h3 class=\"text-white font-semibold mb-1\">Community</h3>\n                                <p class=\"text-purple-200 text-sm\">Learn together with thousands of peers</p>\n                            </div>\n                        </div>\n                        <div class=\"space-y-4 mt-8\">\n                            <div\n                                class=\"bg-white/10 backdrop-blur-sm rounded-2xl p-6 border border-white/20 hover:bg-white/15 transition-colors\">\n                                <ClipboardDocumentCheckIcon class=\"h-10 w-10 text-purple-200 mb-3\" />\n                                <h3 class=\"text-white font-semibold mb-1\">Smart Exams</h3>\n                                <p class=\"text-purple-200 text-sm\">Test your skills with detailed analytics</p>\n                            </div>\n                            <div\n                                class=\"bg-white/10 backdrop-blur-sm rounded-2xl p-6 border border-white/20 hover:bg-white/15 transition-colors\">\n                                <TrophyIcon class=\"h-10 w-10 text-purple-200 mb-3\" />\n                                <h3 class=\"text-white font-semibold mb-1\">Certificates</h3>\n                                <p class=\"text-purple-200 text-sm\">Earn industry-recognized certifications</p>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </section>\n\n        <!-- ===================== SUBJECTS ===================== -->\n        <section id=\"subjects\" class=\"py-20 bg-white\">\n            <div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n                <div class=\"text-center mb-12\">\n                    <span class=\"text-purple-700 font-semibold text-sm uppercase tracking-wider\">Explore</span>\n                    <h2 class=\"text-3xl lg:text-4xl font-bold text-gray-900 mt-1\">Subjects We Offer</h2>\n                    <p class=\"text-gray-500 mt-3 max-w-xl mx-auto text-base\">Choose from a wide range of subjects\n                        and start learning what matters most to your career</p>\n                </div>\n\n                <div v-if=\"subjects && subjects.length\"\n                    class=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6 gap-4\">\n                    <div v-for=\"(subject, index) in subjects\" :key=\"subject.id\"\n                        class=\"group flex flex-col items-center text-center p-5 rounded-2xl border border-gray-100 hover:border-purple-200 hover:shadow-md hover:bg-purple-50 transition-all duration-200 cursor-pointer\">\n                        <div class=\"text-4xl mb-3 group-hover:scale-110 transition-transform duration-200\">{{\n                            getSubjectEmoji(index) }}</div>\n                        <h3 class=\"text-gray-800 font-semibold text-sm leading-snug mb-1\">{{ subject.title }}</h3>\n                        <span class=\"text-xs text-purple-600 font-medium\">\n                            {{ subject.courses_count ?? (subject.courses?.length ?? 0) }} Courses\n                        </span>\n                    </div>\n                </div>\n\n                <div v-else class=\"text-center py-12 text-gray-400\">\n                    <p class=\"text-base\">No subjects available yet — check back soon!</p>\n                </div>\n            </div>\n        </section>\n\n        <!-- ===================== TESTIMONIALS ===================== -->\n        <section class=\"py-20 bg-gradient-to-b from-gray-50 to-white\">\n            <div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n                <div class=\"text-center mb-12\">\n                    <span class=\"text-purple-700 font-semibold text-sm uppercase tracking-wider\">Testimonials</span>\n                    <h2 class=\"text-3xl lg:text-4xl font-bold text-gray-900 mt-1\">What Our Students Say</h2>\n                    <p class=\"text-gray-500 mt-3 max-w-xl mx-auto text-base\">Real stories from real learners who\n                        transformed their careers with our platform</p>\n                </div>\n\n                <div class=\"grid grid-cols-1 md:grid-cols-3 gap-8\">\n                    <div v-for=\"t in testimonials\" :key=\"t.name\"\n                        class=\"bg-white rounded-2xl p-8 shadow-sm border border-gray-100 hover:shadow-lg transition-shadow duration-300 flex flex-col\">\n                        <!-- Stars -->\n                        <div class=\"flex gap-0.5 mb-4\">\n                            <span v-for=\"i in 5\" :key=\"i\" class=\"text-amber-400 text-xl\">★</span>\n                        </div>\n                        <!-- Quote -->\n                        <p class=\"text-gray-700 leading-relaxed mb-6 italic flex-1\">\"{{ t.text }}\"</p>\n                        <!-- Author -->\n                        <div class=\"flex items-center gap-3\">\n                            <img :src=\"t.avatar\" :alt=\"t.name\"\n                                class=\"w-12 h-12 rounded-full object-cover border-2 border-purple-100\"\n                                loading=\"lazy\" />\n                            <div>\n                                <div class=\"font-semibold text-gray-900 text-sm\">{{ t.name }}</div>\n                                <div class=\"text-purple-600 text-xs\">{{ t.role }}</div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </section>\n\n        <!-- ===================== CONTACT & CHAT ===================== -->\n        <section id=\"contact\" class=\"py-20 bg-white\">\n            <div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\n                <div class=\"text-center mb-12\">\n                    <span class=\"text-purple-700 font-semibold text-sm uppercase tracking-wider\">Get In\n                        Touch</span>\n                    <h2 class=\"text-3xl lg:text-4xl font-bold text-gray-900 mt-1\">Contact &amp; Support</h2>\n                    <p class=\"text-gray-500 mt-3 max-w-xl mx-auto text-base\">Have a question? We're here to help\n                        you every step of the way</p>\n                </div>\n\n                <div class=\"grid lg:grid-cols-2 gap-16 items-start\">\n                    <!-- Contact form -->\n                    <div class=\"bg-gray-50 rounded-3xl p-8 border border-gray-100\">\n                        <h3 class=\"text-xl font-bold text-gray-900 mb-6\">Send us a Message</h3>\n                        <form @submit.prevent=\"submitContact\" class=\"space-y-5\">\n                            <div class=\"grid sm:grid-cols-2 gap-4\">\n                                <div>\n                                    <label class=\"block text-sm font-medium text-gray-700 mb-1.5\">Your\n                                        Name</label>\n                                    <input v-model=\"contactForm.name\" type=\"text\" placeholder=\"John Doe\"\n                                        required\n                                        class=\"w-full px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent bg-white text-sm transition-all\" />\n                                </div>\n                                <div>\n                                    <label class=\"block text-sm font-medium text-gray-700 mb-1.5\">Email\n                                        Address</label>\n                                    <input v-model=\"contactForm.email\" type=\"email\"\n                                        placeholder=\"john@example.com\" required\n                                        class=\"w-full px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent bg-white text-sm transition-all\" />\n                                </div>\n                            </div>\n                            <div>\n                                <label class=\"block text-sm font-medium text-gray-700 mb-1.5\">Message</label>\n                                <textarea v-model=\"contactForm.message\"\n                                    placeholder=\"Tell us how we can help you...\" rows=\"5\" required\n                                    class=\"w-full px-4 py-3 rounded-xl border border-gray-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent bg-white text-sm resize-none transition-all\"></textarea>\n                            </div>\n                            <button type=\"submit\"\n                                class=\"w-full bg-purple-700 hover:bg-purple-800 text-white font-semibold py-3.5 rounded-xl transition-colors shadow-sm\">\n                                Send Message\n                            </button>\n                        </form>\n                    </div>\n\n                    <!-- Chat & support cards -->\n                    <div class=\"space-y-6\">\n                        <div>\n                            <h3 class=\"text-xl font-bold text-gray-900 mb-2\">We're Always Here</h3>\n                            <p class=\"text-gray-500 leading-relaxed\">Whether you have questions about a course,\n                                exam, or certification — our team is ready to help you succeed.</p>\n                        </div>\n\n                        <div class=\"space-y-4\">\n                            <div\n                                class=\"flex items-start gap-4 p-5 rounded-2xl border border-gray-100 hover:border-purple-200 hover:bg-purple-50 transition-colors\">\n                                <div\n                                    class=\"w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center flex-shrink-0\">\n                                    <ChatBubbleLeftRightIcon class=\"h-6 w-6 text-purple-700\" />\n                                </div>\n                                <div>\n                                    <h4 class=\"font-semibold text-gray-900\">Live Chat Support</h4>\n                                    <p class=\"text-sm text-gray-500 mt-0.5\">Chat with our team in real-time</p>\n                                    <span\n                                        class=\"inline-flex items-center gap-1 text-xs text-green-600 font-medium mt-1\">\n                                        <span class=\"w-2 h-2 bg-green-400 rounded-full\"></span>Online now\n                                    </span>\n                                </div>\n                            </div>\n\n                            <div\n                                class=\"flex items-start gap-4 p-5 rounded-2xl border border-gray-100 hover:border-purple-200 hover:bg-purple-50 transition-colors\">\n                                <div\n                                    class=\"w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center flex-shrink-0\">\n                                    <EnvelopeIcon class=\"h-6 w-6 text-purple-700\" />\n                                </div>\n                                <div>\n                                    <h4 class=\"font-semibold text-gray-900\">Email Support</h4>\n                                    <p class=\"text-sm text-gray-500 mt-0.5\">support@examinee.com</p>\n                                    <p class=\"text-xs text-gray-400 mt-1\">Response within 24 hours</p>\n                                </div>\n                            </div>\n\n                            <div\n                                class=\"flex items-start gap-4 p-5 rounded-2xl border border-gray-100 hover:border-purple-200 hover:bg-purple-50 transition-colors\">\n                                <div\n                                    class=\"w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center flex-shrink-0\">\n                                    <AcademicCapIcon class=\"h-6 w-6 text-purple-700\" />\n                                </div>\n                                <div>\n                                    <h4 class=\"font-semibold text-gray-900\">FAQ &amp; Help Center</h4>\n                                    <p class=\"text-sm text-gray-500 mt-0.5\">Browse our detailed knowledge base\n                                    </p>\n                                    <a href=\"#\"\n                                        class=\"text-xs text-purple-600 font-medium mt-1 inline-flex items-center gap-1 hover:text-purple-800 transition-colors\">\n                                        Visit Help Center <ChevronRightIcon class=\"h-3.5 w-3.5\" />\n                                    </a>\n                                </div>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </section>\n\n        <!-- ===================== FOOTER ===================== -->\n        <footer class=\"bg-gray-950 text-gray-400\">\n            <div class=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16\">\n                <div class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-10\">\n                    <!-- Brand col -->\n                    <div class=\"lg:col-span-2\">\n                        <Link :href=\"route('home')\"\n                            class=\"inline-block brightness-0 invert mb-4\">\n                            <img src=\"/images/logo.svg\" alt=\"Examinee\" class=\"h-8 w-auto\" />\n                        </Link>\n                        <p class=\"text-sm leading-relaxed mb-6\">Empower your future with expert-led courses,\n                            certification exams, and a community of passionate learners.</p>\n                        <!-- Social -->\n                        <div class=\"flex gap-3\">\n                            <a href=\"#\"\n                                class=\"w-9 h-9 bg-gray-800 hover:bg-purple-700 rounded-lg flex items-center justify-center transition-colors\"\n                                aria-label=\"Twitter / X\">\n                                <svg class=\"w-4 h-4 text-white\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n                                    <path\n                                        d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.748l7.73-8.835L1.254 2.25H8.08l4.253 5.622zm-1.161 17.52h1.833L7.084 4.126H5.117z\" />\n                                </svg>\n                            </a>\n                            <a href=\"#\"\n                                class=\"w-9 h-9 bg-gray-800 hover:bg-purple-700 rounded-lg flex items-center justify-center transition-colors\"\n                                aria-label=\"LinkedIn\">\n                                <svg class=\"w-4 h-4 text-white\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n                                    <path\n                                        d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\" />\n                                </svg>\n                            </a>\n                            <a href=\"#\"\n                                class=\"w-9 h-9 bg-gray-800 hover:bg-purple-700 rounded-lg flex items-center justify-center transition-colors\"\n                                aria-label=\"YouTube\">\n                                <svg class=\"w-4 h-4 text-white\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n                                    <path\n                                        d=\"M23.498 6.186a3.016 3.016 0 00-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 00.502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 002.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 002.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z\" />\n                                </svg>\n                            </a>\n                        </div>\n                    </div>\n\n                    <!-- Courses -->\n                    <div>\n                        <h4 class=\"text-white font-semibold mb-4\">Courses</h4>\n                        <ul class=\"space-y-3 text-sm\">\n                            <li><a href=\"#courses\" class=\"hover:text-purple-400 transition-colors\">All\n                                    Courses</a></li>\n                            <li><a href=\"#courses\" class=\"hover:text-purple-400 transition-colors\">Featured\n                                    Courses</a></li>\n                            <li><a href=\"#\" class=\"hover:text-purple-400 transition-colors\">Free Courses</a>\n                            </li>\n                            <li><a href=\"#certifications\"\n                                    class=\"hover:text-purple-400 transition-colors\">Certifications</a></li>\n                        </ul>\n                    </div>\n\n                    <!-- Platform -->\n                    <div>\n                        <h4 class=\"text-white font-semibold mb-4\">Platform</h4>\n                        <ul class=\"space-y-3 text-sm\">\n                            <li><a href=\"#\" class=\"hover:text-purple-400 transition-colors\">About Us</a></li>\n                            <li><a href=\"#\" class=\"hover:text-purple-400 transition-colors\">How It Works</a>\n                            </li>\n                            <li><a href=\"#contact\" class=\"hover:text-purple-400 transition-colors\">Contact\n                                    Us</a></li>\n                            <li>\n                                <Link :href=\"route('register')\"\n                                    class=\"hover:text-purple-400 transition-colors\">Sign Up\n                                </Link>\n                            </li>\n                        </ul>\n                    </div>\n\n                    <!-- Legal -->\n                    <div>\n                        <h4 class=\"text-white font-semibold mb-4\">Legal</h4>\n                        <ul class=\"space-y-3 text-sm\">\n                            <li><a href=\"#\" class=\"hover:text-purple-400 transition-colors\">Privacy Policy</a>\n                            </li>\n                            <li><a href=\"#\" class=\"hover:text-purple-400 transition-colors\">Terms of Service</a>\n                            </li>\n                            <li><a href=\"#\" class=\"hover:text-purple-400 transition-colors\">Cookie Policy</a>\n                            </li>\n                            <li><a href=\"#\" class=\"hover:text-purple-400 transition-colors\">Refund Policy</a>\n                            </li>\n                        </ul>\n                    </div>\n                </div>\n\n                <!-- Bottom bar -->\n                <div\n                    class=\"mt-12 pt-8 border-t border-gray-800 flex flex-col sm:flex-row items-center justify-between gap-4\">\n                    <p class=\"text-sm\">© {{ new Date().getFullYear() }} Examinee. All rights reserved.</p>\n                    <p class=\"text-sm\">Made with ❤️ for lifelong learners</p>\n                </div>\n            </div>\n        </footer>\n    </div>\n</template>\n\n<style scoped>\n/* Hero slide transition */\n.hero-fade-enter-active {\n    transition: opacity 0.5s ease, transform 0.5s ease;\n}\n\n.hero-fade-leave-active {\n    transition: opacity 0.3s ease, transform 0.3s ease;\n}\n\n.hero-fade-enter-from {\n    opacity: 0;\n    transform: translateY(16px);\n}\n\n.hero-fade-leave-to {\n    opacity: 0;\n    transform: translateY(-8px);\n}\n\n/* Tailwind line-clamp fallback */\n.line-clamp-1 {\n    display: -webkit-box;\n    -webkit-line-clamp: 1;\n    -webkit-box-orient: vertical;\n    overflow: hidden;\n}\n\n.line-clamp-2 {\n    display: -webkit-box;\n    -webkit-line-clamp: 2;\n    -webkit-box-orient: vertical;\n    overflow: hidden;\n}\n</style>\n"
  },
  {
    "path": "resources/js/Pages/Home/Slider.vue",
    "content": "<template>\n    \n</template>"
  },
  {
    "path": "resources/js/Pages/Instructor/Courses.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport MainLayout from \"@/Layouts/MainLayout.vue\";\nimport { Head } from \"@inertiajs/vue3\";\nimport { Course } from \"@/types\";\nimport CourseComponent from \"@/Elements/Course.vue\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\n\ndefineProps<{\n    courses: Course[];\n    canModify: boolean\n}>();\n\nconst openCourseForm = ref(false);\n</script>\n\n<template>\n    <MainLayout>\n        <Head title=\"Instructor course\" />\n        <div class=\"container mx-auto\">\n            <Card class=\"my-5\">\n                <div class=\"flex justify-between items-center\">\n                    <h1>Instruct courses</h1>\n                    <Button v-if=\"canModify\" @click.prevent=\"openCourseForm = true\">Create course</Button>\n                </div>\n            </Card>\n            <div\n                class=\"grid gap-6 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 mt-6\"\n            >\n                <template v-for=\"course in courses\" :key=\"course.id\">\n                    <CourseComponent :course=\"course\" :canModify=\"canModify\"/>\n                </template>\n            </div>\n        </div>\n    </MainLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Learning/Courses.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport MainLayout from \"@/Layouts/MainLayout.vue\";\nimport { Head } from \"@inertiajs/vue3\";\nimport { Course } from \"@/types\";\nimport CourseComponent from \"@/Elements/Course.vue\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\n\ndefineProps<{\n    courses: Course[];\n    canModify: boolean\n}>();\n\nconst openCourseForm = ref(false);\n</script>\n\n<template>\n    <MainLayout>\n        <Head title=\"Instructor course\" />\n        <div class=\"container mx-auto\">\n            <Card class=\"my-5\">\n                <div class=\"flex justify-between items-center\">\n                    <h1>Instruct courses</h1>\n                    <Button v-if=\"canModify\" @click.prevent=\"openCourseForm = true\">Create course</Button>\n                </div>\n            </Card>\n            <div\n                class=\"grid gap-6 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 mt-6\"\n            >\n                <template v-for=\"course in courses\" :key=\"course.id\">\n                    <CourseComponent :course=\"course\" :canModify=\"canModify\">\n                        <template #button>\n                            <Button is=\"a\" :href=\"route('start.course', course.slug)\">\n                                Start Learning\n                            </Button>\n                        </template>\n                    </CourseComponent>\n                </template>\n            </div>\n        </div>\n    </MainLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Learning/SingleResource.vue",
    "content": "<script setup lang=\"ts\">\nimport MainLayout from \"@/Layouts/MainLayout.vue\";\nimport { Head } from \"@inertiajs/vue3\";\nimport { Course, Exam, Lesson } from \"@/types\";\nimport Card from \"@/Components/Card.vue\";\nimport SingleLesson from \"@/Elements/Lesson/SingleLesson.vue\";\n\ndefineProps<{\n    course: Course;\n    resource: Lesson | Exam;\n}>();\n</script>\n\n<template>\n    <MainLayout>\n        <Head :title=\"resource.title\" />\n        <div class=\"grid grid-cols-12\">\n            <div class=\"col-span-3\">\n                <Card class=\"my-5\">\n                    <template #header>\n                        <h2>Course content</h2>\n                    </template>\n\n                    <template\n                        v-for=\"section in course.sections\"\n                        :key=\"`section${section.id}`\"\n                    >\n                        <h2 class=\"text-lg font-bold\">{{ section.title }}</h2>\n                        <ul>\n                            <template v-for=\"resource in section.resources\">\n                                <li>\n                                    {{ resource.title }}\n                                </li>\n                            </template>\n                        </ul>\n                    </template>\n                </Card>\n            </div>\n\n            <div class=\"col-span-9\">\n                <SingleLesson :lesson=\"resource as Lesson\" />\n            </div>\n        </div>\n    </MainLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Profile/Edit.vue",
    "content": "<script setup lang=\"ts\">\nimport DeleteUserForm from './Partials/DeleteUserForm.vue';\nimport UpdatePasswordForm from './Partials/UpdatePasswordForm.vue';\nimport UpdateProfileInformationForm from './Partials/UpdateProfileInformationForm.vue';\nimport { Head } from '@inertiajs/vue3';\nimport MainLayout from '@/Layouts/MainLayout.vue';\n\ndefineProps<{\n    mustVerifyEmail?: boolean;\n    status?: string;\n}>();\n</script>\n\n<template>\n    <Head title=\"Profile\" />\n\n    <MainLayout>\n        <template #header>\n            <h2 class=\"font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight\">Profile</h2>\n        </template>\n\n        <div class=\"py-12\">\n            <div class=\"max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6\">\n                <div class=\"p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg\">\n                    <UpdateProfileInformationForm\n                        :must-verify-email=\"mustVerifyEmail\"\n                        :status=\"status\"\n                        class=\"max-w-xl\"\n                    />\n                </div>\n\n                <div class=\"p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg\">\n                    <UpdatePasswordForm class=\"max-w-xl\" />\n                </div>\n\n                <div class=\"p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg\">\n                    <DeleteUserForm class=\"max-w-xl\" />\n                </div>\n            </div>\n        </div>\n    </MainLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Profile/Partials/DeleteUserForm.vue",
    "content": "<script setup lang=\"ts\">\nimport Label from '@/Components/Form/Label.vue';\nimport Modal from '@/Components/Modal.vue';\nimport Button from '@/Components/Button.vue';\nimport Input from '@/Components/Form/Input.vue';\nimport { useForm } from '@inertiajs/vue3';\nimport { nextTick, ref } from 'vue';\n\nconst confirmingUserDeletion = ref(false);\nconst passwordInput = ref<HTMLInputElement | null>(null);\n\nconst form = useForm({\n    password: '',\n});\n\nconst confirmUserDeletion = () => {\n    confirmingUserDeletion.value = true;\n\n    nextTick(() => passwordInput.value?.focus());\n};\n\nconst deleteUser = () => {\n    form.delete(route('profile.destroy'), {\n        preserveScroll: true,\n        onSuccess: () => closeModal(),\n        onError: () => passwordInput.value?.focus(),\n        onFinish: () => {\n            form.reset();\n        },\n    });\n};\n\nconst closeModal = () => {\n    confirmingUserDeletion.value = false;\n\n    form.reset();\n};\n</script>\n\n<template>\n    <section class=\"space-y-6\">\n        <header>\n            <h2 class=\"text-lg font-medium text-gray-900 dark:text-gray-100\">Delete Account</h2>\n\n            <p class=\"mt-1 text-sm text-gray-600 dark:text-gray-400\">\n                Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting\n                your account, please download any data or information that you wish to retain.\n            </p>\n        </header>\n\n        <Button @click=\"confirmUserDeletion\" color=\"red\">Delete Account</Button>\n\n        <Modal :show=\"confirmingUserDeletion\" @close=\"closeModal\">\n            <div class=\"p-6\">\n                <h2 class=\"text-lg font-medium text-gray-900 dark:text-gray-100\">\n                    Are you sure you want to delete your account?\n                </h2>\n\n                <p class=\"mt-1 text-sm text-gray-600 dark:text-gray-400\">\n                    Once your account is deleted, all of its resources and data will be permanently deleted. Please\n                    enter your password to confirm you would like to permanently delete your account.\n                </p>\n\n                <div class=\"mt-6\">\n                    <Label for=\"password\" value=\"Password\" class=\"sr-only\" :error=\"form.errors.password\">\n\n                    <Input\n                        id=\"password\"\n                        ref=\"passwordInput\"\n                        v-model=\"form.password\"\n                        type=\"password\"\n                        class=\"mt-1 block w-3/4\"\n                        placeholder=\"Password\"\n                        @keyup.enter=\"deleteUser\"\n                    />\n\n                    </Label>\n                </div>\n\n                <div class=\"mt-6 flex justify-end\">\n                    <Button @click=\"closeModal\" color=\"gray\"> Cancel </Button>\n\n                    <Button\n                        class=\"ms-3\"\n                        :class=\"{ 'opacity-25': form.processing }\"\n                        :disabled=\"form.processing\"\n                        color=\"red\"\n                        @click=\"deleteUser\"\n                    >\n                        Delete Account\n                    </Button>\n                </div>\n            </div>\n        </Modal>\n    </section>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Profile/Partials/UpdatePasswordForm.vue",
    "content": "<script setup lang=\"ts\">\nimport Label from '@/Components/Form/Label.vue';\nimport Button from '@/Components/Button.vue';\nimport Input from '@/Components/Form/Input.vue';\nimport { useForm } from '@inertiajs/vue3';\nimport { ref } from 'vue';\n\nconst passwordInput = ref<HTMLInputElement | null>(null);\nconst currentPasswordInput = ref<HTMLInputElement | null>(null);\n\nconst form = useForm({\n    current_password: '',\n    password: '',\n    password_confirmation: '',\n});\n\nconst updatePassword = () => {\n    form.put(route('password.update'), {\n        preserveScroll: true,\n        onSuccess: () => {\n            form.reset();\n        },\n        onError: () => {\n            if (form.errors.password) {\n                form.reset('password', 'password_confirmation');\n                passwordInput.value?.focus();\n            }\n            if (form.errors.current_password) {\n                form.reset('current_password');\n                currentPasswordInput.value?.focus();\n            }\n        },\n    });\n};\n</script>\n\n<template>\n    <section>\n        <header>\n            <h2 class=\"text-lg font-medium text-gray-900 dark:text-gray-100\">Update Password</h2>\n\n            <p class=\"mt-1 text-sm text-gray-600 dark:text-gray-400\">\n                Ensure your account is using a long, random password to stay secure.\n            </p>\n        </header>\n\n        <form @submit.prevent=\"updatePassword\" class=\"mt-6 space-y-6\">\n            <div>\n                <Label label=\"Current Password\" :error=\"form.errors.current_password\">\n\n                <Input\n                    id=\"current_password\"\n                    ref=\"currentPasswordInput\"\n                    v-model=\"form.current_password\"\n                    type=\"password\"\n                    class=\"mt-1 block w-full\"\n                    autocomplete=\"current-password\"\n                />\n\n                </Label>\n            </div>\n\n            <div>\n                <Label label=\"New Password\" :error=\"form.errors.password\">\n\n                <Input\n                    id=\"password\"\n                    ref=\"passwordInput\"\n                    v-model=\"form.password\"\n                    type=\"password\"\n                    class=\"mt-1 block w-full\"\n                    autocomplete=\"new-password\"\n                />\n\n                </Label>\n            </div>\n\n            <div>\n                <Label label=\"Confirm Password\" :error=\"form.errors.password_confirmation\">\n\n                <Input\n                    id=\"password_confirmation\"\n                    v-model=\"form.password_confirmation\"\n                    type=\"password\"\n                    class=\"mt-1 block w-full\"\n                    autocomplete=\"new-password\"\n                />\n\n                </Label>\n            </div>\n\n            <div class=\"flex items-center gap-4\">\n                <Button :disabled=\"form.processing\">Save</Button>\n\n                <Transition\n                    enter-active-class=\"transition ease-in-out\"\n                    enter-from-class=\"opacity-0\"\n                    leave-active-class=\"transition ease-in-out\"\n                    leave-to-class=\"opacity-0\"\n                >\n                    <p v-if=\"form.recentlySuccessful\" class=\"text-sm text-gray-600 dark:text-gray-400\">Saved.</p>\n                </Transition>\n            </div>\n        </form>\n    </section>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/Profile/Partials/UpdateProfileInformationForm.vue",
    "content": "<script setup lang=\"ts\">\nimport Label from '@/Components/Form/Label.vue';\nimport Button from '@/Components/Button.vue';\nimport Input from '@/Components/Form/Input.vue';\nimport { Link, useForm, usePage } from '@inertiajs/vue3';\n\ndefineProps<{\n    mustVerifyEmail?: Boolean;\n    status?: String;\n}>();\n\nconst user = usePage().props.auth.user;\n\nconst form = useForm({\n    name: user.name,\n    email: user.email,\n});\n</script>\n\n<template>\n    <section>\n        <header>\n            <h2 class=\"text-lg font-medium text-gray-900 dark:text-gray-100\">Profile Information</h2>\n\n            <p class=\"mt-1 text-sm text-gray-600 dark:text-gray-400\">\n                Update your account's profile information and email address.\n            </p>\n        </header>\n\n        <form @submit.prevent=\"form.patch(route('profile.update'))\" class=\"mt-6 space-y-6\">\n            <div>\n                <Label label=\"Name\" required :error=\"form.errors.name\" >\n\n                <Input\n                    id=\"name\"\n                    type=\"text\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.name\"\n                    required\n                    autofocus\n                    autocomplete=\"name\"\n                />\n\n                </Label>\n            </div>\n\n            <div>\n                <Label label=\"Email\" required :error=\"form.errors.email\">\n\n                <Input\n                    id=\"email\"\n                    type=\"email\"\n                    class=\"mt-1 block w-full\"\n                    v-model=\"form.email\"\n                    required\n                    autocomplete=\"username\"\n                />\n\n                </Label>\n            </div>\n\n            <div v-if=\"mustVerifyEmail && user.email_verified_at === null\">\n                <p class=\"text-sm mt-2 text-gray-800 dark:text-gray-200\">\n                    Your email address is unverified.\n                    <Link\n                        :href=\"route('verification.send')\"\n                        method=\"post\"\n                        as=\"button\"\n                        class=\"underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800\"\n                    >\n                        Click here to re-send the verification email.\n                    </Link>\n                </p>\n\n                <div\n                    v-show=\"status === 'verification-link-sent'\"\n                    class=\"mt-2 font-medium text-sm text-green-600 dark:text-green-400\"\n                >\n                    A new verification link has been sent to your email address.\n                </div>\n            </div>\n\n            <div class=\"flex items-center gap-4\">\n                <Button :disabled=\"form.processing\">Save</Button>\n\n                <Transition\n                    enter-active-class=\"transition ease-in-out\"\n                    enter-from-class=\"opacity-0\"\n                    leave-active-class=\"transition ease-in-out\"\n                    leave-to-class=\"opacity-0\"\n                >\n                    <p v-if=\"form.recentlySuccessful\" class=\"text-sm text-gray-600 dark:text-gray-400\">Saved.</p>\n                </Transition>\n            </div>\n        </form>\n    </section>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/admin/Dashboard.vue",
    "content": "<template>\n  <AdminLayout>\n  <div id=\"admin\">\n    <div v-if=\"roles\" class=\"float-right mb-6 text-center\">\n      <RolesBadges :roles=\"roles\" />\n    </div>\n    <nav class=\"mb-6 text-sm font-semibold\" aria-label=\"Breadcrumb\">\n      <ol class=\"inline-flex list-none p-0\">\n        <li class=\"flex items-center\">\n          <Link\n            \n            :to=\"{ name: 'admin' }\"\n            class=\"text-gray-500 hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-400\"\n          >\n            <span\n              :class=\"[\n                  'cursor-default text-gray-800 hover:text-gray-900 dark:text-gray-500 dark:hover:text-gray-500',\n              ]\"\n            >\n              Admin\n            </span>\n          </Link>\n        </li>\n      </ol>\n    </nav>\n\n    <div class=\"mb-6 items-center justify-between lg:flex\">\n      <p class=\"mb-2 text-2xl font-semibold lg:mb-0\">\n        {{ greeting }}, {{ user.name }}!\n      </p>\n      <!--\n      <button\n        class=\"rounded-lg bg-blue-500 px-6 py-2 font-semibold text-white shadow hover:bg-blue-600 focus:outline-none\"\n      >\n        View Logs\n      </button>\n      -->\n    </div>\n\n    <div class=\"-mx-3 mb-20 flex flex-wrap\">\n      <div\n        class=\"w-full px-3 md:w-2/3 xl:w-2/3\"\n      >\n        <Link >\n          <div\n            class=\"mb-6 flex w-full items-center rounded-lg border bg-white p-6 text-gray-600 hover:bg-gray-100 dark:border-slate-900 dark:bg-slate-900 dark:hover:border-slate-700 dark:hover:bg-slate-700\"\n          >\n            <span\n              class=\"fas fa-lock fa-fw fa-3x text-gray-700 dark:text-gray-300\"\n            />\n            <div>\n              <p\n                class=\"text-3xl font-semibold text-gray-700 dark:text-gray-300\"\n              >\n                <span\n                  v-if=\"loading\"\n                  class=\"fas fa-circle-notch fa-spin fa-xs\"\n                />\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-square-facebook fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableFbLogin')\n                      ? 'text-blue-600 dark:text-blue-600'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-twitter fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableTwitterLogin')\n                      ? 'text-blue-300 dark:text-blue-300'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-instagram fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableInstagramLogin')\n                      ? 'text-green-300 dark:text-yellow-300'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-github fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableGitHubLogin')\n                      ? 'text-gray-300 dark:text-gray-300'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-youtube fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableYouTubeLogin')\n                      ? 'text-red-500 dark:text-red-500'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-google fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableGoogleLogin')\n                      ? 'text-green-300 dark:text-green-300'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-linkedin fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableLinkedInLogin')\n                      ? 'text-blur-700 dark:text-blur-700'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-twitch fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableTwitchLogin')\n                      ? 'text-blue-500 dark:text-blue-500'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-apple fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableAppleLogin')\n                      ? 'text-gray-800 dark:text-gray-200'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-microsoft fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableMicrosoftLogin')\n                      ? 'text-blue-300 dark:text-blue-300'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <!--\n                <span\n                  class=\"rounded-xl\"\n                  :class=\"\n                    checkSettingEnabled('enableZoHoLogin')\n                      ? 'bg-yellow-300 dark:bg-yellow-600'\n                      : ''\n                  \"\n                  style=\"\n                    height: 24px;\n                    display: inline-block;\n                    padding: 0 6px 0 0;\n                    margin: 0;\n                    line-height: 0.9;\n                  \"\n                >\n                  <img\n                    v-if=\"!loading\"\n                    id=\"zoho\"\n                    :src=\"zohoImgUrl\"\n                    alt=\"Zoho\"\n                    class=\"\"\n                    style=\"\n                      width: 100%;\n                      max-width: 60px;\n                      margin: -10px 0 0 5px;\n                      display: inline-block;\n                    \"\n                  />\n                </span>\n                -->\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa fa-z fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableZoHoLogin')\n                      ? 'text-yellow-600 dark:text-yellow-600'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-stack-exchange fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableStackExchangeLogin')\n                      ? 'text-blue-400 dark:text-blue-400'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-square-gitlab fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableGitLabLogin')\n                      ? 'text-orange-400 dark:text-orange-400'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-square-reddit fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableRedditLogin')\n                      ? 'text-orange-700 dark:text-orange-700'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-square-snapchat fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableSnapchatLogin')\n                      ? 'text-yellow-400 dark:text-yellow-400'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-meetup fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableMeetupLogin')\n                      ? 'text-red-400 dark:text-red-400'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n\n                <span\n                  v-if=\"!loading\"\n                  class=\"fa-brands fa-atlassian fa-fw fa-xs\"\n                  :class=\"\n                    checkSettingEnabled('enableAtlassianLogin')\n                      ? 'text-blue-800 dark:text-blue-800'\n                      : 'text-gray-300 dark:text-gray-800'\n                  \"\n                >\n                </span>\n                <!-- NEW_PROVIDER_PLUG :: Put New Provider HERE -->\n              </p>\n              <p class=\"text-gray-600 dark:text-gray-400\">Logins Enabled</p>\n            </div>\n          </div>\n        </Link>\n      </div>\n\n      <div\n        v-if=\"authenticated && roles && roles.superAdmin\"\n        class=\"w-full px-3 sm:w-1/2 md:w-1/3 xl:w-1/3\"\n      >\n        <Link :to=\"{ name: 'users' }\">\n          <div\n            class=\"mb-6 flex w-full items-center rounded-lg border bg-white p-6 text-gray-600 hover:bg-gray-100 dark:border-slate-900 dark:bg-slate-900 dark:hover:border-slate-700 dark:hover:bg-slate-700\"\n          >\n            <span\n              class=\"fas fa-user fa-fw fa-3x text-gray-700 dark:text-gray-300\"\n            />\n            <div>\n              <p\n                class=\"text-3xl font-semibold text-gray-700 dark:text-gray-300\"\n              >\n                <span\n                  v-if=\"loading\"\n                  class=\"fas fa-circle-notch fa-spin fa-xs\"\n                />\n                <span v-if=\"!loading\">\n                  {{ users.length }}\n                </span>\n              </p>\n              <p class=\"text-gray-600 dark:text-gray-400\">Registered Users</p>\n            </div>\n          </div>\n        </Link>\n      </div>\n\n      <div\n        v-if=\"authenticated && roles && roles.superAdmin\"\n        class=\"w-full px-3 sm:w-1/2 lg:w-1/2 xl:w-1/2\"\n      >\n        <Link :to=\"{ name: 'app-settings' }\">\n          <div\n            class=\"mb-6 flex w-full items-center rounded-lg border bg-white p-6 text-gray-600 hover:bg-gray-100 dark:border-slate-900 dark:bg-slate-900 dark:hover:border-slate-700 dark:hover:bg-slate-700\"\n          >\n            <span\n              class=\"fa-brands fa-google fa-fw fa-3x text-gray-700 dark:text-gray-300\"\n            />\n            <div>\n              <p\n                class=\"text-3xl font-semibold text-gray-700 dark:text-gray-300\"\n              >\n                <span\n                  v-if=\"loading\"\n                  class=\"fas fa-circle-notch fa-spin fa-xs\"\n                />\n                <span\n                  v-if=\"!loading\"\n                  :class=\"analyticsEnabled ? 'text-yellow-500' : ''\"\n                >\n                  {{ analyticsEnabled ? 'Enabled' : 'Disabled' }}\n                  <div\n                    style=\"\n                      font-size: 0.25em;\n                      line-height: 1;\n                      margin-left: 2px;\n                      margin-top: -4px;\n                      position: absolute;\n                    \"\n                  >\n                    {{ analyticsTag }}\n                  </div>\n                </span>\n              </p>\n              <p class=\"text-gray-600 dark:text-gray-400\">Google Analytics</p>\n            </div>\n          </div>\n        </Link>\n      </div>\n\n      <div\n        v-if=\"authenticated && roles && roles.superAdmin\"\n        class=\"w-full px-3 sm:w-1/2 lg:w-1/2 xl:w-1/2\"\n      >\n        <Link :to=\"{ name: 'app-settings' }\">\n          <div\n            class=\"mb-6 flex w-full items-center rounded-lg border bg-white p-6 text-gray-600 hover:bg-gray-100 dark:border-slate-900 dark:bg-slate-900 dark:hover:border-slate-700 dark:hover:bg-slate-700\"\n          >\n            <svg\n              class=\"css-1mxa28m e10nushx4 float-left mr-1\"\n              xmlns=\"http://www.w3.org/2000/svg\"\n              viewBox=\"0 0 65 65\"\n              width=\"60\"\n              height=\"65\"\n              style=\"margin-top: -1px; margin-right: 5px\"\n            >\n              <path\n                d=\"M29,2.26a4.67,4.67,0,0,0-8,0L14.42,13.53A32.21,32.21,0,0,1,32.17,40.19H27.55A27.68,27.68,0,0,0,12.09,17.47L6,28a15.92,15.92,0,0,1,9.23,12.17H4.62A.76.76,0,0,1,4,39.06l2.94-5a10.74,10.74,0,0,0-3.36-1.9l-2.91,5a4.54,4.54,0,0,0,1.69,6.24A4.66,4.66,0,0,0,4.62,44H19.15a19.4,19.4,0,0,0-8-17.31l2.31-4A23.87,23.87,0,0,1,23.76,44H36.07a35.88,35.88,0,0,0-16.41-31.8l4.67-8a.77.77,0,0,1,1.05-.27c.53.29,20.29,34.77,20.66,35.17a.76.76,0,0,1-.68,1.13H40.6q.09,1.91,0,3.81h4.78A4.59,4.59,0,0,0,50,39.43a4.49,4.49,0,0,0-.62-2.28Z\"\n                transform=\"translate(11, 11)\"\n                :fill=\"user.theme_dark ? '#ffffff' : '#362d59'\"\n              ></path>\n            </svg>\n\n            <div>\n              <p\n                class=\"text-3xl font-semibold text-gray-700 dark:text-gray-300\"\n              >\n                <span\n                  v-if=\"loading\"\n                  class=\"fas fa-circle-notch fa-spin fa-xs\"\n                />\n                <span\n                  v-if=\"!loading\"\n                  :class=\"sentryEnabled ? 'text-red-500' : ''\"\n                >\n                  {{ sentryEnabled ? 'Enabled' : 'Disabled' }}\n                  <div\n                    style=\"\n                      font-size: 0.25em;\n                      line-height: 1;\n                      margin-left: 1px;\n                      margin-top: -4px;\n                      position: absolute;\n                    \"\n                  >\n                    {{ sentryDSN }}\n                    {{ sentryDSN && sentryFormEnabled ? ' / ' : '' }}\n                    {{ sentryFormEnabled ? 'Feedback Enabled' : '' }}\n                  </div>\n                </span>\n              </p>\n              <p class=\"text-gray-600 dark:text-gray-400\">\n                Setry.io Monitoring\n              </p>\n            </div>\n          </div>\n        </Link>\n      </div>\n\n      <div\n        v-if=\"authenticated && roles && roles.superAdmin\"\n        class=\"w-full px-3 sm:w-1/2 lg:w-1/2 xl:w-1/2\"\n      >\n        <Link :to=\"{ name: 'roles' }\">\n          <div\n            class=\"mb-6 flex w-full items-center rounded-lg border bg-white p-6 text-gray-600 hover:bg-gray-100 dark:border-slate-900 dark:bg-slate-900 dark:hover:border-slate-700 dark:hover:bg-slate-700\"\n          >\n            <span\n              class=\"fas fa-shield-alt fa-fw fa-3x text-gray-700 dark:text-gray-300\"\n            />\n            <div>\n              <p\n                class=\"text-3xl font-semibold text-gray-700 dark:text-gray-300\"\n              >\n                <span\n                  v-if=\"loading\"\n                  class=\"fas fa-circle-notch fa-spin fa-xs\"\n                />\n                <span v-if=\"!loading\">\n                  {{ rolesData.length }}\n                </span>\n              </p>\n              <p class=\"text-gray-600 dark:text-gray-400\">Roles</p>\n            </div>\n          </div>\n        </Link>\n      </div>\n\n      <div\n        v-if=\"authenticated && roles && roles.superAdmin\"\n        class=\"w-full px-3 sm:w-1/2 lg:w-1/2 xl:w-1/2\"\n      >\n        <Link :to=\"{ name: 'permissions' }\">\n          <div\n            class=\"mb-6 flex w-full items-center rounded-lg border bg-white p-6 text-gray-600 hover:bg-gray-100 dark:border-slate-900 dark:bg-slate-900 dark:hover:border-slate-700 dark:hover:bg-slate-700\"\n          >\n            <span\n              class=\"fas fa-shield-alt fa-fw fa-3x text-gray-700 dark:text-gray-300\"\n            />\n            <div>\n              <p\n                class=\"text-3xl font-semibold text-gray-700 dark:text-gray-300\"\n              >\n                <span\n                  v-if=\"loading\"\n                  class=\"fas fa-circle-notch fa-spin fa-xs\"\n                />\n                <span v-if=\"!loading\">\n                  {{ permissionsData.length }}\n                </span>\n              </p>\n              <p class=\"text-gray-600 dark:text-gray-400\">Permissions</p>\n            </div>\n          </div>\n        </Link>\n      </div>\n\n      <!--\n      <div class=\"w-full sm:w-1/2 px-3 xl:w-1/3\">\n        <div\n          class=\"mb-6 flex w-full items-center rounded-lg border bg-white p-6 text-blue-400 xl:mb-0\"\n        >\n          <svg\n            class=\"mr-4 hidden h-16 w-16 fill-current lg:block\"\n            viewBox=\"0 0 20 20\"\n          >\n            <path\n              d=\"M17.684,7.925l-5.131-0.67L10.329,2.57c-0.131-0.275-0.527-0.275-0.658,0L7.447,7.255l-5.131,0.67C2.014,7.964,1.892,8.333,2.113,8.54l3.76,3.568L4.924,17.21c-0.056,0.297,0.261,0.525,0.533,0.379L10,15.109l4.543,2.479c0.273,0.153,0.587-0.089,0.533-0.379l-0.949-5.103l3.76-3.568C18.108,8.333,17.986,7.964,17.684,7.925 M13.481,11.723c-0.089,0.083-0.129,0.205-0.105,0.324l0.848,4.547l-4.047-2.208c-0.055-0.03-0.116-0.045-0.176-0.045s-0.122,0.015-0.176,0.045l-4.047,2.208l0.847-4.547c0.023-0.119-0.016-0.241-0.105-0.324L3.162,8.54L7.74,7.941c0.124-0.016,0.229-0.093,0.282-0.203L10,3.568l1.978,4.17c0.053,0.11,0.158,0.187,0.282,0.203l4.578,0.598L13.481,11.723z\"\n            ></path>\n          </svg>\n\n          <div class=\"text-gray-700\">\n            <p class=\"text-3xl font-semibold\">177</p>\n            <p>Product Reviews</p>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"w-full sm:w-1/2 px-3 xl:w-1/3\">\n        <div\n          class=\"flex w-full items-center rounded-lg border bg-white p-6 text-blue-400\"\n        >\n          <svg\n            class=\"mr-4 hidden h-16 w-16 fill-current lg:block\"\n            viewBox=\"0 0 20 20\"\n          >\n            <path\n              d=\"M14.999,8.543c0,0.229-0.188,0.417-0.416,0.417H5.417C5.187,8.959,5,8.772,5,8.543s0.188-0.417,0.417-0.417h9.167C14.812,8.126,14.999,8.314,14.999,8.543 M12.037,10.213H5.417C5.187,10.213,5,10.4,5,10.63c0,0.229,0.188,0.416,0.417,0.416h6.621c0.229,0,0.416-0.188,0.416-0.416C12.453,10.4,12.266,10.213,12.037,10.213 M14.583,6.046H5.417C5.187,6.046,5,6.233,5,6.463c0,0.229,0.188,0.417,0.417,0.417h9.167c0.229,0,0.416-0.188,0.416-0.417C14.999,6.233,14.812,6.046,14.583,6.046 M17.916,3.542v10c0,0.229-0.188,0.417-0.417,0.417H9.373l-2.829,2.796c-0.117,0.116-0.71,0.297-0.71-0.296v-2.5H2.5c-0.229,0-0.417-0.188-0.417-0.417v-10c0-0.229,0.188-0.417,0.417-0.417h15C17.729,3.126,17.916,3.313,17.916,3.542 M17.083,3.959H2.917v9.167H6.25c0.229,0,0.417,0.187,0.417,0.416v1.919l2.242-2.215c0.079-0.077,0.184-0.12,0.294-0.12h7.881V3.959z\"\n            ></path>\n          </svg>\n\n          <div class=\"text-gray-700\">\n            <p class=\"text-3xl font-semibold\">31</p>\n            <p>New Enquiries</p>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"w-full sm:w-1/2 px-3 xl:w-1/3\">\n        <div\n          class=\"flex w-full items-center rounded-lg border bg-white p-6 text-blue-400\"\n        >\n          <svg\n            class=\"mr-4 hidden h-16 w-16 fill-current lg:block\"\n            viewBox=\"0 0 20 20\"\n          >\n            <path\n              d=\"M17.431,2.156h-3.715c-0.228,0-0.413,0.186-0.413,0.413v6.973h-2.89V6.687c0-0.229-0.186-0.413-0.413-0.413H6.285c-0.228,0-0.413,0.184-0.413,0.413v6.388H2.569c-0.227,0-0.413,0.187-0.413,0.413v3.942c0,0.228,0.186,0.413,0.413,0.413h14.862c0.228,0,0.413-0.186,0.413-0.413V2.569C17.844,2.342,17.658,2.156,17.431,2.156 M5.872,17.019h-2.89v-3.117h2.89V17.019zM9.587,17.019h-2.89V7.1h2.89V17.019z M13.303,17.019h-2.89v-6.651h2.89V17.019z M17.019,17.019h-2.891V2.982h2.891V17.019z\"\n            ></path>\n          </svg>\n\n          <div class=\"text-gray-700\">\n            <p class=\"text-3xl font-semibold\">1,653</p>\n            <p>Product Views</p>\n          </div>\n        </div>\n      </div>\n       -->\n    </div>\n\n    <!--\n    <div class=\"-mx-3 flex flex-wrap\">\n      <div class=\"w-full px-3 xl:w-1/3\">\n        <p class=\"mb-4 text-xl font-semibold\">Recent Sales</p>\n\n        <div class=\"mb-8 w-full rounded-lg border bg-white p-4 xl:mb-0\">\n          <canvas id=\"buyers-chart\" width=\"600\" height=\"400\"></canvas>\n        </div>\n      </div>\n\n      <div class=\"w-full px-3 xl:w-1/3\">\n        <p class=\"mb-4 text-xl font-semibold\">Recent Reviews</p>\n\n        <div class=\"mb-8 w-full rounded-lg border bg-white p-4 xl:mb-0\">\n          <canvas id=\"reviews-chart\" width=\"600\" height=\"400\"></canvas>\n        </div>\n      </div>\n\n      <div class=\"w-full px-3 xl:w-1/3\">\n        <p class=\"mb-4 text-xl font-semibold\">Recent Transactions</p>\n        <div class=\"w-full rounded-lg border bg-white p-4\">\n          <div\n            class=\"mb-4 flex w-full items-center justify-between rounded-lg border bg-gray-100 px-4 py-2\"\n          >\n            <div>\n              <p class=\"text-xl font-semibold\">Trent Murphy</p>\n              <p>Product 1</p>\n            </div>\n            <span class=\"text-lg font-semibold text-green-500\">$25.00</span>\n          </div>\n\n          <div\n            class=\"mb-4 flex w-full items-center justify-between rounded-lg border bg-gray-100 px-4 py-2\"\n          >\n            <div>\n              <p class=\"text-xl font-semibold\">Joseph Brent</p>\n              <p>Product 34</p>\n            </div>\n            <span class=\"text-lg font-semibold text-red-500\">$74.99</span>\n          </div>\n\n          <div\n            class=\"mb-4 flex w-full items-center justify-between rounded-lg border bg-gray-100 px-4 py-2\"\n          >\n            <div>\n              <p class=\"text-xl font-semibold\">Jacob Bator</p>\n              <p>Product 23</p>\n            </div>\n            <span class=\"text-lg font-semibold text-green-500\">$14.95</span>\n          </div>\n\n          <div\n            class=\"flex w-full items-center justify-between rounded-lg border bg-gray-100 px-4 py-2\"\n          >\n            <div>\n              <p class=\"text-xl font-semibold\">Alex Mason</p>\n              <p>Product 66</p>\n            </div>\n            <span class=\"text-lg font-semibold text-green-500\">$44.99</span>\n          </div>\n        </div>\n      </div>\n    </div>\n    -->\n  </div>\n</AdminLayout>\n</template>\n\n<script>\nimport axios from 'axios';\nimport useAuth from '@/Composables/useAuth';\nimport { ChevronRightIcon } from '@heroicons/vue/24/outline';\nimport AdminLayout from '@/Layouts/AdminLayout.vue';\nimport RolesBadges from '@/Elements/roles/RolesBadges.vue'\nimport { Link } from \"@inertiajs/vue3\";\n\nexport default {\n  name: 'Admin',\n  components: {\n    ChevronRightIcon,\n    AdminLayout,\n    Link,\n    RolesBadges,\n  },\n  props: {},\n  setup() {\n    const { user, roles, authenticated } = useAuth();\n    return {\n      user,\n      roles,\n      authenticated\n    };\n  },\n  data() {\n    return {\n      dataReady: false,\n      loading: false,\n      users: [],\n      rolesData: [],\n      permissionsData: [],\n      authSettings: [],\n      analyticsData: [],\n      monitoringData: [],\n      // buyersData: {\n      //   type: 'line',\n      //   data: {\n      //     labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],\n      //     datasets: [\n      //       {\n      //         backgroundColor: 'rgba(99,179,237,0.4)',\n      //         strokeColor: '#63b3ed',\n      //         pointColor: '#fff',\n      //         pointStrokeColor: '#63b3ed',\n      //         data: [203, 156, 99, 251, 305, 247, 256],\n      //       },\n      //       {\n      //         backgroundColor: 'rgba(198,198,198,0.4)',\n      //         strokeColor: '#f7fafc',\n      //         pointColor: '#fff',\n      //         pointStrokeColor: '#f7fafc',\n      //         data: [86, 97, 144, 114, 94, 108, 156],\n      //       },\n      //     ],\n      //   },\n      //   options: {\n      //     legend: {\n      //       display: false,\n      //     },\n      //     scales: {\n      //       yAxes: [\n      //         {\n      //           gridLines: {\n      //             display: false,\n      //           },\n      //           ticks: {\n      //             display: false,\n      //           },\n      //         },\n      //       ],\n      //       xAxes: [\n      //         {\n      //           gridLines: {\n      //             display: false,\n      //           },\n      //         },\n      //       ],\n      //     },\n      //   },\n      // },\n      // reviewsData: {\n      //   type: 'bar',\n      //   data: {\n      //     labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],\n      //     datasets: [\n      //       {\n      //         backgroundColor: 'rgba(99,179,237,0.4)',\n      //         strokeColor: '#63b3ed',\n      //         pointColor: '#fff',\n      //         pointStrokeColor: '#63b3ed',\n      //         data: [203, 156, 99, 251, 305, 247, 256],\n      //       },\n      //     ],\n      //   },\n      //   options: {\n      //     legend: {\n      //       display: false,\n      //     },\n      //     scales: {\n      //       yAxes: [\n      //         {\n      //           gridLines: {\n      //             display: false,\n      //           },\n      //           ticks: {\n      //             display: false,\n      //           },\n      //         },\n      //       ],\n      //       xAxes: [\n      //         {\n      //           gridLines: {\n      //             display: false,\n      //           },\n      //         },\n      //       ],\n      //     },\n      //   },\n      // },\n    };\n  },\n  computed: {\n    \n    greeting() {\n      const date = new Date();\n      const currentTime = date.getHours();\n      let greeting;\n      if (currentTime >= 0 && currentTime <= 12) {\n        greeting = 'Good Morning';\n      } else if (currentTime > 12 && currentTime <= 18) {\n        greeting = 'Good Afternoon';\n      } else {\n        greeting = 'Good Evening';\n      }\n      return greeting;\n    },\n    analyticsEnabled() {\n      const found = this.analyticsData.find(\n        (obj) => obj.key == 'enableGoogleAnalytics',\n      );\n      if (found && found.val && found.val == 1) {\n        return true;\n      }\n      return false;\n    },\n    analyticsTag() {\n      const found = this.analyticsData.find(\n        (obj) => obj.key == 'appGoogleAnalyticsKey',\n      );\n      if (found && found.val && found.val != '') {\n        return null;\n        // return found.val;\n      }\n      return 'MISSING TAG ID';\n    },\n    sentryEnabled() {\n      const found = this.monitoringData.find(\n        (obj) => obj.key == 'enableSentryMonitoring',\n      );\n      if (found && found.val && found.val == 1) {\n        return true;\n      }\n      return false;\n    },\n    sentryFormEnabled() {\n      const found = this.monitoringData.find(\n        (obj) => obj.key == 'enableSentryMonitoringFeedbakForm',\n      );\n      if (found && found.val && found.val == 1) {\n        return true;\n      }\n      return false;\n    },\n    sentryDSN() {\n      const found = this.monitoringData.find((obj) => obj.key == 'sentryIoDSN');\n      if (found && found.val && found.val != '') {\n        return null;\n      }\n      return 'MISSING DSN (URL)';\n    },\n    zohoImgUrl() {\n      if (this.user && this.user.theme_dark) {\n        return zohoLight;\n      } else {\n        return zohoDark;\n      }\n    },\n  },\n  mounted() {\n    // this.getDashboardData();\n    // new Chart(document.getElementById('buyers-chart'), this.buyersData);\n    // new Chart(document.getElementById('reviews-chart'), this.reviewsData);\n  },\n  methods: {\n    async getDashboardData() {\n      this.loading = true;\n      await axios\n        .get('/api/dashboard/data')\n        .then(({ data }) => {\n          this.users = data.users;\n          this.rolesData = data.roles;\n          this.authSettings = data.authSettings;\n          this.permissionsData = data.permissions;\n          this.analyticsData = data.analytics;\n          this.monitoringData = data.monitoring;\n          this.dataReady = true;\n          this.loading = false;\n        })\n        .catch(({ response }) => {\n          this.popToast({\n            message: 'Error Getting Users',\n            timer: 5000,\n            icon: 'error',\n          });\n          this.dataReady = true;\n        });\n      this.dataReady = true;\n    },\n    checkSettingEnabled(key = null) {\n      let found = false;\n      let enabled = false;\n      if (key) {\n        found = this.authSettings.find((obj) => obj.key == key);\n        if (found && found.val == 1) {\n          enabled = true;\n        }\n      }\n      return enabled;\n    },\n  },\n};\n</script>\n\n<style scoped>\n.fa-xs {\n  font-size: 0.75em !important;\n}\n</style>\n<style lang=\"scss\" scoped></style>\n"
  },
  {
    "path": "resources/js/Pages/admin/ServerInfo.vue",
    "content": "<template>\n    <AdminLayout>\n        <div v-html=\"info\" />\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue'\nimport AdminLayout from '@/Layouts/AdminLayout.vue'\n\nexport default defineComponent({\n    components: {\n        AdminLayout\n    },\n    props: {\n        info: {\n            type: String,\n        },\n    },\n    setup() {\n    \n\n    }\n})\n\n</script>"
  },
  {
    "path": "resources/js/Pages/admin/courses/CourseStudent.vue",
    "content": "<template>\n    <AdminLayout>\n        <CourseLayout :course=\"course\">\n            <Card>\n                <div v-for=\"student in students\" :key=\"student.id\" class=\"relative rounded-lg border border-gray-300 bg-white px-6 py-5 mb-5 shadow-sm flex items-center space-x-3 hover:border-gray-400 focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-indigo-500\">\n                    <div class=\"flex-shrink-0\">\n                        <img class=\"h-10 w-10 rounded-full\" :src=\"student.avatar\" alt=\"\" />\n                    </div>\n                    <div class=\"flex-1 min-w-0\">\n                        <a href=\"#\" class=\"focus:outline-none\">\n                        <span class=\"absolute inset-0\" aria-hidden=\"true\" />\n                        <p class=\"text-sm font-medium text-gray-900\">\n                            {{ student.full_name }}\n                        </p>\n                        <p class=\"text-sm text-gray-500 truncate\">\n                            {{ student.progress }}\n                        </p>\n                        </a>\n                    </div>\n                    </div>\n            </Card>\n\n        </CourseLayout>\n    </AdminLayout>\n</template>\n\n<script setup lang=\"ts\">\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport CourseLayout from '@/Elements/course/CourseLayout.vue';\nimport SingleSection from '@/Elements/course/SingleSection.vue'\nimport { Course, Student } from \"@/types\";\n\ndefineProps<{\n    course: Course,\n    students: Student[]\n}>()\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/courses/CreateCourse.vue",
    "content": "<template>\n    <AdminLayout>\n        <CourseLayout :course=\"course\">\n            <CourseForm :course=\"course\"/>\n        </CourseLayout>\n    </AdminLayout>\n</template>\n\n<script setup lang=\"ts\">\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport CourseForm from '@/Elements/course/CourseForm.vue'\nimport CourseLayout from '@/Elements/course/CourseLayout.vue'\nimport { Course } from \"@/types\";\n\ndefineProps<{\n    course?: Course\n}>()\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/courses/Index.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"users\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1>Courses</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Button is=\"a\" :href=\"route('admin.courses.create')\">Create Course </Button>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <DataTable\n                    v-model=\"selected\"\n                    :rows=\"response.data\"\n                    :columns=\"columns\"\n                >\n                    <template #actions-data=\"{ row }\">\n                        <div class=\"flex\">\n                            <Link\n                                :href=\"route('admin.courses.edit', row)\"\n                            >\n                                <PencilIcon class=\"mr-2 h-6 w-6\"></PencilIcon>\n                            </Link>\n                            <Link\n                                @click=\"deleteCourse(row)\"\n                                as=\"button\"\n                                href=\"\"\n                            >\n                                <TrashIcon class=\"mr-2 h-6 w-6\"></TrashIcon>\n                            </Link>\n                        </div>\n                    </template>\n                </DataTable>\n                <Pagination :paginate=\"response.meta\" class=\"justify-end\" />\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\">\nimport {\n    ChevronRightIcon,\n    TrashIcon,\n    PencilIcon,\n} from \"@heroicons/vue/24/outline\";\n\nimport CircleSvg from \"@/Components/CircleSvg.vue\";\nimport { LinkType, JsonResponse, Course } from \"@/types\";\nimport { PropType, ref } from \"vue\";\nimport { Link } from \"@inertiajs/vue3\";\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport DataTable from \"@/Components/Datatable/Table.vue\";\nimport Checkbox from \"@/Components/Form/Checkbox.vue\";\nimport Modal from \"@/Components/Modal.vue\";\nimport Card from \"@/Components/Card.vue\";\nimport { router } from \"@inertiajs/vue3\";\nimport Pagination from \"@/Components/Pagination.vue\";\nimport Select from \"@/Components/Form/Select.vue\";\nimport Button from \"@/Components/Button.vue\";\n\nexport default {\n    name: \"Courses\",\n    components: {\n        AdminLayout,\n        Breadcrumb,\n        ChevronRightIcon,\n        CircleSvg,\n        Link,\n        DataTable,\n        Checkbox,\n        TrashIcon,\n        PencilIcon,\n        Modal,\n        Card,\n        Pagination,\n        Select,\n        Button\n    },\n    props: {\n        response: {\n            type: Object as PropType<JsonResponse<Course[]>>,\n            required: true,\n        }\n    },\n    setup(props) {\n        const selected = ref([]);\n        const columns = [\n            {\n                key: \"title\",\n                label: \"Title\",\n            },\n            {\n                key: \"price\",\n                label: \"Price\",\n            },\n            {\n                key: \"start_date\",\n                label: \"Started at\",\n            },\n            {\n                key: \"status\",\n                label: \"Status\",\n            },\n            {\n                key: \"created_by\",\n                label: \"Creator\",\n            },\n            {\n                key: \"actions\",\n            },\n        ];\n\n        function deleteCourse(Course: Course) {\n            if (confirm(\"Are you sure you want to delete this item?\")) {\n                router.delete(route(\"admin.Courses.destroy\", Course.id));\n            }\n        }\n\n        return {\n            selected,\n            columns,\n            deleteCourse,\n        };\n    },\n    computed: {\n        breadcrumb(): LinkType[] {\n            return [\n                {\n                    name: \"Courses\",\n                    href: route(\"admin.courses.index\"),\n                    current: route().current(\"admin.courses.index\"),\n                },\n            ];\n        },\n    },\n};\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/courses/Sections.vue",
    "content": "<template>\n    <AdminLayout>\n        <CourseLayout :course=\"course\">\n                <SingleSection  v-for=\"section in sections\" :key=\"section.id\" :section=\"section\" :course=\"course\"/>\n        </CourseLayout>\n    </AdminLayout>\n</template>\n\n<script setup lang=\"ts\">\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport CourseLayout from '@/Elements/course/CourseLayout.vue';\nimport SingleSection from '@/Elements/course/SingleSection.vue'\nimport { Course, Section } from \"@/types\";\n\ndefineProps<{\n    course: Course,\n    sections: Section[]\n}>()\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/exams/Create.vue",
    "content": "<template>\n    <AdminLayout>\n        <ExamLayout>\n            <CreateExam />\n        </ExamLayout>\n    </AdminLayout>\n</template>\n\n<script setup lang=\"ts\">\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport CreateExam from '@/Elements/exam/CreateExam.vue'\nimport ExamLayout from '@/Elements/exam/ExamLayout.vue'\n\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/exams/CreateQuestion.vue",
    "content": "<template>\n    <AdminLayout>\n        <ExamLayout :exam=\"exam\">\n            <CreateQuestion :exam=\"exam\" :question=\"question\"></CreateQuestion>\n        </ExamLayout>\n    </AdminLayout>\n</template>\n\n<script setup lang=\"ts\">\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport CreateExam from '@/Elements/exam/CreateExam.vue'\nimport ExamLayout from '@/Elements/exam/ExamLayout.vue'\nimport CreateQuestion from '@/Elements/exam/CreateQuestion.vue'\nimport { Exam, Question } from \"@/types\";\n\ndefineProps<{\n    exam: Exam,\n    question?: Question\n}>()\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/exams/Edit.vue",
    "content": "<template>\n    <AdminLayout>\n        <ExamLayout :exam=\"exam\">\n            <CreateExam :exam=\"exam\" />\n        </ExamLayout>\n    </AdminLayout>\n</template>\n\n<script setup lang=\"ts\">\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport CreateExam from '@/Elements/exam/CreateExam.vue'\nimport ExamLayout from '@/Elements/exam/ExamLayout.vue'\nimport { Exam } from \"@/types\";\n\ndefineProps<{\n    exam: Exam\n}>()\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/exams/Index.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"users\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1>Exams</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Button is=\"a\" :href=\"route('admin.exams.create')\">Create Exam </Button>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <DataTable\n                    v-model=\"selected\"\n                    :rows=\"response.data\"\n                    :columns=\"columns\"\n                >\n                    <template #actions-data=\"{ row }\">\n                        <div class=\"flex justify-end\">\n                            <Link\n                                :href=\"route('admin.exams.edit', row)\"\n                            >\n                                <PencilIcon class=\"mr-2 h-6 w-6\"></PencilIcon>\n                            </Link>\n                            <Link\n                                @click=\"deleteExam(row)\"\n                                as=\"button\"\n                                href=\"\"\n                            >\n                                <TrashIcon class=\"mr-2 h-6 w-6 text-red-500\"></TrashIcon>\n                            </Link>\n                        </div>\n                    </template>\n                </DataTable>\n                <Pagination :paginate=\"response.meta\" class=\"justify-end\" />\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\">\nimport {\n    ChevronRightIcon,\n    TrashIcon,\n    PencilIcon,\n} from \"@heroicons/vue/24/outline\";\n\nimport CircleSvg from \"@/Components/CircleSvg.vue\";\nimport { LinkType, JsonResponse, Exam } from \"@/types\";\nimport { PropType, ref } from \"vue\";\nimport { Link } from \"@inertiajs/vue3\";\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport DataTable from \"@/Components/Datatable/Table.vue\";\nimport Checkbox from \"@/Components/Form/Checkbox.vue\";\nimport Modal from \"@/Components/Modal.vue\";\nimport Card from \"@/Components/Card.vue\";\nimport { router } from \"@inertiajs/vue3\";\nimport Pagination from \"@/Components/Pagination.vue\";\nimport Select from \"@/Components/Form/Select.vue\";\nimport Button from \"@/Components/Button.vue\";\n\nexport default {\n    name: \"Exams\",\n    components: {\n        AdminLayout,\n        Breadcrumb,\n        ChevronRightIcon,\n        CircleSvg,\n        Link,\n        DataTable,\n        Checkbox,\n        TrashIcon,\n        PencilIcon,\n        Modal,\n        Card,\n        Pagination,\n        Select,\n        Button\n    },\n    props: {\n        response: {\n            type: Object as PropType<JsonResponse<Exam[]>>,\n            required: true,\n        }\n    },\n    setup(props) {\n        const selected = ref([]);\n        const columns = [\n            {\n                key: \"title\",\n                label: \"Title\",\n            },\n            {\n                key: \"duration\",\n                label: \"Duration\",\n            },\n            {\n                key: \"pass_mark\",\n                label: \"Pass mark\",\n            },\n            {\n                key: \"number_of_questions\",\n                label: \"Questions\",\n            },\n            {\n                key: \"difficulty\",\n                label: \"Difficulty\",\n            },\n            {\n                key: \"certification\",\n                label: \"Certification\",\n            },\n            {\n                key: \"status\",\n                label: \"Status\",\n            },\n            {\n                key: \"created_by\",\n                label: \"Creator\",\n            },\n            {\n                key: \"actions\",\n            },\n        ];\n\n        function deleteExam(exam: Exam) {\n            if (confirm(\"Are you sure you want to delete this item?\")) {\n                router.delete(route(\"admin.exams.destroy\", exam.id));\n            }\n        }\n\n        return {\n            selected,\n            columns,\n            deleteExam,\n        };\n    },\n    computed: {\n        breadcrumb(): LinkType[] {\n            return [\n                {\n                    name: \"Exams\",\n                    href: route(\"admin.exams.index\"),\n                    current: route().current(\"admin.exams.index\"),\n                },\n            ];\n        },\n    },\n};\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/exams/Questions.vue",
    "content": "<template>\n    <AdminLayout>\n        <ExamLayout :exam=\"exam\">\n            <QuestionTable :exam=\"exam\" :questions=\"questions\"/>\n        </ExamLayout>\n    </AdminLayout>\n</template>\n\n<script setup lang=\"ts\">\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport CreateExam from '@/Elements/exam/CreateExam.vue'\nimport ExamLayout from '@/Elements/exam/ExamLayout.vue'\nimport QuestionTable from '@/Elements/exam/QuestionTable.vue'\nimport { Exam, Question } from \"@/types\";\n\ndefineProps<{\n    exam: Exam,\n    questions: Question[]\n}>()\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/roles/Create.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed, ref, watch } from \"vue\";\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport Label from \"@/Components/Form/Label.vue\";\nimport Input from \"@/Components/Form/Input.vue\";\nimport { Link, useForm, usePage } from \"@inertiajs/vue3\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport { CheckCircleIcon, XMarkIcon, ArrowLeftIcon } from \"@heroicons/vue/24/outline\";\nimport { LinkType } from \"@/types\";\n\ninterface Permission {\n    id: number;\n    name: string;\n}\n\nconst props = defineProps<{\n    permissions: Permission[];\n}>();\n\nconst page = usePage();\nconst flashProp = computed(() => (page.props as any).flash as { success?: string; error?: string } | undefined);\n\nconst showToast = ref(false);\nconst toastMessage = ref('');\nconst toastType = ref<'success' | 'error'>('success');\nlet toastTimer: ReturnType<typeof setTimeout>;\n\nwatch(flashProp, (f) => {\n    if (f?.success) {\n        toastMessage.value = f.success;\n        toastType.value = 'success';\n        showToast.value = true;\n        clearTimeout(toastTimer);\n        toastTimer = setTimeout(() => { showToast.value = false; }, 4000);\n    } else if (f?.error) {\n        toastMessage.value = f.error;\n        toastType.value = 'error';\n        showToast.value = true;\n        clearTimeout(toastTimer);\n        toastTimer = setTimeout(() => { showToast.value = false; }, 5000);\n    }\n}, { immediate: true });\n\nconst roleForm = useForm({\n    name: '' as string,\n    permissions: [] as number[],\n});\n\n// Group permissions by their prefix (e.g. \"course\", \"exam\", ...)\nconst groupedPermissions = computed(() => {\n    const groups: Record<string, Permission[]> = {};\n    for (const perm of props.permissions) {\n        const group = perm.name.split('.')[0].trim();\n        if (!groups[group]) groups[group] = [];\n        groups[group].push(perm);\n    }\n    return groups;\n});\n\nfunction groupAllChecked(perms: Permission[]): boolean {\n    return perms.every((p) => roleForm.permissions.includes(p.id));\n}\n\nfunction toggleAll(perms: Permission[], checked: boolean) {\n    perms.forEach((p) => {\n        if (checked && !roleForm.permissions.includes(p.id)) {\n            roleForm.permissions.push(p.id);\n        } else if (!checked) {\n            roleForm.permissions = roleForm.permissions.filter((id) => id !== p.id);\n        }\n    });\n}\n\nfunction submit() {\n    roleForm.post(route(\"admin.roles.store\"));\n}\n\nconst breadcrumb = computed<LinkType[]>(() => [\n    { name: 'Roles', href: route('admin.roles.index'), current: false },\n    { name: 'Create', href: route('admin.roles.create'), current: true },\n]);\n</script>\n\n<template>\n    <AdminLayout>\n        <div id=\"create-role\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1 class=\"text-lg\">Create Role</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Link :href=\"route('admin.roles.index')\" class=\"inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-indigo-600 dark:text-gray-400 dark:hover:text-indigo-400 transition-colors\">\n                            <ArrowLeftIcon class=\"h-4 w-4\" />\n                            Back to Roles\n                        </Link>\n                    </div>\n                </div>\n            </Card>\n\n            <!-- Toast notification -->\n            <transition\n                enter-active-class=\"transition ease-out duration-300\"\n                enter-from-class=\"opacity-0 -translate-y-3\"\n                enter-to-class=\"opacity-100 translate-y-0\"\n                leave-active-class=\"transition ease-in duration-200\"\n                leave-from-class=\"opacity-100 translate-y-0\"\n                leave-to-class=\"opacity-0 -translate-y-3\"\n            >\n                <div\n                    v-if=\"showToast\"\n                    :class=\"[\n                        'flex items-start gap-3 mb-4 px-4 py-3 rounded-xl border shadow-sm',\n                        toastType === 'success'\n                            ? 'bg-green-50 border-green-200 text-green-800'\n                            : 'bg-red-50 border-red-200 text-red-800',\n                    ]\"\n                >\n                    <CheckCircleIcon v-if=\"toastType === 'success'\" class=\"h-5 w-5 flex-shrink-0 text-green-500 mt-0.5\" />\n                    <span class=\"flex-1 text-sm font-medium\">{{ toastMessage }}</span>\n                    <button type=\"button\" @click=\"showToast = false\" class=\"flex-shrink-0 opacity-60 hover:opacity-100 transition-opacity\">\n                        <XMarkIcon class=\"h-4 w-4\" />\n                    </button>\n                </div>\n            </transition>\n\n            <Card>\n                <template #header>\n                    <h1 class=\"text-lg font-semibold\">Create Role</h1>\n                </template>\n\n                <form @submit.prevent=\"submit\" class=\"space-y-6\">\n                    <!-- Role name -->\n                    <div class=\"max-w-sm\">\n                        <Label label=\"Role Name\" name=\"name\" :error=\"roleForm.errors.name\">\n                            <Input v-model=\"roleForm.name\" required placeholder=\"e.g. editor\" />\n                        </Label>\n                    </div>\n\n                    <!-- Permissions -->\n                    <div>\n                        <h3 class=\"text-sm font-semibold text-gray-700 mb-3\">Permissions</h3>\n                        <div v-if=\"permissions.length\" class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n                            <div\n                                v-for=\"(perms, group) in groupedPermissions\"\n                                :key=\"group\"\n                                class=\"border border-gray-200 rounded-lg p-4 bg-gray-50\"\n                            >\n                                <!-- Group header with select-all toggle -->\n                                <label class=\"flex items-center gap-2 mb-3 cursor-pointer\">\n                                    <input\n                                        type=\"checkbox\"\n                                        :checked=\"groupAllChecked(perms)\"\n                                        @change=\"(e) => toggleAll(perms, (e.target as HTMLInputElement).checked)\"\n                                        class=\"rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500\"\n                                    />\n                                    <span class=\"text-xs font-bold uppercase tracking-wide text-gray-600 capitalize\">{{ group }}</span>\n                                </label>\n                                <!-- Individual permissions -->\n                                <div class=\"space-y-2 pl-1\">\n                                    <label\n                                        v-for=\"perm in perms\"\n                                        :key=\"perm.id\"\n                                        class=\"flex items-center gap-2 cursor-pointer\"\n                                    >\n                                        <input\n                                            type=\"checkbox\"\n                                            :value=\"perm.id\"\n                                            v-model=\"roleForm.permissions\"\n                                            class=\"rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500\"\n                                        />\n                                        <span class=\"text-sm text-gray-700\">{{ perm.name.trim() }}</span>\n                                    </label>\n                                </div>\n                            </div>\n                        </div>\n                        <p v-else class=\"text-sm text-gray-400\">No permissions found. Run the seeder first.</p>\n                    </div>\n\n                    <Button :disabled=\"roleForm.processing\">Create Role</Button>\n                </form>\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/admin/roles/Edit.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed, ref, watch } from \"vue\";\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport Label from \"@/Components/Form/Label.vue\";\nimport Input from \"@/Components/Form/Input.vue\";\nimport { Role, LinkType } from \"@/types\";\nimport { Link, useForm, usePage } from \"@inertiajs/vue3\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport { CheckCircleIcon, XMarkIcon, ArrowLeftIcon } from \"@heroicons/vue/24/outline\";\n\ninterface Permission {\n    id: number;\n    name: string;\n}\n\nconst props = defineProps<{\n    role: Role;\n    permissions: Permission[];\n}>();\n\nconst page = usePage();\nconst flashProp = computed(() => (page.props as any).flash as { success?: string; error?: string } | undefined);\n\n// Local dismissible state\nconst showToast = ref(false);\nconst toastMessage = ref('');\nconst toastType = ref<'success' | 'error'>('success');\nlet toastTimer: ReturnType<typeof setTimeout>;\n\nwatch(flashProp, (f) => {\n    if (f?.success) {\n        toastMessage.value = f.success;\n        toastType.value = 'success';\n        showToast.value = true;\n        clearTimeout(toastTimer);\n        toastTimer = setTimeout(() => { showToast.value = false; }, 4000);\n    } else if (f?.error) {\n        toastMessage.value = f.error;\n        toastType.value = 'error';\n        showToast.value = true;\n        clearTimeout(toastTimer);\n        toastTimer = setTimeout(() => { showToast.value = false; }, 5000);\n    }\n}, { immediate: true });\n\n// Pre-select the role's current permission IDs\nconst currentPermissionIds: number[] = (props.role.permissions ?? []).map((p: any) => p.id as number);\n\nconst roleForm = useForm({\n    name: props.role.name,\n    permissions: currentPermissionIds,\n});\n\n// Group permissions by prefix\nconst groupedPermissions = computed(() => {\n    const groups: Record<string, Permission[]> = {};\n    for (const perm of props.permissions) {\n        const group = perm.name.split('.')[0].trim();\n        if (!groups[group]) groups[group] = [];\n        groups[group].push(perm);\n    }\n    return groups;\n});\n\nfunction groupAllChecked(perms: Permission[]): boolean {\n    return perms.every((p) => roleForm.permissions.includes(p.id));\n}\n\nfunction toggleAll(perms: Permission[], checked: boolean) {\n    perms.forEach((p) => {\n        if (checked && !roleForm.permissions.includes(p.id)) {\n            roleForm.permissions.push(p.id);\n        } else if (!checked) {\n            roleForm.permissions = roleForm.permissions.filter((id) => id !== p.id);\n        }\n    });\n}\n\nfunction submit() {\n    roleForm.put(route(\"admin.roles.update\", props.role.id));\n}\n\nconst breadcrumb = computed<LinkType[]>(() => [\n    { name: 'Roles', href: route('admin.roles.index'), current: false },\n    { name: props.role.name, href: route('admin.roles.edit', props.role.id), current: true },\n]);\n</script>\n\n<template>\n    <AdminLayout>\n        <div id=\"edit-role\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1 class=\"text-lg\">Edit Role</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Link :href=\"route('admin.roles.index')\" class=\"inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-indigo-600 dark:text-gray-400 dark:hover:text-indigo-400 transition-colors\">\n                            <ArrowLeftIcon class=\"h-4 w-4\" />\n                            Back to Roles\n                        </Link>\n                    </div>\n                </div>\n            </Card>\n\n            <!-- Toast notification -->\n            <transition\n                enter-active-class=\"transition ease-out duration-300\"\n                enter-from-class=\"opacity-0 -translate-y-3\"\n                enter-to-class=\"opacity-100 translate-y-0\"\n                leave-active-class=\"transition ease-in duration-200\"\n                leave-from-class=\"opacity-100 translate-y-0\"\n                leave-to-class=\"opacity-0 -translate-y-3\"\n            >\n                <div\n                    v-if=\"showToast\"\n                    :class=\"[\n                        'flex items-start gap-3 mb-4 px-4 py-3 rounded-xl border shadow-sm',\n                        toastType === 'success'\n                            ? 'bg-green-50 border-green-200 text-green-800'\n                            : 'bg-red-50 border-red-200 text-red-800',\n                    ]\"\n                >\n                    <CheckCircleIcon v-if=\"toastType === 'success'\" class=\"h-5 w-5 flex-shrink-0 text-green-500 mt-0.5\" />\n                    <span class=\"flex-1 text-sm font-medium\">{{ toastMessage }}</span>\n                    <button type=\"button\" @click=\"showToast = false\" class=\"flex-shrink-0 opacity-60 hover:opacity-100 transition-opacity\">\n                        <XMarkIcon class=\"h-4 w-4\" />\n                    </button>\n                </div>\n            </transition>\n\n            <Card>\n                <template #header>\n                    <h1 class=\"text-lg font-semibold\">Edit Role</h1>\n                </template>\n\n                <!-- Flash success -->\n                <!-- (handled by the toast above) -->\n\n                <form @submit.prevent=\"submit\" class=\"space-y-6\">\n                    <!-- Role name -->\n                    <div class=\"max-w-sm\">\n                        <Label label=\"Role Name\" name=\"name\" :error=\"roleForm.errors.name\">\n                            <Input v-model=\"roleForm.name\" required />\n                        </Label>\n                    </div>\n\n                    <!-- Permissions -->\n                    <div>\n                        <h3 class=\"text-sm font-semibold text-gray-700 mb-3\">Permissions</h3>\n                        <div v-if=\"permissions.length\" class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n                            <div\n                                v-for=\"(perms, group) in groupedPermissions\"\n                                :key=\"group\"\n                                class=\"border border-gray-200 rounded-lg p-4 bg-gray-50\"\n                            >\n                                <!-- Group header with select-all toggle -->\n                                <label class=\"flex items-center gap-2 mb-3 cursor-pointer\">\n                                    <input\n                                        type=\"checkbox\"\n                                        :checked=\"groupAllChecked(perms)\"\n                                        @change=\"(e) => toggleAll(perms, (e.target as HTMLInputElement).checked)\"\n                                        class=\"rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500\"\n                                    />\n                                    <span class=\"text-xs font-bold uppercase tracking-wide text-gray-600 capitalize\">{{ group }}</span>\n                                </label>\n                                <!-- Individual permissions -->\n                                <div class=\"space-y-2 pl-1\">\n                                    <label\n                                        v-for=\"perm in perms\"\n                                        :key=\"perm.id\"\n                                        class=\"flex items-center gap-2 cursor-pointer\"\n                                    >\n                                        <input\n                                            type=\"checkbox\"\n                                            :value=\"perm.id\"\n                                            v-model=\"roleForm.permissions\"\n                                            class=\"rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500\"\n                                        />\n                                        <span class=\"text-sm text-gray-700\">{{ perm.name.trim() }}</span>\n                                    </label>\n                                </div>\n                            </div>\n                        </div>\n                        <p v-else class=\"text-sm text-gray-400\">No permissions found. Run the seeder first.</p>\n                    </div>\n\n                    <Button :disabled=\"roleForm.processing\">Update Role</Button>\n                </form>\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n"
  },
  {
    "path": "resources/js/Pages/admin/roles/Index.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"users\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1>Roles</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Button is=\"a\" :href=\"route('admin.roles.create')\">Create Role </Button>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <DataTable\n                    v-model=\"selected\"\n                    :rows=\"response.data\"\n                    :columns=\"columns\"\n                >\n                    <template #users_count-data=\"{ row }\">\n                        <span class=\"inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-semibold bg-indigo-50 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300\">\n                            {{ row.users_count }}\n                        </span>\n                    </template>\n                    <template #permissions_count-data=\"{ row }\">\n                        <span class=\"inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-semibold bg-amber-50 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300\">\n                            {{ row.permissions_count }}\n                        </span>\n                    </template>\n                    <template #actions-data=\"{ row }\">\n                        <div class=\"flex\">\n                            <Link\n                                :href=\"route('admin.roles.edit', row)\"\n                                v-if=\"canModify(row.name)\"\n                            >\n                                <PencilIcon class=\"mr-2 h-6 w-6\"></PencilIcon>\n                            </Link>\n                            <Link\n                                @click=\"deleteRole(row)\"\n                                as=\"button\"\n                                href=\"\"\n                                v-if=\"canModify(row.name)\"\n                            >\n                                <TrashIcon class=\"mr-2 h-6 w-6\"></TrashIcon>\n                            </Link>\n                        </div>\n                    </template>\n                </DataTable>\n                <Pagination :paginate=\"response.meta\" class=\"justify-end\" />\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\">\nimport {\n    ChevronRightIcon,\n    TrashIcon,\n    PencilIcon,\n} from \"@heroicons/vue/24/outline\";\n\nimport CircleSvg from \"@/Components/CircleSvg.vue\";\nimport { LinkType, JsonResponse, Role } from \"@/types\";\nimport { PropType, ref } from \"vue\";\nimport { Link } from \"@inertiajs/vue3\";\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport DataTable from \"@/Components/Datatable/Table.vue\";\nimport Checkbox from \"@/Components/Form/Checkbox.vue\";\nimport Modal from \"@/Components/Modal.vue\";\nimport Card from \"@/Components/Card.vue\";\nimport { router } from \"@inertiajs/vue3\";\nimport Pagination from \"@/Components/Pagination.vue\";\nimport Select from \"@/Components/Form/Select.vue\";\nimport Button from \"@/Components/Button.vue\";\n\nexport default {\n    name: \"Roles\",\n    components: {\n        AdminLayout,\n        Breadcrumb,\n        ChevronRightIcon,\n        CircleSvg,\n        Link,\n        DataTable,\n        Checkbox,\n        TrashIcon,\n        PencilIcon,\n        Modal,\n        Card,\n        Pagination,\n        Select,\n        Button\n    },\n    props: {\n        response: {\n            type: Object as PropType<JsonResponse<Role[]>>,\n            required: true,\n        },\n        app_roles: {\n            type: Array,\n        },\n    },\n    setup(props) {\n\n        const selected = ref([]);\n\n        const columns = [\n            {\n                key: \"name\",\n                label: \"Name\",\n            },\n            {\n                key: \"users_count\",\n                label: \"Users\",\n            },\n            {\n                key: \"permissions_count\",\n                label: \"Permissions\",\n            },\n            {\n                key: \"actions\",\n            },\n        ];\n\n        function canModify(name: string): boolean {\n            return !Array.from(props.app_roles).includes(name);\n        }\n\n        function deleteRole(role: Role) {\n            if (confirm(\"Are you sure you want to delete this item?\")) {\n                router.delete(route(\"admin.roles.destroy\", role.id));\n            }\n        }\n\n        return {\n            columns,\n            selected,\n            canModify,\n            deleteRole,\n        };\n    },\n    computed: {\n        breadcrumb(): LinkType[] {\n            return [\n                {\n                    name: \"Roles\",\n                    href: route(\"admin.roles.index\"),\n                    current: route().current(\"admin.roles.index\"),\n                },\n            ];\n        },\n    },\n};\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/subjects/Create.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"create-subject\">\n            <!-- Flash toast -->\n            <transition\n                enter-active-class=\"transition ease-out duration-300\"\n                enter-from-class=\"opacity-0 translate-y-2\"\n                enter-to-class=\"opacity-100 translate-y-0\"\n                leave-active-class=\"transition ease-in duration-200\"\n                leave-from-class=\"opacity-100 translate-y-0\"\n                leave-to-class=\"opacity-0 translate-y-2\"\n            >\n                <div v-if=\"toast.show\" :class=\"[\n                    'fixed bottom-6 right-6 z-50 flex items-start gap-3 px-4 py-3 rounded-xl shadow-xl text-sm font-medium max-w-sm',\n                    toast.type === 'success' ? 'bg-green-600 text-white' : 'bg-red-600 text-white'\n                ]\">\n                    <CheckCircleIcon v-if=\"toast.type === 'success'\" class=\"h-5 w-5 flex-shrink-0 mt-0.5\" />\n                    <ExclamationCircleIcon v-else class=\"h-5 w-5 flex-shrink-0 mt-0.5\" />\n                    <span class=\"flex-1\">{{ toast.message }}</span>\n                    <button type=\"button\" @click=\"toast.show = false\" class=\"ml-1 opacity-75 hover:opacity-100\">\n                        <XMarkIcon class=\"h-4 w-4\" />\n                    </button>\n                </div>\n            </transition>\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1 class=\"text-lg\">Create Subject</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Link :href=\"route('admin.subjects.index')\" class=\"inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-indigo-600 dark:text-gray-400 dark:hover:text-indigo-400 transition-colors\">\n                            <ArrowLeftIcon class=\"h-4 w-4\" />\n                            Back to Subjects\n                        </Link>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <template #header>\n                    <h1 class=\"text-lg\">Create Subject</h1>\n                </template>\n                <form @submit.prevent=\"submit\" enctype=\"multipart/form-data\">\n                    <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n                        <!-- Left: main fields (2/3) -->\n                        <div class=\"lg:col-span-2 space-y-4\">\n                            <Label label=\"Title\" name=\"title\">\n                                <Input v-model=\"form.title\" />\n                                <p v-if=\"form.errors.title\" class=\"text-xs text-red-500 mt-1\">{{ form.errors.title }}</p>\n                            </Label>\n\n                            <!-- Parent subject -->\n                            <div>\n                                <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">Parent Subject <span class=\"text-gray-400 font-normal\">(optional)</span></label>\n                                <select\n                                    v-model=\"form.parent\"\n                                    class=\"relative block w-full focus:outline-none border-0 form-input rounded-md text-md px-3 py-2 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                                >\n                                    <option :value=\"0\">— None (top-level subject) —</option>\n                                    <option v-for=\"p in parentSubjects\" :key=\"p.id\" :value=\"p.id\">{{ p.title }}</option>\n                                </select>\n                            </div>\n\n                            <Label label=\"Description\" name=\"description\">\n                                <textarea\n                                    v-model=\"form.description\"\n                                    name=\"description\"\n                                    rows=\"5\"\n                                    class=\"relative block w-full focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                                />\n                            </Label>\n\n                            <div>\n                                <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">Icon</label>\n                                <HeroiconPicker v-model=\"form.icon\" />\n                                <div v-if=\"form.icon\" class=\"mt-2 flex items-center gap-2 text-xs text-gray-500\">\n                                    <component :is=\"iconComponent\" class=\"h-5 w-5 text-indigo-500\" />\n                                    <span>{{ form.icon.replace('Icon', '') }}</span>\n                                </div>\n                                <p class=\"text-xs text-gray-400 mt-1\">Used on the home page if no image is set.</p>\n                            </div>\n                        </div>\n\n                        <!-- Right: image upload sidebar (1/3) -->\n                        <div class=\"flex flex-col gap-2\">\n                            <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">Cover Image</label>\n                            <div\n                                class=\"flex flex-col items-center justify-center gap-3 rounded-xl border-2 border-dashed border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 p-6 cursor-pointer hover:border-indigo-400 transition-colors flex-1 min-h-[180px]\"\n                                @click=\"imageInput?.click()\"\n                            >\n                                <img v-if=\"imagePreview\" :src=\"imagePreview\" alt=\"Preview\" class=\"w-full rounded-lg object-cover max-h-48\" />\n                                <template v-else>\n                                    <PhotoIcon class=\"h-12 w-12 text-gray-300 dark:text-gray-600\" />\n                                    <div class=\"text-center\">\n                                        <p class=\"text-sm font-medium text-indigo-600 dark:text-indigo-400\">Click to upload</p>\n                                        <p class=\"text-xs text-gray-400 mt-0.5\">PNG, JPG, GIF up to 2MB</p>\n                                    </div>\n                                </template>\n                                <input\n                                    ref=\"imageInput\"\n                                    type=\"file\"\n                                    accept=\"image/*\"\n                                    class=\"hidden\"\n                                    @change=\"onImageChange\"\n                                />\n                            </div>\n                            <p v-if=\"form.errors.image\" class=\"text-xs text-red-500\">{{ form.errors.image }}</p>\n                            <button v-if=\"imagePreview\" type=\"button\" @click=\"clearImage\"\n                                class=\"text-xs text-red-500 hover:underline text-left\">Remove image</button>\n                        </div>\n                    </div>\n\n                    <div class=\"mt-6\">\n                        <Button :disabled=\"form.processing\">\n                            {{ form.processing ? 'Saving…' : 'Create Subject' }}\n                        </Button>\n                    </div>\n                </form>\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ref, computed, watch } from 'vue';\nimport AdminLayout from '@/Layouts/AdminLayout.vue';\nimport Label from '@/Components/Form/Label.vue';\nimport Input from '@/Components/Form/Input.vue';\nimport Card from '@/Components/Card.vue';\nimport Button from '@/Components/Button.vue';\nimport Breadcrumb from '@/Components/Breadcrumb.vue';\nimport HeroiconPicker from '@/Components/Form/HeroiconPicker.vue';\nimport { Link, useForm, usePage } from '@inertiajs/vue3';\nimport { PhotoIcon, CheckCircleIcon, ExclamationCircleIcon, XMarkIcon, ArrowLeftIcon } from '@heroicons/vue/24/outline';\nimport { LinkType } from '@/types';\nimport * as OutlineIcons from '@heroicons/vue/24/outline';\n\nconst page = usePage();\n\n// ── Toast ────────────────────────────────────────────────────\nconst toast = ref<{ show: boolean; type: 'success' | 'error'; message: string }>({\n    show: false, type: 'success', message: '',\n});\nlet toastTimer: ReturnType<typeof setTimeout>;\nwatch(\n    () => (page.props as any).flash,\n    (flash: any) => {\n        if (flash?.success) {\n            toast.value = { show: true, type: 'success', message: flash.success };\n        } else if (flash?.error) {\n            toast.value = { show: true, type: 'error', message: flash.error };\n        } else { return; }\n        clearTimeout(toastTimer);\n        toastTimer = setTimeout(() => { toast.value.show = false; }, 4000);\n    },\n    { deep: true, immediate: true }\n);\n\nconst props = defineProps<{\n    parentSubjects: { id: number; title: string }[];\n}>();\n\nconst imageInput = ref<HTMLInputElement | null>(null);\nconst imagePreview = ref<string | null>(null);\n\nconst form = useForm({\n    title: '',\n    description: '',\n    icon: '',\n    parent: 0 as number,\n    image: null as File | null,\n});\n\nconst allIcons = OutlineIcons as Record<string, any>;\nconst iconComponent = computed(() => form.icon ? allIcons[form.icon] ?? null : null);\n\nfunction onImageChange(e: Event) {\n    const file = (e.target as HTMLInputElement).files?.[0];\n    if (!file) return;\n    form.image = file;\n    imagePreview.value = URL.createObjectURL(file);\n}\n\nfunction clearImage() {\n    form.image = null;\n    imagePreview.value = null;\n    if (imageInput.value) imageInput.value.value = '';\n}\n\nfunction submit() {\n    form.post(route('admin.subjects.store'), {\n        forceFormData: true,\n    });\n}\n\nconst breadcrumb = computed<LinkType[]>(() => [\n    { name: 'Subjects', href: route('admin.subjects.index'), current: false },\n    { name: 'Create', href: route('admin.subjects.create'), current: true },\n]);\n</script>\n\n"
  },
  {
    "path": "resources/js/Pages/admin/subjects/Edit.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"edit-subject\">\n            <!-- Flash toast -->\n            <transition\n                enter-active-class=\"transition ease-out duration-300\"\n                enter-from-class=\"opacity-0 translate-y-2\"\n                enter-to-class=\"opacity-100 translate-y-0\"\n                leave-active-class=\"transition ease-in duration-200\"\n                leave-from-class=\"opacity-100 translate-y-0\"\n                leave-to-class=\"opacity-0 translate-y-2\"\n            >\n                <div v-if=\"toast.show\" :class=\"[\n                    'fixed bottom-6 right-6 z-50 flex items-start gap-3 px-4 py-3 rounded-xl shadow-xl text-sm font-medium max-w-sm',\n                    toast.type === 'success' ? 'bg-green-600 text-white' : 'bg-red-600 text-white'\n                ]\">\n                    <CheckCircleIcon v-if=\"toast.type === 'success'\" class=\"h-5 w-5 flex-shrink-0 mt-0.5\" />\n                    <ExclamationCircleIcon v-else class=\"h-5 w-5 flex-shrink-0 mt-0.5\" />\n                    <span class=\"flex-1\">{{ toast.message }}</span>\n                    <button type=\"button\" @click=\"toast.show = false\" class=\"ml-1 opacity-75 hover:opacity-100\">\n                        <XMarkIcon class=\"h-4 w-4\" />\n                    </button>\n                </div>\n            </transition>\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1 class=\"text-lg\">Edit Subject</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Link :href=\"route('admin.subjects.index')\" class=\"inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-indigo-600 dark:text-gray-400 dark:hover:text-indigo-400 transition-colors\">\n                            <ArrowLeftIcon class=\"h-4 w-4\" />\n                            Back to Subjects\n                        </Link>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <template #header>\n                    <h1>Edit Subject</h1>\n                </template>\n                <form @submit.prevent=\"submit\" enctype=\"multipart/form-data\">\n                    <div class=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n                        <!-- Left: main fields (2/3) -->\n                        <div class=\"lg:col-span-2 space-y-4\">\n                            <Label label=\"Title\" name=\"title\">\n                                <Input v-model=\"form.title\" />\n                                <p v-if=\"form.errors.title\" class=\"text-xs text-red-500 mt-1\">{{ form.errors.title }}</p>\n                            </Label>\n\n                            <!-- Parent subject -->\n                            <div v-if=\"!(form.parent === 0 && (props.subject.children_count ?? 0) > 0)\">\n                                <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">Parent Subject <span class=\"text-gray-400 font-normal\">(optional)</span></label>\n                                <select\n                                    v-model=\"form.parent\"\n                                    class=\"relative block w-full focus:outline-none border-0 form-input rounded-md text-md px-3 py-2 shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                                >\n                                    <option :value=\"0\">— None (top-level subject) —</option>\n                                    <option v-for=\"p in parentSubjects\" :key=\"p.id\" :value=\"p.id\">{{ p.title }}</option>\n                                </select>\n                            </div>\n                            <div v-else class=\"flex items-start gap-2 rounded-lg border border-indigo-200 dark:border-indigo-700 bg-indigo-50 dark:bg-indigo-900/20 px-4 py-3 text-sm text-indigo-700 dark:text-indigo-300\">\n                                <InformationCircleIcon class=\"h-5 w-5 flex-shrink-0 mt-0.5\" />\n                                <span>This is a top-level subject with <strong>{{ props.subject.children_count }}</strong> child subject{{ (props.subject.children_count ?? 0) !== 1 ? 's' : '' }}. Parent assignment is not available.</span>\n                            </div>\n\n                            <Label label=\"Description\" name=\"description\">\n                                <textarea\n                                    v-model=\"form.description\"\n                                    name=\"description\"\n                                    rows=\"5\"\n                                    class=\"relative block w-full focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"\n                                />\n                            </Label>\n\n                            <div>\n                                <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">Icon</label>\n                                <HeroiconPicker v-model=\"form.icon\" />\n                                <div v-if=\"form.icon\" class=\"mt-2 flex items-center gap-2 text-xs text-gray-500\">\n                                    <component :is=\"iconComponent\" class=\"h-5 w-5 text-indigo-500\" />\n                                    <span>{{ form.icon.replace('Icon', '') }}</span>\n                                </div>\n                                <p class=\"text-xs text-gray-400 mt-1\">Used on the home page if no image is set.</p>\n                            </div>\n                        </div>\n\n                        <!-- Right: image upload sidebar (1/3) -->\n                        <div class=\"flex flex-col gap-2\">\n                            <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">Cover Image</label>\n                            <div\n                                class=\"flex flex-col items-center justify-center gap-3 rounded-xl border-2 border-dashed border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800 p-6 cursor-pointer hover:border-indigo-400 transition-colors flex-1 min-h-[180px]\"\n                                @click=\"imageInput?.click()\"\n                            >\n                                <img v-if=\"imagePreview\" :src=\"imagePreview\" alt=\"Preview\" class=\"w-full rounded-lg object-cover max-h-48\" />\n                                <template v-else>\n                                    <PhotoIcon class=\"h-12 w-12 text-gray-300 dark:text-gray-600\" />\n                                    <div class=\"text-center\">\n                                        <p class=\"text-sm font-medium text-indigo-600 dark:text-indigo-400\">Click to upload</p>\n                                        <p class=\"text-xs text-gray-400 mt-0.5\">PNG, JPG, GIF up to 2MB</p>\n                                    </div>\n                                </template>\n                                <input\n                                    ref=\"imageInput\"\n                                    type=\"file\"\n                                    accept=\"image/*\"\n                                    class=\"hidden\"\n                                    @change=\"onImageChange\"\n                                />\n                            </div>\n                            <p v-if=\"form.errors.image\" class=\"text-xs text-red-500\">{{ form.errors.image }}</p>\n                            <button v-if=\"imagePreview\" type=\"button\" @click=\"clearImage\"\n                                class=\"text-xs text-red-500 hover:underline text-left\">Remove image</button>\n                        </div>\n                    </div>\n\n                    <div class=\"mt-6\">\n                        <Button :disabled=\"form.processing\">\n                            {{ form.processing ? 'Saving…' : 'Update Subject' }}\n                        </Button>\n                    </div>\n                </form>\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ref, computed, watch, PropType } from 'vue';\nimport AdminLayout from '@/Layouts/AdminLayout.vue';\nimport Label from '@/Components/Form/Label.vue';\nimport Input from '@/Components/Form/Input.vue';\nimport Card from '@/Components/Card.vue';\nimport Button from '@/Components/Button.vue';\nimport Breadcrumb from '@/Components/Breadcrumb.vue';\nimport HeroiconPicker from '@/Components/Form/HeroiconPicker.vue';\nimport { Subject, LinkType } from '@/types';\nimport { Link, useForm, usePage } from '@inertiajs/vue3';\nimport { PhotoIcon, CheckCircleIcon, ExclamationCircleIcon, XMarkIcon, InformationCircleIcon, ArrowLeftIcon } from '@heroicons/vue/24/outline';\nimport * as OutlineIcons from '@heroicons/vue/24/outline';\n\nconst page = usePage();\n\n// ── Toast ────────────────────────────────────────────────────\nconst toast = ref<{ show: boolean; type: 'success' | 'error'; message: string }>({\n    show: false, type: 'success', message: '',\n});\nlet toastTimer: ReturnType<typeof setTimeout>;\nwatch(\n    () => (page.props as any).flash,\n    (flash: any) => {\n        if (flash?.success) {\n            toast.value = { show: true, type: 'success', message: flash.success };\n        } else if (flash?.error) {\n            toast.value = { show: true, type: 'error', message: flash.error };\n        } else { return; }\n        clearTimeout(toastTimer);\n        toastTimer = setTimeout(() => { toast.value.show = false; }, 4000);\n    },\n    { deep: true, immediate: true }\n);\n\nconst props = defineProps({\n    subject: {\n        type: Object as PropType<Subject>,\n        required: true,\n    },\n    parentSubjects: {\n        type: Array as PropType<{ id: number; title: string }[]>,\n        default: () => [],\n    },\n});\n\nconst imageInput = ref<HTMLInputElement | null>(null);\nconst imagePreview = ref<string | null>(props.subject.image_url ?? null);\n\nconst form = useForm({\n    _method: 'PUT',\n    title: props.subject.title,\n    description: props.subject.description ?? '',\n    icon: props.subject.icon ?? '',\n    parent: props.subject.parent ?? 0,\n    image: null as File | null,\n});\n\nconst allIcons = OutlineIcons as Record<string, any>;\nconst iconComponent = computed(() => form.icon ? allIcons[form.icon] ?? null : null);\n\nfunction onImageChange(e: Event) {\n    const file = (e.target as HTMLInputElement).files?.[0];\n    if (!file) return;\n    form.image = file;\n    imagePreview.value = URL.createObjectURL(file);\n}\n\nfunction clearImage() {\n    form.image = null;\n    imagePreview.value = null;\n    if (imageInput.value) imageInput.value.value = '';\n}\n\nfunction submit() {\n    form.post(route('admin.subjects.update', props.subject.id), {\n        forceFormData: true,\n    });\n}\n\nconst breadcrumb = computed<LinkType[]>(() => [\n    { name: 'Subjects', href: route('admin.subjects.index'), current: false },\n    { name: props.subject.title, href: route('admin.subjects.edit', props.subject.id), current: true },\n]);\n</script>\n\n"
  },
  {
    "path": "resources/js/Pages/admin/subjects/Index.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"subjects\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1 class=\"text-lg\">Subjects</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Button is=\"a\" :href=\"route('admin.subjects.create')\">Create Subject</Button>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <!-- Search bar -->\n                <div class=\"flex items-center gap-2 mb-4\">\n                    <div class=\"flex-1 relative sm:max-w-xs\">\n                        <MagnifyingGlassIcon class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-indigo-400 dark:text-indigo-300 pointer-events-none\" />\n                        <input\n                            type=\"text\"\n                            :value=\"props.filters.search\"\n                            @input=\"onSearch\"\n                            placeholder=\"Search subjects…\"\n                            class=\"w-full pl-8 pr-3 py-1.5 text-xs bg-white dark:bg-gray-800 dark:text-gray-100 border border-indigo-200 dark:border-indigo-700 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 placeholder-gray-400 dark:placeholder-gray-500\"\n                        />\n                    </div>\n                    <button\n                        v-if=\"props.filters.search\"\n                        type=\"button\"\n                        @click=\"clearSearch\"\n                        class=\"inline-flex items-center gap-1 text-xs font-medium text-indigo-600 dark:text-indigo-300 hover:text-white hover:bg-indigo-600 dark:hover:bg-indigo-500 bg-white dark:bg-gray-800 border border-indigo-300 dark:border-indigo-600 rounded-lg px-3 py-1.5 transition-colors shadow-sm\"\n                    >\n                        <XMarkIcon class=\"h-3 w-3\" />\n                        Clear\n                    </button>\n                </div>\n\n                <div class=\"overflow-x-auto\">\n                    <table class=\"w-full text-sm text-left\">\n                        <thead>\n                            <tr class=\"border-b border-gray-200 dark:border-gray-700 text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400\">\n                                <th class=\"py-3 px-4 w-full\">Title</th>\n                                <th class=\"py-3 px-4 whitespace-nowrap\">Courses</th>\n                                <th class=\"py-3 px-4 whitespace-nowrap\">Exams</th>\n                                <th class=\"py-3 px-4\"></th>\n                            </tr>\n                        </thead>\n                        <tbody>\n                            <template v-for=\"subject in response.data\" :key=\"subject.id\">\n                                <!-- ── Parent row ─────────────────────────────── -->\n                                <tr class=\"border-b border-gray-100 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors\">\n                                    <td class=\"py-3 px-4\">\n                                        <div class=\"flex items-center gap-2\">\n                                            <!-- Expand/collapse toggle -->\n                                            <button\n                                                v-if=\"subject.children?.length\"\n                                                type=\"button\"\n                                                @click=\"toggle(subject.id)\"\n                                                class=\"flex-shrink-0 p-0.5 rounded text-gray-400 hover:text-indigo-600 transition-colors\"\n                                            >\n                                                <ChevronDownIcon v-if=\"expanded.has(subject.id)\" class=\"h-4 w-4\" />\n                                                <ChevronRightIcon v-else class=\"h-4 w-4\" />\n                                            </button>\n                                            <!-- Spacer when no children so title aligns -->\n                                            <span v-else class=\"w-5 flex-shrink-0\" />\n\n                                            <!-- Image or heroicon -->\n                                            <img v-if=\"subject.image_url\" :src=\"subject.image_url\" :alt=\"subject.title\"\n                                                class=\"h-9 w-9 rounded-lg object-cover flex-shrink-0 ring-1 ring-gray-200 dark:ring-gray-700\" />\n                                            <span v-else-if=\"subject.icon && allIcons[subject.icon]\"\n                                                class=\"h-9 w-9 flex items-center justify-center rounded-lg bg-indigo-50 dark:bg-indigo-900/30 flex-shrink-0\">\n                                                <component :is=\"allIcons[subject.icon]\" class=\"h-5 w-5 text-indigo-600 dark:text-indigo-400\" />\n                                            </span>\n                                            <span v-else class=\"h-9 w-9 flex items-center justify-center rounded-lg bg-gray-100 dark:bg-gray-800 flex-shrink-0 text-base\">📚</span>\n\n                                            <div>\n                                                <span class=\"font-semibold text-gray-900 dark:text-white\">{{ subject.title }}</span>\n                                                <span v-if=\"subject.children?.length\" class=\"ml-2 text-xs text-gray-400\">{{ subject.children.length }} sub-subjects</span>\n                                            </div>\n                                        </div>\n                                    </td>\n                                    <td class=\"py-3 px-4\">\n                                        <span class=\"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-indigo-50 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300\">\n                                            {{ subject.courses_count ?? 0 }}\n                                        </span>\n                                    </td>\n                                    <td class=\"py-3 px-4\">\n                                        <span class=\"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-amber-50 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300\">\n                                            {{ subject.exams_count ?? 0 }}\n                                        </span>\n                                    </td>\n                                    <td class=\"py-3 px-4\">\n                                        <div class=\"flex items-center justify-end gap-1\">\n                                            <Link :href=\"route('admin.subjects.edit', subject)\" class=\"p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\">\n                                                <PencilIcon class=\"h-5 w-5 text-gray-500 hover:text-indigo-600\" />\n                                            </Link>\n                                            <button type=\"button\" @click=\"deleteSubject(subject)\" class=\"p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\">\n                                                <TrashIcon class=\"h-5 w-5 text-gray-500 hover:text-red-600\" />\n                                            </button>\n                                        </div>\n                                    </td>\n                                </tr>\n\n                                <!-- ── Child rows (collapsible) ───────────────── -->\n                                <template v-if=\"expanded.has(subject.id)\">\n                                    <tr v-for=\"child in subject.children\" :key=\"child.id\"\n                                        class=\"border-b border-gray-100 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-800/20 hover:bg-indigo-50/30 dark:hover:bg-indigo-900/10 transition-colors\">\n                                        <td class=\"py-2.5 px-4\">\n                                            <div class=\"flex items-center gap-2 pl-7\">\n                                                <!-- curved sub-line indicator -->\n                                                <span class=\"text-gray-300 dark:text-gray-600 flex-shrink-0\">&#8627;</span>\n\n                                                <img v-if=\"child.image_url\" :src=\"child.image_url\" :alt=\"child.title\"\n                                                    class=\"h-7 w-7 rounded-md object-cover flex-shrink-0 ring-1 ring-gray-200 dark:ring-gray-700\" />\n                                                <span v-else-if=\"child.icon && allIcons[child.icon]\"\n                                                    class=\"h-7 w-7 flex items-center justify-center rounded-md bg-indigo-50 dark:bg-indigo-900/30 flex-shrink-0\">\n                                                    <component :is=\"allIcons[child.icon]\" class=\"h-4 w-4 text-indigo-500 dark:text-indigo-400\" />\n                                                </span>\n                                                <span v-else class=\"h-7 w-7 flex items-center justify-center rounded-md bg-gray-100 dark:bg-gray-800 flex-shrink-0 text-xs\">📚</span>\n\n                                                <span class=\"text-gray-700 dark:text-gray-300\">{{ child.title }}</span>\n                                            </div>\n                                        </td>\n                                        <td class=\"py-2.5 px-4\">\n                                            <span class=\"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-indigo-50 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300\">\n                                                {{ child.courses_count ?? 0 }}\n                                            </span>\n                                        </td>\n                                        <td class=\"py-2.5 px-4\">\n                                            <span class=\"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-amber-50 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300\">\n                                                {{ child.exams_count ?? 0 }}\n                                            </span>\n                                        </td>\n                                        <td class=\"py-2.5 px-4\">\n                                            <div class=\"flex items-center justify-end gap-1\">\n                                                <Link :href=\"route('admin.subjects.edit', child)\" class=\"p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\">\n                                                    <PencilIcon class=\"h-4 w-4 text-gray-400 hover:text-indigo-600\" />\n                                                </Link>\n                                                <button type=\"button\" @click=\"deleteSubject(child)\" class=\"p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\">\n                                                    <TrashIcon class=\"h-4 w-4 text-gray-400 hover:text-red-600\" />\n                                                </button>\n                                            </div>\n                                        </td>\n                                    </tr>\n                                </template>\n                            </template>\n\n                            <tr v-if=\"!response.data.length\">\n                                <td colspan=\"4\" class=\"py-12 text-center text-sm text-gray-400\">No subjects found.</td>\n                            </tr>\n                        </tbody>\n                    </table>\n                </div>\n                <Pagination :paginate=\"response.meta\" class=\"justify-end mt-4\" />\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ref, computed } from 'vue';\nimport {\n    TrashIcon, PencilIcon, ChevronRightIcon, ChevronDownIcon,\n    MagnifyingGlassIcon, XMarkIcon,\n} from '@heroicons/vue/24/outline';\nimport * as OutlineIcons from '@heroicons/vue/24/outline';\nimport { Link, router } from '@inertiajs/vue3';\nimport AdminLayout from '@/Layouts/AdminLayout.vue';\nimport Breadcrumb from '@/Components/Breadcrumb.vue';\nimport Card from '@/Components/Card.vue';\nimport Pagination from '@/Components/Pagination.vue';\nimport Button from '@/Components/Button.vue';\nimport { LinkType, JsonResponse, Subject } from '@/types';\n\nconst props = defineProps<{\n    response: JsonResponse<Subject[]>;\n    filters: { search?: string };\n}>();\n\nconst allIcons = OutlineIcons as Record<string, any>;\n\n// ── Search / filter ─────────────────────────────────────────\nlet searchTimer: ReturnType<typeof setTimeout>;\nfunction onSearch(e: Event) {\n    clearTimeout(searchTimer);\n    searchTimer = setTimeout(() => {\n        applyFilters({ s: (e.target as HTMLInputElement).value });\n    }, 350);\n}\nfunction clearSearch() {\n    applyFilters({ s: '' });\n}\nfunction applyFilters(params: Record<string, string>) {\n    router.get(route('admin.subjects.index'), params, {\n        preserveState: true,\n        preserveScroll: true,\n        replace: true,\n    });\n}\n\n// ── Expand / collapse ────────────────────────────────────────\nconst expanded = ref<Set<number>>(new Set());\nfunction toggle(id: number) {\n    if (expanded.value.has(id)) {\n        expanded.value.delete(id);\n    } else {\n        expanded.value.add(id);\n    }\n    // trigger reactivity\n    expanded.value = new Set(expanded.value);\n}\n\n// ── Actions ──────────────────────────────────────────────────\nfunction deleteSubject(subject: Subject) {\n    if (confirm('Are you sure you want to delete this subject?')) {\n        router.delete(route('admin.subjects.destroy', subject.id));\n    }\n}\n\n// ── Breadcrumb ───────────────────────────────────────────────\nconst breadcrumb = computed<LinkType[]>(() => [\n    { name: 'Subjects', href: route('admin.subjects.index'), current: route().current('admin.subjects.index') },\n]);\n</script>\n\n"
  },
  {
    "path": "resources/js/Pages/admin/topics/Create.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"edit-topic\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1 class=\"text-lg\">Create Topic</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Link :href=\"route('admin.topics.index')\" class=\"inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-indigo-600 dark:text-gray-400 dark:hover:text-indigo-400 transition-colors\">\n                            <ArrowLeftIcon class=\"h-4 w-4\" />\n                            Back to Topics\n                        </Link>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <template #header>\n                    <h1 class=\"text-lg\">Create Topic</h1>\n                </template>\n                <form @submit.prevent=\"submit\">\n                    <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                        <Label label=\"Title\" name=\"title\">\n                            <Input v-model=\"form.title\" />\n                        </Label>\n                    </div>\n                    <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                        <Label label=\"Description\" name=\"description\">\n                            <textarea v-model=\"form.description\" name=\"description\" cols=\"80\" rows=\"8\" class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"></textarea>\n                        </Label>\n                    </div>\n                    <Button>Create Topic</Button>\n                </form>\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, computed } from \"vue\";\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport Label from \"@/Components/Form/Label.vue\";\nimport Input from \"@/Components/Form/Input.vue\";\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport { LinkType } from \"@/types\";\nimport { Link, useForm } from \"@inertiajs/vue3\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\nimport { ArrowLeftIcon } from \"@heroicons/vue/24/outline\";\n\nexport default defineComponent({\n    components: {\n        AdminLayout,\n        Label,\n        Input,\n        Card,\n        Button,\n        Breadcrumb,\n        Link,\n        ArrowLeftIcon,\n    },\n    props: {},\n    setup(props) {\n        const form = useForm({\n            title: '',\n            description: ''\n        });\n\n        function submit() {\n            form.post(route(\"admin.topics.store\"));\n        }\n\n        const breadcrumb = computed<LinkType[]>(() => [\n            { name: 'Topics', href: route('admin.topics.index'), current: false },\n            { name: 'Create', href: route('admin.topics.create'), current: true },\n        ]);\n\n        return {\n            form,\n            submit,\n            breadcrumb,\n        };\n    },\n});\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/topics/Edit.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"edit-user\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1 class=\"text-lg\">Edit Topic</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Link :href=\"route('admin.topics.index')\" class=\"inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-indigo-600 dark:text-gray-400 dark:hover:text-indigo-400 transition-colors\">\n                            <ArrowLeftIcon class=\"h-4 w-4\" />\n                            Back to Topics\n                        </Link>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <template #header>\n                    <h1>Edit Topic</h1>\n                </template>\n                <form @submit.prevent=\"submit\">\n                    <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                        <Label label=\"Title\" name=\"title\">\n                            <Input v-model=\"form.title\" />\n                        </Label>\n                    </div>\n                    <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                        <Label label=\"Description\" name=\"description\">\n                            <textarea v-model=\"form.description\" name=\"description\" cols=\"80\" rows=\"8\" class=\"relative block w-full disabled:cursor-not-allowed disabled:opacity-75 focus:outline-none border-0 form-input rounded-md placeholder-gray-400 dark:placeholder-gray-500 text-md px-3 py-2 shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-blue-500 dark:ring-blue-400 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400\"></textarea>\n                        </Label>\n                    </div>\n                    <Button>Update Topic</Button>\n                </form>\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType, computed } from \"vue\";\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport Label from \"@/Components/Form/Label.vue\";\nimport Input from \"@/Components/Form/Input.vue\";\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport { Topic, LinkType } from \"@/types\";\nimport { Link, useForm } from \"@inertiajs/vue3\";\nimport Card from \"@/Components/Card.vue\";\nimport Button from \"@/Components/Button.vue\";\nimport { ArrowLeftIcon } from \"@heroicons/vue/24/outline\";\n\nexport default defineComponent({\n    components: {\n        AdminLayout,\n        Label,\n        Input,\n        Card,\n        Button,\n        Breadcrumb,\n        Link,\n        ArrowLeftIcon,\n    },\n    props: {\n        topic: {\n            type: Object as PropType<Topic>,\n            required: true,\n        },\n    },\n    setup(props) {\n        const form = useForm({\n            id: props.topic.id,\n            title: props.topic.title,\n            description: props.topic.description,\n        });\n\n        function submit() {\n            form.put(route(\"admin.topics.update\", props.topic.id));\n        }\n\n        const breadcrumb = computed<LinkType[]>(() => [\n            { name: 'Topics', href: route('admin.topics.index'), current: false },\n            { name: props.topic.title, href: route('admin.topics.edit', props.topic.id), current: true },\n        ]);\n\n        return {\n            form,\n            submit,\n            breadcrumb,\n        };\n    },\n});\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/topics/Index.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"users\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1 class=\"text-lg\">Topics</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Button is=\"a\" :href=\"route('admin.topics.create')\">Create Topic </Button>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <!-- Search bar -->\n                <div class=\"flex items-center gap-2 mb-4\">\n                    <div class=\"flex-1 relative sm:max-w-xs\">\n                        <MagnifyingGlassIcon class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-indigo-400 dark:text-indigo-300 pointer-events-none\" />\n                        <input\n                            type=\"text\"\n                            :value=\"filters.search\"\n                            @input=\"onSearch\"\n                            placeholder=\"Search topics…\"\n                            class=\"w-full pl-8 pr-3 py-1.5 text-xs bg-white dark:bg-gray-800 dark:text-gray-100 border border-indigo-200 dark:border-indigo-700 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 placeholder-gray-400 dark:placeholder-gray-500\"\n                        />\n                    </div>\n                    <button\n                        v-if=\"filters.search\"\n                        type=\"button\"\n                        @click=\"clearSearch\"\n                        class=\"inline-flex items-center gap-1 text-xs font-medium text-indigo-600 dark:text-indigo-300 hover:text-white hover:bg-indigo-600 dark:hover:bg-indigo-500 bg-white dark:bg-gray-800 border border-indigo-300 dark:border-indigo-600 rounded-lg px-3 py-1.5 transition-colors shadow-sm\"\n                    >\n                        <XMarkIcon class=\"h-3 w-3\" />\n                        Clear\n                    </button>\n                </div>\n\n                <!-- Bulk action bar -->\n                <transition\n                    enter-active-class=\"transition ease-out duration-200\"\n                    enter-from-class=\"opacity-0 -translate-y-2\"\n                    enter-to-class=\"opacity-100 translate-y-0\"\n                    leave-active-class=\"transition ease-in duration-150\"\n                    leave-from-class=\"opacity-100 translate-y-0\"\n                    leave-to-class=\"opacity-0 -translate-y-2\"\n                >\n                    <div v-if=\"selected.length\" class=\"flex items-center gap-3 mb-4 px-4 py-2.5 bg-indigo-600 dark:bg-indigo-700 rounded-xl\">\n                        <span class=\"text-xs font-semibold text-white\">\n                            {{ selected.length }} topic{{ selected.length > 1 ? 's' : '' }} selected\n                        </span>\n                        <div class=\"flex items-center gap-2 ml-auto\">\n                            <button\n                                type=\"button\"\n                                @click=\"bulkDelete\"\n                                class=\"inline-flex items-center gap-1.5 text-xs font-semibold text-white bg-red-500 hover:bg-red-600 px-3 py-1.5 rounded-lg transition-colors shadow-sm\"\n                            >\n                                <TrashIcon class=\"h-3.5 w-3.5\" />\n                                Delete\n                            </button>\n                            <button\n                                type=\"button\"\n                                @click=\"selected = []\"\n                                class=\"p-1.5 rounded-lg text-indigo-200 hover:text-white hover:bg-indigo-500 transition-colors\"\n                                title=\"Clear selection\"\n                            >\n                                <XMarkIcon class=\"h-4 w-4\" />\n                            </button>\n                        </div>\n                    </div>\n                </transition>\n\n                <DataTable\n                    v-model=\"selected\"\n                    :rows=\"response.data\"\n                    :columns=\"columns\"\n                >\n                    <template #actions-data=\"{ row }\">\n                        <div class=\"flex justify-end\">\n                            <Link\n                                :href=\"route('admin.topics.edit', row)\"\n                                \n                            >\n                                <PencilIcon class=\"mr-2 h-6 w-6\"></PencilIcon>\n                            </Link>\n                            <Link\n                                @click=\"deleteTopic(row)\"\n                                as=\"button\"\n                                href=\"\"\n                            >\n                                <TrashIcon class=\"mr-2 h-6 w-6 text-red-500\"></TrashIcon>\n                            </Link>\n                        </div>\n                    </template>\n                </DataTable>\n                <Pagination :paginate=\"response.meta\" class=\"justify-end\" />\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\">\nimport {\n    ChevronRightIcon,\n    TrashIcon,\n    PencilIcon,\n    MagnifyingGlassIcon,\n    XMarkIcon,\n} from \"@heroicons/vue/24/outline\";\n\nimport CircleSvg from \"@/Components/CircleSvg.vue\";\nimport { LinkType, JsonResponse, Topic } from \"@/types\";\nimport { PropType, ref } from \"vue\";\nimport { Link, router } from \"@inertiajs/vue3\";\nimport AdminLayout from \"@/Layouts/AdminLayout.vue\";\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport DataTable from \"@/Components/Datatable/Table.vue\";\nimport Checkbox from \"@/Components/Form/Checkbox.vue\";\nimport Modal from \"@/Components/Modal.vue\";\nimport Card from \"@/Components/Card.vue\";\nimport Pagination from \"@/Components/Pagination.vue\";\nimport Select from \"@/Components/Form/Select.vue\";\nimport Button from \"@/Components/Button.vue\";\n\nexport default {\n    name: \"Topics\",\n        components: {\n        AdminLayout,\n        Breadcrumb,\n        ChevronRightIcon,\n        CircleSvg,\n        Link,\n        DataTable,\n        Checkbox,\n        TrashIcon,\n        PencilIcon,\n        MagnifyingGlassIcon,\n        XMarkIcon,\n        Modal,\n        Card,\n        Pagination,\n        Select,\n        Button\n    },\n    props: {\n        response: {\n            type: Object as PropType<JsonResponse<Topic[]>>,\n            required: true,\n        },\n        filters: {\n            type: Object as PropType<{ search?: string }>,\n            default: () => ({}),\n        },\n    },\n    setup(props) {\n\n        const selected = ref([]);\n\n        const columns = [\n            { key: \"title\", label: \"Title\" },\n            { key: \"courses_count\", label: \"Courses\" },\n            { key: \"exams_count\", label: \"Exams\" },\n            { key: \"actions\" },\n        ];\n\n        let searchTimer: ReturnType<typeof setTimeout>;\n        function onSearch(e: Event) {\n            clearTimeout(searchTimer);\n            searchTimer = setTimeout(() => {\n                applyFilters({ s: (e.target as HTMLInputElement).value });\n            }, 350);\n        }\n        function clearSearch() {\n            applyFilters({ s: '' });\n        }\n        function applyFilters(params: Record<string, string>) {\n            router.get(route('admin.topics.index'), params, {\n                preserveState: true,\n                preserveScroll: true,\n                replace: true,\n            });\n        }\n\n        function deleteTopic(topic: Topic) {\n            if (confirm(\"Are you sure you want to delete this item?\")) {\n                router.delete(route(\"admin.topics.destroy\", topic.id));\n            }\n        }\n\n        function bulkDelete() {\n            if (!selected.value.length) return;\n            if (confirm(`Are you sure you want to delete ${selected.value.length} topic(s)?`)) {\n                router.post(route('admin.topics.bulk-delete'), { ids: selected.value.map((t: Topic) => t.id) }, {\n                    onSuccess: () => { selected.value = []; },\n                });\n            }\n        }\n\n        return {\n            columns,\n            selected,\n            deleteTopic,\n            bulkDelete,\n            onSearch,\n            clearSearch,\n        };\n    },\n    computed: {\n        breadcrumb(): LinkType[] {\n            return [\n                {\n                    name: \"Topics\",\n                    href: route(\"admin.topics.index\"),\n                    current: route().current(\"admin.topics.index\"),\n                },\n            ];\n        },\n    },\n};\n</script>\n"
  },
  {
    "path": "resources/js/Pages/admin/users/Create.vue",
    "content": "<template>\n    <div id=\"create-user\">\n        \n    </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n    components: {\n    },\n    props: {\n    },\n    setup() {\n    \n\n    }\n})\n\n</script>"
  },
  {
    "path": "resources/js/Pages/admin/users/Edit.vue",
    "content": "<template>\n    <AdminLayout>\n        <div id=\"edit-user\">\n            <Card class=\"mb-5\">\n                <div class=\"flex justify-between items-center\">\n                    <div>\n                        <h1 class=\"text-lg\">Edit User</h1>\n                        <Breadcrumb :items=\"breadcrumb\" />\n                    </div>\n                    <div>\n                        <Link :href=\"route('admin.users.index')\" class=\"inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-indigo-600 dark:text-gray-400 dark:hover:text-indigo-400 transition-colors\">\n                            <ArrowLeftIcon class=\"h-4 w-4\" />\n                            Back to Users\n                        </Link>\n                    </div>\n                </div>\n            </Card>\n\n            <Card>\n                <template #header>\n                    <h3>Edit User</h3>\n                </template>\n                <form @submit.prevent=\"submit\">\n                    <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-2\">\n                        <Label label=\"First Name\" name=\"firstname\">\n                            <Input v-model=\"userForm.firstname\" />\n                        </Label>\n                        <Label label=\"Last name\" name=\"lastname\">\n                            <Input v-model=\"userForm.lastname\" />\n                        </Label>\n                        <Label label=\"Username\" name=\"name\">\n                            <Input v-model=\"userForm.name\" />\n                        </Label>\n                        <Label label=\"Email\" name=\"email\">\n                            <Input type=\"email\" v-model=\"userForm.email\" />\n                        </Label>\n                    </div>\n                    <Button>Update User</Button>\n                </form>\n            </Card>\n        </div>\n    </AdminLayout>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, PropType, computed } from 'vue'\nimport AdminLayout from '@/Layouts/AdminLayout.vue';\nimport Label from '@/Components/Form/Label.vue'\nimport Input from '@/Components/Form/Input.vue'\nimport Breadcrumb from '@/Components/Breadcrumb.vue'\nimport { User, LinkType } from '@/types'\nimport { Link, router, useForm } from '@inertiajs/vue3'\nimport Card from '@/Components/Card.vue'\nimport Button from '@/Components/Button.vue'\nimport { ArrowLeftIcon } from '@heroicons/vue/24/outline'\n\n\nexport default defineComponent({\n    components: {\n            AdminLayout,\n            Label,\n            Input,\n            Card,\n            Button,\n            Breadcrumb,\n            Link,\n            ArrowLeftIcon,\n        },\n    props: {\n        user: {\n            type: Object as PropType<User>,\n            required: true\n        },\n    },\n    setup(props) {\n        const userForm = useForm({\n            id: props.user.id,\n            firstname: props.user.firstname,\n            lastname: props.user.lastname,\n            name: props.user.name,\n            email: props.user.email\n        })\n\n        function submit() {\n            userForm.put(route('admin.users.update', props.user.id))\n        }\n\n        const breadcrumb = computed<LinkType[]>(() => [\n            { name: 'Users', href: route('admin.users.index'), current: false },\n            { name: `${props.user.firstname} ${props.user.lastname}`.trim() || props.user.name, href: route('admin.users.edit', props.user.id), current: true },\n        ]);\n\n        return {\n            userForm,\n            submit,\n            breadcrumb,\n        }\n    }\n})\n\n</script>"
  },
  {
    "path": "resources/js/Pages/admin/users/Index.vue",
    "content": "<template>\n  <AdminLayout>\n    <div id=\"users\">\n      <Card class=\"mb-5\">\n        <h1 class=\"text-lg font-semibold\">Users</h1>\n        <Breadcrumb :items=\"breadcrumb\" />\n      </Card>\n\n      <Card>\n        <!-- Filter bar -->\n        <div class=\"w-full flex flex-col sm:flex-row gap-2 mb-6\">\n          <!-- Search -->\n          <div class=\"flex-1 relative sm:w-44\">\n            <MagnifyingGlassIcon class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-indigo-400 dark:text-indigo-300 pointer-events-none\" />\n            <input\n              type=\"text\"\n              :value=\"filters.search\"\n              @input=\"onSearch\"\n              placeholder=\"Search by name or email…\"\n              class=\"w-full pl-8 pr-3 py-1.5 text-xs bg-white dark:bg-gray-800 dark:text-gray-100 border border-indigo-200 dark:border-indigo-700 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 placeholder-gray-400 dark:placeholder-gray-500\"\n            />\n          </div>\n\n          <!-- Role filter -->\n          <div class=\"w-full sm:w-44\">\n            <select\n              :value=\"filters.role\"\n              @change=\"onRoleChange\"\n              class=\"w-full text-xs bg-white dark:bg-gray-800 dark:text-gray-100 border border-indigo-200 dark:border-indigo-700 rounded-lg px-2.5 py-1.5 shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500\"\n            >\n              <option value=\"\">All Roles</option>\n              <option v-for=\"role in roles\" :key=\"role.id\" :value=\"role.name\">\n                {{ role.name }}\n              </option>\n            </select>\n          </div>\n\n          <!-- Clear filters -->\n          <button\n            v-if=\"filters.search || filters.role\"\n            type=\"button\"\n            @click=\"clearFilters\"\n            class=\"flex-shrink-0 inline-flex items-center gap-1 text-xs font-medium text-indigo-600 dark:text-indigo-300 hover:text-white hover:bg-indigo-600 dark:hover:bg-indigo-500 bg-white dark:bg-gray-800 border border-indigo-300 dark:border-indigo-600 rounded-lg px-3 py-1.5 transition-colors shadow-sm\"\n          >\n            <XMarkIcon class=\"h-3 w-3\" />\n            Clear\n          </button>\n        </div>\n\n        <!-- Bulk action bar (visible when rows are selected) -->\n        <transition\n          enter-active-class=\"transition ease-out duration-200\"\n          enter-from-class=\"opacity-0 -translate-y-2\"\n          enter-to-class=\"opacity-100 translate-y-0\"\n          leave-active-class=\"transition ease-in duration-150\"\n          leave-from-class=\"opacity-100 translate-y-0\"\n          leave-to-class=\"opacity-0 -translate-y-2\"\n        >\n          <div v-if=\"selected.length\" class=\"flex items-center gap-3 mb-4 px-4 py-2.5 bg-indigo-600 dark:bg-indigo-700 rounded-xl\">\n            <span class=\"text-xs font-semibold text-white\">\n              {{ selected.length }} user{{ selected.length > 1 ? 's' : '' }} selected\n            </span>\n            <div class=\"flex items-center gap-2 ml-auto\">\n              <!-- Bulk sync roles -->\n              <button\n                type=\"button\"\n                @click=\"openBulkRoleModal\"\n                class=\"inline-flex items-center gap-1.5 text-xs font-semibold text-indigo-700 bg-white hover:bg-indigo-50 px-3 py-1.5 rounded-lg transition-colors shadow-sm\"\n              >\n                <UserGroupIcon class=\"h-3.5 w-3.5\" />\n                Sync Roles\n              </button>\n              <!-- Bulk delete -->\n              <button\n                type=\"button\"\n                @click=\"bulkDeleteUsers\"\n                class=\"inline-flex items-center gap-1.5 text-xs font-semibold text-white bg-red-500 hover:bg-red-600 px-3 py-1.5 rounded-lg transition-colors shadow-sm\"\n              >\n                <TrashIcon class=\"h-3.5 w-3.5\" />\n                Delete\n              </button>\n              <!-- Clear selection -->\n              <button\n                type=\"button\"\n                @click=\"selected = []\"\n                class=\"p-1.5 rounded-lg text-indigo-200 hover:text-white hover:bg-indigo-500 transition-colors\"\n                title=\"Clear selection\"\n              >\n                <XMarkIcon class=\"h-4 w-4\" />\n              </button>\n            </div>\n          </div>\n        </transition>\n\n        <DataTable v-model=\"selected\" :rows=\"response.data\" :columns=\"columns\">\n          <template #name-data=\"{ row }\">\n            <div class=\"flex items-center gap-3\">\n              <img\n                class=\"h-10 w-10 rounded-xl object-cover object-center flex-shrink-0 ring-2 ring-indigo-100\"\n                alt=\"Avatar\"\n                :src=\"row.avatar?.avatar ?? row.avatar\"\n              />\n              <div>\n                <div class=\"font-semibold text-indigo-700 hover:text-indigo-900 transition-colors\">{{ row.full_name }}</div>\n                <div class=\"text-xs text-gray-400 mt-0.5\">{{ row.email }}</div>\n              </div>\n            </div>\n          </template>\n\n          <!-- Role column with assign icon -->\n          <template #roles.0.name-data=\"{ row }\">\n            <div class=\"flex items-center gap-2\">\n              <span\n                v-if=\"row.roles && row.roles.length\"\n                class=\"inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-indigo-100 dark:bg-indigo-900 text-indigo-700 dark:text-indigo-300\"\n              >\n                {{ row.roles[0].name }}\n                <span v-if=\"row.roles.length > 1\" class=\"text-indigo-400\">+{{ row.roles.length - 1 }}</span>\n              </span>\n              <span v-else class=\"text-xs text-gray-400 italic\">No role</span>\n\n              <button\n                type=\"button\"\n                title=\"Manage roles\"\n                @click=\"openRoleModal(row)\"\n                class=\"flex-shrink-0 p-0.5 rounded text-indigo-400 hover:text-indigo-600 hover:bg-indigo-50 dark:hover:bg-indigo-900 transition-colors\"\n              >\n                <UserGroupIcon class=\"h-4 w-4\" />\n              </button>\n            </div>\n          </template>\n\n          <template #actions-data=\"{ row }\">\n            <div class=\"flex\">\n              <Link :href=\"route('admin.users.edit', row)\">\n                <PencilIcon class=\"mr-2 h-5 w-5 text-gray-500 hover:text-indigo-600 transition-colors\" />\n              </Link>\n              <Link @click=\"deleteUser(row)\" as=\"button\" href=\"\">\n                <TrashIcon class=\"mr-2 h-5 w-5 text-gray-500 hover:text-red-600 transition-colors\" />\n              </Link>\n            </div>\n          </template>\n        </DataTable>\n\n        <Pagination :paginate=\"response.meta\" class=\"justify-end mt-4\" />\n      </Card>\n    </div>\n\n    <!-- Role assignment modal -->\n    <teleport to=\"body\">\n      <transition\n        enter-active-class=\"transition ease-out duration-200\"\n        enter-from-class=\"opacity-0\"\n        enter-to-class=\"opacity-100\"\n        leave-active-class=\"transition ease-in duration-150\"\n        leave-from-class=\"opacity-100\"\n        leave-to-class=\"opacity-0\"\n      >\n        <div v-if=\"roleModal.open\" class=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n          <!-- Backdrop -->\n          <div class=\"absolute inset-0 bg-black/50 dark:bg-black/70\" @click=\"closeRoleModal\" />\n\n          <!-- Panel -->\n          <div class=\"relative w-full max-w-sm bg-white dark:bg-gray-900 rounded-2xl shadow-2xl ring-1 ring-gray-200 dark:ring-gray-700 overflow-hidden\">\n            <!-- Header -->\n            <div class=\"flex items-center justify-between px-5 py-4 border-b border-gray-100 dark:border-gray-800\">\n              <div>\n                <h3 class=\"text-base font-semibold text-gray-900 dark:text-white\">\n                  {{ roleModal.isBulk ? 'Bulk Sync Roles' : 'Manage Roles' }}\n                </h3>\n                <p class=\"text-xs text-gray-500 dark:text-gray-400 mt-0.5\">\n                  <template v-if=\"roleModal.isBulk\">\n                    Applying to {{ selected.length }} selected user{{ selected.length > 1 ? 's' : '' }}\n                  </template>\n                  <template v-else>{{ roleModal.user?.full_name }}</template>\n                </p>\n              </div>\n              <button type=\"button\" @click=\"closeRoleModal\"\n                class=\"p-1.5 rounded-lg text-gray-400 hover:text-gray-600 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors\">\n                <XMarkIcon class=\"h-5 w-5\" />\n              </button>\n            </div>\n\n            <!-- Role list -->\n            <div class=\"px-5 py-4 space-y-2\">\n              <label\n                v-for=\"role in roles\"\n                :key=\"role.id\"\n                class=\"flex items-center gap-3 p-3 rounded-xl border cursor-pointer transition-colors\"\n                :class=\"selectedRoleIds.includes(role.id)\n                  ? 'border-indigo-400 bg-indigo-50 dark:bg-indigo-900/40 dark:border-indigo-600'\n                  : 'border-gray-200 dark:border-gray-700 hover:border-indigo-200 dark:hover:border-indigo-700 hover:bg-gray-50 dark:hover:bg-gray-800'\"\n              >\n                <input\n                  type=\"checkbox\"\n                  :value=\"role.id\"\n                  v-model=\"selectedRoleIds\"\n                  class=\"rounded border-gray-300 dark:border-gray-600 text-indigo-600 focus:ring-indigo-500 dark:bg-gray-700\"\n                />\n                <span class=\"text-sm font-medium text-gray-800 dark:text-gray-200 capitalize\">{{ role.name }}</span>\n                <span\n                  v-if=\"selectedRoleIds.includes(role.id)\"\n                  class=\"ml-auto text-xs text-indigo-600 dark:text-indigo-400 font-medium\"\n                >Active</span>\n              </label>\n            </div>\n\n            <!-- Footer -->\n            <div class=\"flex items-center justify-end gap-2 px-5 py-4 border-t border-gray-100 dark:border-gray-800 bg-gray-50 dark:bg-gray-800/50\">\n              <button type=\"button\" @click=\"closeRoleModal\"\n                class=\"text-sm font-medium text-gray-600 dark:text-gray-400 px-4 py-2 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors\">\n                Cancel\n              </button>\n              <button type=\"button\" @click=\"saveRoles\" :disabled=\"savingRoles\"\n                class=\"inline-flex items-center gap-1.5 text-sm font-semibold text-white bg-indigo-600 hover:bg-indigo-700 disabled:opacity-60 px-4 py-2 rounded-lg transition-colors shadow-sm\">\n                <ArrowPathIcon v-if=\"savingRoles\" class=\"h-4 w-4 animate-spin\" />\n                {{ roleModal.isBulk ? 'Apply to All' : 'Save Roles' }}\n              </button>\n            </div>\n          </div>\n        </div>\n      </transition>\n    </teleport>\n  </AdminLayout>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed } from 'vue';\nimport {\n  MagnifyingGlassIcon, TrashIcon, PencilIcon, XMarkIcon,\n  UserGroupIcon, ArrowPathIcon,\n} from '@heroicons/vue/24/outline';\nimport { LinkType, JsonResponse, User, Role } from \"@/types\";\nimport { Link, router, useForm } from \"@inertiajs/vue3\";\nimport AdminLayout from '@/Layouts/AdminLayout.vue';\nimport Breadcrumb from \"@/Components/Breadcrumb.vue\";\nimport DataTable from \"@/Components/Datatable/Table.vue\";\nimport Card from '@/Components/Card.vue';\nimport Pagination from '@/Components/Pagination.vue';\n\nconst props = defineProps<{\n  response: JsonResponse<User[]>;\n  roles: Role[];\n  filters: { search?: string; role?: string };\n}>();\n\nconst selected = ref([]);\n\nconst columns = [\n  { key: 'name',              label: 'Name' },\n  { key: 'roles.0.name',     label: 'Role' },\n  { key: 'email_verified_at', label: 'Verified' },\n  { key: 'actions' },\n];\n\nconst breadcrumb = computed<LinkType[]>(() => [\n  { name: 'Users', href: route('admin.users.index'), current: route().current('admin.users.index') },\n]);\n\n// ── Filters ─────────────────────────────────────────────────\nlet searchTimer: ReturnType<typeof setTimeout>;\nfunction onSearch(e: Event) {\n  clearTimeout(searchTimer);\n  searchTimer = setTimeout(() => {\n    applyFilters({ search: (e.target as HTMLInputElement).value, role: props.filters.role ?? '' });\n  }, 350);\n}\nfunction onRoleChange(e: Event) {\n  applyFilters({ search: props.filters.search ?? '', role: (e.target as HTMLSelectElement).value });\n}\nfunction clearFilters() {\n  applyFilters({ search: '', role: '' });\n}\nfunction applyFilters(params: Record<string, string>) {\n  router.get(route('admin.users.index'), params, {\n    preserveState: true,\n    preserveScroll: true,\n    replace: true,\n  });\n}\n\n// ── Delete ───────────────────────────────────────────────────\nfunction deleteUser(user: User) {\n  if (confirm('Are you sure you want to delete this user?')) {\n    router.delete(route('admin.users.destroy', user.id));\n  }\n}\n\n// ── Role modal (single + bulk) ───────────────────────────────\nconst roleModal = ref<{ open: boolean; isBulk: boolean; user: User | null }>({\n  open: false, isBulk: false, user: null,\n});\nconst selectedRoleIds = ref<number[]>([]);\nconst savingRoles = ref(false);\n\nfunction openRoleModal(user: User) {\n  roleModal.value = { open: true, isBulk: false, user };\n  selectedRoleIds.value = (user.roles ?? []).map((r: any) => r.id as number);\n}\nfunction openBulkRoleModal() {\n  roleModal.value = { open: true, isBulk: true, user: null };\n  selectedRoleIds.value = [];\n}\nfunction closeRoleModal() {\n  roleModal.value = { open: false, isBulk: false, user: null };\n}\nfunction saveRoles() {\n  savingRoles.value = true;\n  if (roleModal.value.isBulk) {\n    router.post(\n      route('admin.users.bulk-sync-roles'),\n      { ids: selected.value.map((u: any) => u.id), roles: selectedRoleIds.value },\n      {\n        preserveScroll: true,\n        onSuccess: () => { closeRoleModal(); selected.value = []; },\n        onFinish: () => { savingRoles.value = false; },\n      }\n    );\n  } else {\n    const user = roleModal.value.user;\n    if (!user) return;\n    router.put(\n      route('admin.users.sync-roles', user.id),\n      { roles: selectedRoleIds.value },\n      {\n        preserveScroll: true,\n        onSuccess: () => { closeRoleModal(); },\n        onFinish: () => { savingRoles.value = false; },\n      }\n    );\n  }\n}\n\n// ── Bulk delete ───────────────────────────────────────────────\nfunction bulkDeleteUsers() {\n  if (!confirm(`Delete ${selected.value.length} selected user(s)? This cannot be undone.`)) return;\n  router.post(\n    route('admin.users.bulk-delete'),\n    { ids: selected.value.map((u: any) => u.id) },\n    {\n      preserveScroll: true,\n      onSuccess: () => { selected.value = []; },\n    }\n  );\n}\n</script>\n"
  },
  {
    "path": "resources/js/app.ts",
    "content": "import './bootstrap';\nimport '../css/app.css';\n\nimport { createApp, h, DefineComponent } from 'vue';\nimport { createInertiaApp } from '@inertiajs/vue3';\nimport { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';\nimport { ZiggyVue } from '../../vendor/tightenco/ziggy';\n\nconst appName = import.meta.env.VITE_APP_NAME || 'Laravel';\n\ncreateInertiaApp({\n    title: (title) => `${title} - ${appName}`,\n    resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob<DefineComponent>('./Pages/**/*.vue')),\n    setup({ el, App, props, plugin }) {\n        createApp({ render: () => h(App, props) })\n            .use(plugin)\n            .use(ZiggyVue)\n            .mount(el);\n    },\n    progress: {\n        color: '#4B5563',\n    },\n});\n"
  },
  {
    "path": "resources/js/bootstrap.ts",
    "content": "import axios from 'axios';\nwindow.axios = axios;\n\nwindow.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\n"
  },
  {
    "path": "resources/js/types/forms.d.ts",
    "content": "import type { Ref } from 'vue'\n\nexport interface FormError<T extends string = string> {\n  path: T\n  message: string\n}\n\nexport interface FormErrorWithId extends FormError {\n  id: string\n}\n\nexport interface Form<T> {\n  validate(path?: string | string[], opts?: { silent?: true }): Promise<T | false>;\n  validate(path?: string | string[], opts?: { silent?: false }): Promise<T>;\n  clear(path?: string): void\n  errors: Ref<FormError[]>\n  setErrors(errs: FormError[], path?: string): void\n  getErrors(path?: string): FormError[]\n  submit(): Promise<void>\n}\n\nexport type FormSubmitEvent<T> = SubmitEvent & { data: T }\nexport type FormErrorEvent = SubmitEvent & { errors: FormErrorWithId[] }\n\nexport type FormEventType = 'blur' | 'input' | 'change' | 'submit'\n\nexport interface FormEvent {\n  type: FormEventType\n  path?: string\n}\n\nexport interface InjectedFormGroupValue {\n  inputId: Ref<string | undefined>\n  name: Ref<string>\n  size: Ref<string | number | symbol>\n  error: Ref<string | boolean | undefined>\n  eagerValidation: Ref<boolean>\n}\n\nexport type Sizes = '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';\nexport type InputColor = 'white' | 'gray' | 'red';\nexport type InputVariant = 'outline' | 'none';"
  },
  {
    "path": "resources/js/types/global.d.ts",
    "content": "import { PageProps as InertiaPageProps } from '@inertiajs/core';\nimport { AxiosInstance } from 'axios';\nimport { route as ziggyRoute } from 'ziggy-js';\nimport { PageProps as AppPageProps } from './';\n\ndeclare global {\n    interface Window {\n        axios: AxiosInstance;\n    }\n\n    var route: typeof ziggyRoute;\n}\n\ndeclare module 'vue' {\n    interface ComponentCustomProperties {\n        route: typeof ziggyRoute;\n    }\n}\n\ndeclare module '@inertiajs/core' {\n    interface PageProps extends InertiaPageProps, AppPageProps {}\n}\n"
  },
  {
    "path": "resources/js/types/icons.d.ts",
    "content": "import * as solid from \"@heroicons/vue/24/solid\";\nexport type CustomIconName = \"LoadingIcon\";\n\nexport type HeroIconName = keyof typeof solid\n\nexport type IconName = HeroIconName | CustomIconName;"
  },
  {
    "path": "resources/js/types/index.d.ts",
    "content": "\nexport * from './resources';\nexport * from './forms';\nexport * from './icons';\n\nexport type Strategy = 'merge' | 'override'\n\nexport type PageProps<T extends Record<string, unknown> = Record<string, unknown>> = T & {\n    auth: {\n        user: User;\n    };\n};\n"
  },
  {
    "path": "resources/js/types/resources.d.ts",
    "content": "export interface User {\n    id: number;\n    name: string;\n    firstname?: string;\n    lastname?: string;\n    full_name?: string;\n    avatar?: string;\n    email: string;\n    email_verified_at: string;\n    created_at?: string;\n    updated_at?: string;\n    deleted_at?: string;\n    roles?: Role[];\n    results?: Result[];\n    instructCourses?: Course[];\n    enrolledCourses?: Course[];\n}\n\nexport interface Student {\n    id: number;\n    name: string;\n    full_name?: string;\n    avatar?: string;\n    rating: number;\n    progress: number;\n}\n\nexport interface Role {\n    id: number;\n    name: string;\n    guard_name: string;\n    permissions: Array\n}\n\nexport interface Topic {\n    id: number;\n    title: string;\n    description: string;\n    created_at?: string;\n    updated_at?: string;\n    courses?: Course[];\n    exams?: Exam[];\n    courses_count?: number;\n    exams_count?: number;\n}\nexport interface Section {\n    id: number;\n    title: string;\n    description: string;\n    created_at?: string;\n    updated_at?: string;\n    exams?: Exam[];\n    lessons?: Lesson[];\n    resources: Exam[] | Lesson[]\n}\nexport interface Result {\n    id: number;\n    answers: string;\n    obtain_mark: number;\n    is_pass: boolean;\n    time_taken: string;\n    created_at?: string;\n    updated_at?: string;\n    examinee?: User;\n    exam?: any;\n}\nexport interface QuestionOption {\n    option: string;\n    id?: string;\n    answer?: boolean;\n}\nexport interface Question {\n    id: number;\n    qtype: string;\n    question?: string;\n    options?: QuestionOption[];\n    answers?: Array;\n    hint?: string;\n    explanation?: string;\n    mark?: number;\n    nmark?: number;\n    created_at?: string;\n    updated_at?: string;\n    topics?: Topic[];\n    exam?: any;\n}\n\nexport interface Lesson {\n    id: number;\n    title: string;\n    slug: string;\n    thumbnail?: string;\n    type?: string;\n    object?: string;\n    short_text?: string;\n    full_text?: string;\n    position?: string;\n    status?: string;\n    created_at?: string;\n    updated_at?: string;\n    courses?: Course[];\n    students?: User[];\n    examSessions?: any;\n}\nexport interface File {\n    id: number;\n    name: string;\n    path?: string;\n    description?: string;\n    file_name?: string;\n    extension?: string;\n    mime?: string;\n    type?: string;\n    public_path?: string;\n    parent_id?: string;\n    uploaded_by?: any;\n    created_at?: string;\n    updated_at?: string;\n}\nexport interface Subject {\n    id: number;\n    title: string;\n    slug: string;\n    description?: string;\n    icon?: string;\n    image?: string;\n    image_url?: string;\n    parent?: number;\n    created_at?: string;\n    updated_at?: string;\n    courses?: Course[];\n    exams?: Exam[];\n    courses_count?: number;\n    exams_count?: number;\n    children?: Subject[];\n    children_count?: number;\n}\n\nexport interface Exam {\n    id: number;\n    title: string;\n    description?: string;\n    status?: number;\n    price?: number;\n    duration?: number;\n    pass_mark?: number;\n    number_of_questions?: number;\n    random_questions?: boolean;\n    certification?: boolean;\n    difficulty?: string;\n    permalink?: string;\n    meta?: any;\n    subjects?: Subject[];\n    courses?: Course[];\n    questions?: Question[];\n    examiner?: User;\n    topics: Topic[];\n    results?: Result[];\n}\n\nexport interface Course {\n    id: number;\n    title: string;\n    subtitle: string;\n    slug: string;\n    description?: string;\n    requirements?: string;\n    status?: number;\n    thumbnail?: string;\n    start_date?: string;\n    features?: string;\n    rating?: number;\n    certified?: boolean;\n    created_at?: string;\n    updated_at?: string;\n    price: number;\n    discount: number;\n    permalink: string;\n    teachers?: User[];\n    students?: User[];\n    sections?: Section[];\n    lessons?: Lesson[];\n    exams?: Exam[];\n    topics?: Topic[];\n    subjects?: Subject[];\n    lessons_count?: number;\n    students_count?: number;\n    sections_count?: number;\n    exams_count?: number;\n}\n\nexport interface LinkType {\n    name: string;\n    href: string;\n    current: boolean;\n    icon?: string;\n}\n\nexport interface JsonResponse<T> {\n    data: T;\n    links: {\n        fast: string;\n        last: string;\n        prev?: string;\n        next?: string;\n    },\n    meta: LaravelPagination\n}\n\n\nexport interface  PaginationLink {\n    url: string; \n    label: string; \n    active: boolean\n}\n\nexport interface LaravelPagination {\n    current_page: number;\n    from: number;\n    last_page: number;\n    links?: PaginationLink[];\n    path: string;\n    per_page: number;\n    to: number,\n    total?: number\n}"
  },
  {
    "path": "resources/js/types/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "resources/js/types/vuex.d.ts",
    "content": "declare module \"vuex\" {\n    export * from \"vuex/types/index.d.ts\";\n    export * from \"vuex/types/helpers.d.ts\";\n    export * from \"vuex/types/logger.d.ts\";\n    export * from \"vuex/types/vue.d.ts\";\n}"
  },
  {
    "path": "resources/js/ui.config/buttonGroup.ts",
    "content": "export default {\n    wrapper: {\n      horizontal: 'inline-flex -space-x-px',\n      vertical: 'inline-flex flex-col -space-y-px'\n    },\n    rounded: 'rounded-md',\n    shadow: 'shadow-sm',\n    orientation: {\n      'rounded-none': { horizontal: { start: 'rounded-s-none', end: 'rounded-e-none' }, vertical: { start: 'rounded-t-none', end: 'rounded-b-none' } },\n      'rounded-sm': { horizontal: { start: 'rounded-s-sm', end: 'rounded-e-sm' }, vertical: { start: 'rounded-t-sm', end: 'rounded-b-sm' } },\n      rounded: { horizontal: { start: 'rounded-s', end: 'rounded-e' }, vertical: { start: 'rounded-t', end: 'rounded-b' } },\n      'rounded-md': { horizontal: { start: 'rounded-s-md', end: 'rounded-e-md' }, vertical: { start: 'rounded-t-md', end: 'rounded-b-md' } },\n      'rounded-lg': { horizontal: { start: 'rounded-s-lg', end: 'rounded-e-lg' }, vertical: { start: 'rounded-t-lg', end: 'rounded-b-lg' } },\n      'rounded-xl': { horizontal: { start: 'rounded-s-xl', end: 'rounded-e-xl' }, vertical: { start: 'rounded-t-xl', end: 'rounded-b-xl' } },\n      'rounded-2xl': { horizontal: { start: 'rounded-s-2xl', end: 'rounded-e-2xl' }, vertical: { start: 'rounded-t-2xl', end: 'rounded-b-2xl' } },\n      'rounded-3xl': { horizontal: { start: 'rounded-s-3xl', end: 'rounded-e-3xl' }, vertical: { start: 'rounded-t-3xl', end: 'rounded-b-3xl' } },\n      'rounded-full': { horizontal: { start: 'rounded-s-full', end: 'rounded-e-full' }, vertical: { start: 'rounded-t-full', end: 'rounded-b-full' } }\n    }\n  }"
  },
  {
    "path": "resources/js/ui.config/index.ts",
    "content": "export { default as buttonGroup } from './buttonGroup'"
  },
  {
    "path": "resources/views/app.blade.php",
    "content": "<!DOCTYPE html>\n<html lang=\"{{ str_replace('_', '-', app()->getLocale()) }}\" class=\"h-full bg-gray-100\">\n    <head>\n        <meta charset=\"utf-8\">\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n        <title inertia>{{ config('app.name', 'Laravel') }}</title>\n\n        <!-- Fonts -->\n        <link rel=\"preconnect\" href=\"https://fonts.bunny.net\">\n        <link href=\"https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap\" rel=\"stylesheet\" />\n\n        <!-- Scripts -->\n        @routes\n        @vite(['resources/js/app.ts', \"resources/js/Pages/{$page['component']}.vue\"])\n        @inertiaHead\n    </head>\n    <body class=\"font-sans h-full antialiased\">\n        @inertia\n    </body>\n</html>\n"
  },
  {
    "path": "resources/views/errors/401.blade.php",
    "content": "@extends('errors::minimal')\n\n@section('title', __('Unauthorized'))\n@section('code', '401')\n@section('message', __('Unauthorized'))\n"
  },
  {
    "path": "resources/views/errors/403.blade.php",
    "content": "@extends('errors::minimal')\n\n@section('title', __('Forbidden'))\n@section('code', '403')\n@section('message', __($exception->getMessage() ?: 'Forbidden'))\n"
  },
  {
    "path": "resources/views/errors/500.blade.php",
    "content": "@extends('errors::minimal')\n\n@section('title', __('Server Error'))\n@section('code', '500')\n@section('message', __('Server Error'))\n"
  },
  {
    "path": "resources/views/errors/503.blade.php",
    "content": "{{-- @extends('errors::minimal')\n@section('title', __('Service Unavailable'))\n@section('code', '503')\n@section('message', __('Service Unavailable'))\n--}}\n<!DOCTYPE html>\n<html lang=\"{{ str_replace('_', '-', app()->getLocale()) }}\">\n    <head>\n        @if($ga_enabled)\n            <!-- Google tag (gtag.js) -->\n            <script async src=\"https://www.googletagmanager.com/gtag/js?id={{$ga_key}}\"></script>\n            <script>\n              window.dataLayer = window.dataLayer || [];\n              function gtag(){dataLayer.push(arguments);}\n              gtag('js', new Date());\n              gtag('config', '{{ $ga_key }}');\n            </script>\n        @endif\n        <meta charset=\"UTF-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n        <meta name=\"csrf-token\" content=\"{{ csrf_token() }}\">\n        <title>{{ config('app.name') }}</title>\n        @vite(['resources/css/app.css'])\n    </head>\n    <body class=\"bg-slate-800 h-screen antialiased leading-none font-sans overflow-x-hidden overflow-y-auto\">\n        <section class=\"mt-6\">\n            <div class=\"py-8 px-4 mx-auto max-w-screen-md text-center lg:py-16 lg:px-12\">\n                <svg class=\"mx-auto mb-4 w-10 h-10 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path fill=\"currentColor\" d=\"M331.8 224.1c28.29 0 54.88 10.99 74.86 30.97l19.59 19.59c40.01-17.74 71.25-53.3 81.62-96.65c5.725-23.92 5.34-47.08 .2148-68.4c-2.613-10.88-16.43-14.51-24.34-6.604l-68.9 68.9h-75.6V97.2l68.9-68.9c7.912-7.912 4.275-21.73-6.604-24.34c-21.32-5.125-44.48-5.51-68.4 .2148c-55.3 13.23-98.39 60.22-107.2 116.4C224.5 128.9 224.2 137 224.3 145l82.78 82.86C315.2 225.1 323.5 224.1 331.8 224.1zM384 278.6c-23.16-23.16-57.57-27.57-85.39-13.9L191.1 158L191.1 95.99l-127.1-95.99L0 63.1l96 127.1l62.04 .0077l106.7 106.6c-13.67 27.82-9.251 62.23 13.91 85.39l117 117.1c14.62 14.5 38.21 14.5 52.71-.0016l52.75-52.75c14.5-14.5 14.5-38.08-.0016-52.71L384 278.6zM227.9 307L168.7 247.9l-148.9 148.9c-26.37 26.37-26.37 69.08 0 95.45C32.96 505.4 50.21 512 67.5 512s34.54-6.592 47.72-19.78l119.1-119.1C225.5 352.3 222.6 329.4 227.9 307zM64 472c-13.25 0-24-10.75-24-24c0-13.26 10.75-24 24-24S88 434.7 88 448C88 461.3 77.25 472 64 472z\"/></svg>\n                <h1 class=\"mb-4 text-4xl font-bold tracking-tight leading-none text-whitelg:mb-6 md:text-5xl xl:text-6xl dark:text-white\">Under Maintenance</h1>\n                <p class=\"font-light text-gray-500 md:text-lg xl:text-xl dark:text-gray-400\">Our Enterprise administrators are performing scheduled maintenance.</p>\n            </div>\n        </section>\n        <script> const GA_ENABLED=\"{{ $ga_enabled }}\"</script>\n        <script> const GA_TAG=\"{{ $ga_key }}\"</script>\n    </body>\n</html>\n"
  },
  {
    "path": "resources/views/errors/layout.blade.php",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n  <title>@yield('title')</title>\n\n  <!-- Fonts -->\n  <link href=\"https://fonts.googleapis.com/css?family=Raleway:100,600\" rel=\"stylesheet\" type=\"text/css\">\n\n  <!-- Styles -->\n  <style>\n  html, body {\n    background-color: #fff;\n    color: #636b6f;\n    font-family: 'Raleway', sans-serif;\n    font-weight: 100;\n    height: 100vh;\n    margin: 0;\n  }\n\n  .full-height {\n    height: 100vh;\n  }\n\n  .flex-center {\n    align-items: center;\n    display: flex;\n    justify-content: center;\n  }\n\n  .position-ref {\n    position: relative;\n  }\n\n  .content {\n    text-align: center;\n  }\n\n  .title {\n    font-size: 36px;\n    padding: 20px;\n  }\n</style>\n</head>\n<body>\n  <div class=\"flex-center position-ref full-height\">\n    <div class=\"content\">\n      <div class=\"title\">\n        @yield('message')\n      </div>\n    </div>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "resources/views/socialite/callback.blade.php",
    "content": "<!DOCTYPE html>\n<html lang=\"{{ str_replace('_', '-', app()->getLocale()) }}\">\n    <head>\n        <meta charset=\"UTF-8\" />\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n        <meta name=\"csrf-token\" content=\"{{ csrf_token() }}\">\n        <title>{{ config('app.name') }}</title>\n        <script>\n            window.opener.postMessage({ token: \"{{ $token }}\" }, \"{{ url('/') }}\")\n            window.close()\n        </script>\n    </head>\n    <body>\n    </body>\n</html>\n"
  },
  {
    "path": "resources/views/socialite/denied.blade.php",
    "content": "@extends('errors.layout')\n\n@section('title', 'Login Error')\n\n@section('message', 'You did not share your profile data with '.config('app.name').'.')\n"
  },
  {
    "path": "routes/api.php",
    "content": "<?php\n\nuse Illuminate\\Support\\Facades\\Route;\nuse App\\Http\\Controllers\\API\\ExamController;\nuse App\\Http\\Controllers\\API\\FileController;\nuse App\\Http\\Controllers\\API\\CourseController;\nuse App\\Http\\Controllers\\API\\LessonController;\nuse App\\Http\\Controllers\\API\\SessionController;\nuse App\\Http\\Controllers\\API\\SubjectController;\nuse App\\Http\\Controllers\\API\\MyCourseController;\nuse App\\Http\\Controllers\\API\\QuestionController;\nuse App\\Http\\Controllers\\API\\TakeExamController;\nuse App\\Http\\Controllers\\API\\SessionableController;\n\n/*\n|--------------------------------------------------------------------------\n| API Routes\n|--------------------------------------------------------------------------\n|\n| Here is where you can register API routes for your application. These\n| routes are loaded by the RouteServiceProvider within a group which\n| is assigned the \"api\" middleware group. Enjoy building your API!\n|\n*/\n\nRoute::group(['middleware' => ['auth:sanctum']], function () {\n    Route::get('courses/my-courses', [MyCourseController::class, 'index']);\n    Route::get('courses/my-courses/{course:slug}', [MyCourseController::class, 'show']);\n\n    \n    Route::apiResource('course', CourseController::class);\n\n    Route::put('sessions/{session}/attach-exam', [SessionController::class,'attachExam']);\n    Route::put('sessions/{session}/attach-lession', [SessionController::class, 'attacLession']);\n\n    Route::get('take-exam/{exam}', [TakeExamController::class, 'show']);\n    Route::post('start-exam/{exam}', [TakeExamController::class, 'start']);\n    Route::post('complete-exam/{exam}', [TakeExamController::class, 'complete']);\n    Route::post('answer/{exam}', [TakeExamController::class, 'answer']);\n\n    Route::apiResource('/files', FileController::class);\n});\n\n\nRoute::get('courses/{course}/sessions', [SessionableController::class, 'lessons']);"
  },
  {
    "path": "routes/auth.php",
    "content": "<?php\n\nuse App\\Http\\Controllers\\Auth\\AuthenticatedSessionController;\nuse App\\Http\\Controllers\\Auth\\ConfirmablePasswordController;\nuse App\\Http\\Controllers\\Auth\\EmailVerificationNotificationController;\nuse App\\Http\\Controllers\\Auth\\EmailVerificationPromptController;\nuse App\\Http\\Controllers\\Auth\\NewPasswordController;\nuse App\\Http\\Controllers\\Auth\\PasswordController;\nuse App\\Http\\Controllers\\Auth\\PasswordResetLinkController;\nuse App\\Http\\Controllers\\Auth\\RegisteredUserController;\nuse App\\Http\\Controllers\\Auth\\VerifyEmailController;\nuse Illuminate\\Support\\Facades\\Route;\n\nRoute::middleware('guest')->group(function () {\n    Route::get('register', [RegisteredUserController::class, 'create'])\n                ->name('register');\n\n    Route::post('register', [RegisteredUserController::class, 'store']);\n\n    Route::get('login', [AuthenticatedSessionController::class, 'create'])\n                ->name('login');\n\n    Route::post('login', [AuthenticatedSessionController::class, 'store']);\n\n    Route::get('forgot-password', [PasswordResetLinkController::class, 'create'])\n                ->name('password.request');\n\n    Route::post('forgot-password', [PasswordResetLinkController::class, 'store'])\n                ->name('password.email');\n\n    Route::get('reset-password/{token}', [NewPasswordController::class, 'create'])\n                ->name('password.reset');\n\n    Route::post('reset-password', [NewPasswordController::class, 'store'])\n                ->name('password.store');\n});\n\nRoute::middleware('auth')->group(function () {\n    Route::get('verify-email', EmailVerificationPromptController::class)\n                ->name('verification.notice');\n\n    Route::get('verify-email/{id}/{hash}', VerifyEmailController::class)\n                ->middleware(['signed', 'throttle:6,1'])\n                ->name('verification.verify');\n\n    Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store'])\n                ->middleware('throttle:6,1')\n                ->name('verification.send');\n\n    Route::get('confirm-password', [ConfirmablePasswordController::class, 'show'])\n                ->name('password.confirm');\n\n    Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']);\n\n    Route::put('password', [PasswordController::class, 'update'])->name('password.update');\n\n    Route::post('logout', [AuthenticatedSessionController::class, 'destroy'])\n                ->name('logout');\n});\n"
  },
  {
    "path": "routes/console.php",
    "content": "<?php\n\nuse Illuminate\\Foundation\\Inspiring;\nuse Illuminate\\Support\\Facades\\Artisan;\n\nArtisan::command('inspire', function () {\n    $this->comment(Inspiring::quote());\n})->purpose('Display an inspiring quote')->hourly();\n"
  },
  {
    "path": "routes/web.php",
    "content": "<?php\n\nuse Inertia\\Inertia;\nuse Illuminate\\Support\\Facades\\Route;\nuse App\\Http\\Controllers\\HomeController;\nuse App\\Http\\Controllers\\CourseController;\nuse App\\Http\\Controllers\\UploadController;\nuse App\\Http\\Controllers\\ProfileController;\nuse App\\Http\\Controllers\\DownloadController;\nuse App\\Http\\Controllers\\LearningController;\nuse App\\Http\\Controllers\\Admin\\ExamController;\nuse App\\Http\\Controllers\\InstructorController;\nuse App\\Http\\Controllers\\Admin\\RolesController;\nuse App\\Http\\Controllers\\Admin\\UsersController;\nuse App\\Http\\Controllers\\Admin\\LessonController;\nuse App\\Http\\Controllers\\Admin\\TopicsController;\nuse App\\Http\\Controllers\\Admin\\CoursesController;\nuse App\\Http\\Controllers\\Admin\\SectionController;\nuse App\\Http\\Controllers\\Admin\\SubjectController;\nuse App\\Http\\Controllers\\Admin\\QuestionController;\nuse App\\Http\\Controllers\\Auth\\SocialiteController;\nuse App\\Http\\Controllers\\Admin\\DashboardController;\nuse App\\Http\\Controllers\\Admin\\ServerInfoController;\nuse App\\Http\\Controllers\\Admin\\CourseStudentController;\n\n\nRoute::get('/', HomeController::class)->name('home');\nRoute::get('/courses/{course:slug}', [CourseController::class, 'show'])->name('course.show');\nRoute::get(\"/instructor/{user:name}/course\", [InstructorController::class, 'courses'])->name(\"instructor.courses\");\n\nRoute::post('/oauth/{driver}', [SocialiteController::class, 'getSocialRedirect'])->name('oauth');\nRoute::get('/oauth/{driver}/callback', [SocialiteController::class, 'handleSocialCallback'])->name('oauth.callback');\n\nRoute::group(['middleware' => ['auth']], function(){\n    Route::get(\"/learning/my-courses\", [LearningController::class,  'myCourses' ])->name(\"learning.courses\");\n    Route::get(\"/learning/{course:slug}\", [LearningController::class,  'startCourse' ])->name(\"start.course\");\n    Route::get(\"/learning/{course:slug}/{type}/{slog}\", [LearningController::class,  'singleResource' ])->name(\"start.resource\");\n    Route::post('/download', [DownloadController::class, 'download']);\n    Route::get('/uploads/{id}/{any?}', UploadController::class)->where('any', '.*');\n    Route::post(\"/subscribe/{course}\", [CourseController::class, 'subscribe'])->name('course.subscribe');\n});\n\nRoute::middleware(['auth', 'verified'])->prefix('/dashboard')->name('admin.')->group(function () {\n    Route::get('/', DashboardController::class)->name('dashboard');\n    Route::resource('users', UsersController::class);\n    Route::put('users/{user}/sync-roles', [UsersController::class, 'syncRoles'])->name('users.sync-roles');\n    Route::post('users/bulk-delete', [UsersController::class, 'bulkDelete'])->name('users.bulk-delete');\n    Route::post('users/bulk-sync-roles', [UsersController::class, 'bulkSyncRoles'])->name('users.bulk-sync-roles');\n    Route::resource('roles', RolesController::class);\n    Route::get('courses/{course}/students', CourseStudentController::class)->name('course-student');\n    Route::apiResource('courses/{course:id}/sections', SectionController::class)->except(['show', 'edit']);\n    Route::resource('courses', CoursesController::class);\n    Route::apiResource('courses/{course:id}/lessons', LessonController::class);\n    Route::resource('topics', TopicsController::class)->except(['show']);\n    Route::post('topics/bulk-delete', [TopicsController::class, 'bulkDelete'])->name('topics.bulk-delete');\n    Route::resource('subjects', SubjectController::class)->except(['show']);\n    Route::resource('exams', ExamController::class)->except(['show']);\n    Route::resource('exams/{exam:id}/questions', QuestionController::class)->except(['show']);\n    Route::get('/server-info', [ServerInfoController::class, 'index'])->name('server-info');\n    Route::post('/oauth-revoke/{provider}', [SocialiteController::class, 'revokeSocialProvider']);\n});\n\n\nRoute::middleware('auth')->group(function () {\n    Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');\n    Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');\n    Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');\n});\n\nrequire __DIR__.'/auth.php';\n\n"
  },
  {
    "path": "storage/app/.gitignore",
    "content": "*\n!public/\n!.gitignore\n"
  },
  {
    "path": "storage/framework/.gitignore",
    "content": "compiled.php\nconfig.php\ndown\nevents.scanned.php\nmaintenance.php\nroutes.php\nroutes.scanned.php\nschedule-*\nservices.json\n"
  },
  {
    "path": "storage/framework/cache/.gitignore",
    "content": "*\n!data/\n!.gitignore\n"
  },
  {
    "path": "storage/framework/sessions/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/framework/testing/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/framework/views/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "tailwind.config.js",
    "content": "import defaultTheme from 'tailwindcss/defaultTheme';\nimport forms from '@tailwindcss/forms';\nimport headlessui from '@headlessui/tailwindcss';\n\n/** @type {import('tailwindcss').Config} */\nexport default {\n    darkMode: 'selector',\n    content: [\n        './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',\n        './storage/framework/views/*.php',\n        './resources/views/**/*.blade.php',\n        './resources/js/**/*.vue',\n    ],\n\n    theme: {\n        extend: {\n            fontFamily: {\n                sans: ['Figtree', ...defaultTheme.fontFamily.sans],\n            },\n        },\n    },\n    variants: {\n        extend: {\n            display: [\"group-hover\"],\n        },\n    },\n\n    plugins: [\n        forms,\n        headlessui\n    ],\n};\n"
  },
  {
    "path": "tests/Feature/Auth/AuthenticationTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature\\Auth;\n\nuse App\\Models\\User;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Tests\\TestCase;\n\nclass AuthenticationTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_login_screen_can_be_rendered(): void\n    {\n        $response = $this->get('/login');\n\n        $response->assertStatus(200);\n    }\n\n    public function test_users_can_authenticate_using_the_login_screen(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this->post('/login', [\n            'email' => $user->email,\n            'password' => 'password',\n        ]);\n\n        $this->assertAuthenticated();\n        $response->assertRedirect(route('admin.dashboard', absolute: false));\n    }\n\n    public function test_users_can_not_authenticate_with_invalid_password(): void\n    {\n        $user = User::factory()->create();\n\n        $this->post('/login', [\n            'email' => $user->email,\n            'password' => 'wrong-password',\n        ]);\n\n        $this->assertGuest();\n    }\n\n    public function test_users_can_logout(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this->actingAs($user)->post('/logout');\n\n        $this->assertGuest();\n        $response->assertRedirect('/');\n    }\n}\n"
  },
  {
    "path": "tests/Feature/Auth/EmailVerificationTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature\\Auth;\n\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Events\\Verified;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Support\\Facades\\URL;\nuse Tests\\TestCase;\n\nclass EmailVerificationTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_email_verification_screen_can_be_rendered(): void\n    {\n        $user = User::factory()->unverified()->create();\n\n        $response = $this->actingAs($user)->get('/verify-email');\n\n        $response->assertStatus(200);\n    }\n\n    public function test_email_can_be_verified(): void\n    {\n        $user = User::factory()->unverified()->create();\n\n        Event::fake();\n\n        $verificationUrl = URL::temporarySignedRoute(\n            'verification.verify',\n            now()->addMinutes(60),\n            ['id' => $user->id, 'hash' => sha1($user->email)]\n        );\n\n        $response = $this->actingAs($user)->get($verificationUrl);\n\n        Event::assertDispatched(Verified::class);\n        $this->assertTrue($user->fresh()->hasVerifiedEmail());\n        $response->assertRedirect(route('admin.dashboard', absolute: false).'?verified=1');\n    }\n\n    public function test_email_is_not_verified_with_invalid_hash(): void\n    {\n        $user = User::factory()->unverified()->create();\n\n        $verificationUrl = URL::temporarySignedRoute(\n            'verification.verify',\n            now()->addMinutes(60),\n            ['id' => $user->id, 'hash' => sha1('wrong-email')]\n        );\n\n        $this->actingAs($user)->get($verificationUrl);\n\n        $this->assertFalse($user->fresh()->hasVerifiedEmail());\n    }\n}\n"
  },
  {
    "path": "tests/Feature/Auth/PasswordConfirmationTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature\\Auth;\n\nuse App\\Models\\User;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Tests\\TestCase;\n\nclass PasswordConfirmationTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_confirm_password_screen_can_be_rendered(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this->actingAs($user)->get('/confirm-password');\n\n        $response->assertStatus(200);\n    }\n\n    public function test_password_can_be_confirmed(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this->actingAs($user)->post('/confirm-password', [\n            'password' => 'password',\n        ]);\n\n        $response->assertRedirect();\n        $response->assertSessionHasNoErrors();\n    }\n\n    public function test_password_is_not_confirmed_with_invalid_password(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this->actingAs($user)->post('/confirm-password', [\n            'password' => 'wrong-password',\n        ]);\n\n        $response->assertSessionHasErrors();\n    }\n}\n"
  },
  {
    "path": "tests/Feature/Auth/PasswordResetTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature\\Auth;\n\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Notifications\\ResetPassword;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Illuminate\\Support\\Facades\\Notification;\nuse Tests\\TestCase;\n\nclass PasswordResetTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_reset_password_link_screen_can_be_rendered(): void\n    {\n        $response = $this->get('/forgot-password');\n\n        $response->assertStatus(200);\n    }\n\n    public function test_reset_password_link_can_be_requested(): void\n    {\n        Notification::fake();\n\n        $user = User::factory()->create();\n\n        $this->post('/forgot-password', ['email' => $user->email]);\n\n        Notification::assertSentTo($user, ResetPassword::class);\n    }\n\n    public function test_reset_password_screen_can_be_rendered(): void\n    {\n        Notification::fake();\n\n        $user = User::factory()->create();\n\n        $this->post('/forgot-password', ['email' => $user->email]);\n\n        Notification::assertSentTo($user, ResetPassword::class, function ($notification) {\n            $response = $this->get('/reset-password/'.$notification->token);\n\n            $response->assertStatus(200);\n\n            return true;\n        });\n    }\n\n    public function test_password_can_be_reset_with_valid_token(): void\n    {\n        Notification::fake();\n\n        $user = User::factory()->create();\n\n        $this->post('/forgot-password', ['email' => $user->email]);\n\n        Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {\n            $response = $this->post('/reset-password', [\n                'token' => $notification->token,\n                'email' => $user->email,\n                'password' => 'password',\n                'password_confirmation' => 'password',\n            ]);\n\n            $response\n                ->assertSessionHasNoErrors()\n                ->assertRedirect(route('login'));\n\n            return true;\n        });\n    }\n}\n"
  },
  {
    "path": "tests/Feature/Auth/PasswordUpdateTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature\\Auth;\n\nuse App\\Models\\User;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Illuminate\\Support\\Facades\\Hash;\nuse Tests\\TestCase;\n\nclass PasswordUpdateTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_password_can_be_updated(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this\n            ->actingAs($user)\n            ->from('/profile')\n            ->put('/password', [\n                'current_password' => 'password',\n                'password' => 'new-password',\n                'password_confirmation' => 'new-password',\n            ]);\n\n        $response\n            ->assertSessionHasNoErrors()\n            ->assertRedirect('/profile');\n\n        $this->assertTrue(Hash::check('new-password', $user->refresh()->password));\n    }\n\n    public function test_correct_password_must_be_provided_to_update_password(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this\n            ->actingAs($user)\n            ->from('/profile')\n            ->put('/password', [\n                'current_password' => 'wrong-password',\n                'password' => 'new-password',\n                'password_confirmation' => 'new-password',\n            ]);\n\n        $response\n            ->assertSessionHasErrors('current_password')\n            ->assertRedirect('/profile');\n    }\n}\n"
  },
  {
    "path": "tests/Feature/Auth/RegistrationTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature\\Auth;\n\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Tests\\TestCase;\n\nclass RegistrationTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_registration_screen_can_be_rendered(): void\n    {\n        $response = $this->get('/register');\n\n        $response->assertStatus(200);\n    }\n\n    public function test_new_users_can_register(): void\n    {\n        $response = $this->post('/register', [\n            'name' => 'Test User',\n            'email' => 'test@example.com',\n            'password' => 'password',\n            'password_confirmation' => 'password',\n        ]);\n\n        $this->assertAuthenticated();\n        $response->assertRedirect(route('admin.dashboard', absolute: false));\n    }\n}\n"
  },
  {
    "path": "tests/Feature/ExampleTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature;\n\n// use Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Tests\\TestCase;\n\nclass ExampleTest extends TestCase\n{\n    /**\n     * A basic test example.\n     */\n    public function test_the_application_returns_a_successful_response(): void\n    {\n        $response = $this->get('/');\n\n        $response->assertStatus(200);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/Http/Controllers/Admin/UsersControllerTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature\\Http\\Controllers\\Admin;\n\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Illuminate\\Foundation\\Testing\\WithFaker;\nuse Tests\\TestCase;\n\nclass UsersControllerTest extends TestCase\n{\n    /**\n     * A basic feature test example.\n     */\n    public function test_example(): void\n    {\n        $response = $this->get('/');\n\n        $response->assertStatus(200);\n    }\n}\n"
  },
  {
    "path": "tests/Feature/ProfileTest.php",
    "content": "<?php\n\nnamespace Tests\\Feature;\n\nuse App\\Models\\User;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Tests\\TestCase;\n\nclass ProfileTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_profile_page_is_displayed(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this\n            ->actingAs($user)\n            ->get('/profile');\n\n        $response->assertOk();\n    }\n\n    public function test_profile_information_can_be_updated(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this\n            ->actingAs($user)\n            ->patch('/profile', [\n                'name' => 'Test User',\n                'email' => 'test@example.com',\n            ]);\n\n        $response\n            ->assertSessionHasNoErrors()\n            ->assertRedirect('/profile');\n\n        $user->refresh();\n\n        $this->assertSame('Test User', $user->name);\n        $this->assertSame('test@example.com', $user->email);\n        $this->assertNull($user->email_verified_at);\n    }\n\n    public function test_email_verification_status_is_unchanged_when_the_email_address_is_unchanged(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this\n            ->actingAs($user)\n            ->patch('/profile', [\n                'name' => 'Test User',\n                'email' => $user->email,\n            ]);\n\n        $response\n            ->assertSessionHasNoErrors()\n            ->assertRedirect('/profile');\n\n        $this->assertNotNull($user->refresh()->email_verified_at);\n    }\n\n    public function test_user_can_delete_their_account(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this\n            ->actingAs($user)\n            ->delete('/profile', [\n                'password' => 'password',\n            ]);\n\n        $response\n            ->assertSessionHasNoErrors()\n            ->assertRedirect('/');\n\n        $this->assertGuest();\n        $this->assertNull(User::withoutTrashed()->where('id', $user->id)->first());\n    }\n\n    public function test_correct_password_must_be_provided_to_delete_account(): void\n    {\n        $user = User::factory()->create();\n\n        $response = $this\n            ->actingAs($user)\n            ->from('/profile')\n            ->delete('/profile', [\n                'password' => 'wrong-password',\n            ]);\n\n        $response\n            ->assertSessionHasErrors('password')\n            ->assertRedirect('/profile');\n\n        $this->assertNotNull($user->fresh());\n    }\n}\n"
  },
  {
    "path": "tests/TestCase.php",
    "content": "<?php\n\nnamespace Tests;\n\nuse Illuminate\\Foundation\\Testing\\TestCase as BaseTestCase;\n\nabstract class TestCase extends BaseTestCase\n{\n    //\n}\n"
  },
  {
    "path": "tests/Unit/ExampleTest.php",
    "content": "<?php\n\nnamespace Tests\\Unit;\n\nuse PHPUnit\\Framework\\TestCase;\n\nclass ExampleTest extends TestCase\n{\n    /**\n     * A basic test example.\n     */\n    public function test_that_true_is_true(): void\n    {\n        $this->assertTrue(true);\n    }\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"noImplicitAny\": false,\n        \"strictNullChecks\": false,\n        \"allowJs\": true,\n        \"module\": \"ESNext\",\n        \"moduleResolution\": \"bundler\",\n        \"jsx\": \"preserve\",\n        \"strict\": true,\n        \"isolatedModules\": true,\n        \"target\": \"ESNext\",\n        \"esModuleInterop\": true,\n        \"forceConsistentCasingInFileNames\": true,\n        \"noEmit\": true,\n        \"skipLibCheck\": true,\n        \"paths\": {\n            \"@/*\": [\"./resources/js/*\"],\n            \"ziggy-js\": [\"./vendor/tightenco/ziggy\"]\n        }\n    },\n    \"include\": [\"resources/js/**/*.ts\", \"resources/js/**/*.d.ts\", \"resources/js/**/*.vue\"]\n}\n"
  },
  {
    "path": "vite.config.js",
    "content": "import { defineConfig } from 'vite';\nimport laravel from 'laravel-vite-plugin';\nimport vue from '@vitejs/plugin-vue';\nimport path from 'path';\n\nexport default defineConfig({\n    plugins: [\n        laravel({\n            input: 'resources/js/app.ts',\n            refresh: true,\n        }),\n        vue({\n            template: {\n                transformAssetUrls: {\n                    base: null,\n                    includeAbsolute: false,\n                },\n            },\n        }),\n    ],\n    resolve: {\n        alias: {\n          '~': path.resolve(__dirname, 'node_modules'),\n          '@': path.resolve(__dirname, 'resources/js'),\n          '@css': path.resolve(__dirname, 'resources/css'),\n          '@img': path.resolve(__dirname, 'resources/img'),\n          '@views': path.resolve(__dirname, 'resources/js/views'),\n          '@pages': path.resolve(__dirname, 'resources/js/views/pages'),\n          '@store': path.resolve(__dirname, 'resources/js/store'),\n          '@Services': path.resolve(__dirname, 'resources/js/Services'),\n          '@router': path.resolve(__dirname, 'resources/js/router'),\n          '@Components': path.resolve(__dirname, 'resources/js/Components'),\n        },\n    }\n});\n"
  }
]