Add group creation and show current groups
This commit is contained in:
@@ -23,7 +23,7 @@ LOG_LEVEL=debug
|
|||||||
DB_CONNECTION=pgsql
|
DB_CONNECTION=pgsql
|
||||||
DB_HOST=127.0.0.1
|
DB_HOST=127.0.0.1
|
||||||
DB_PORT=5432
|
DB_PORT=5432
|
||||||
DB_DATABASE=sendit
|
DB_DATABASE=patchbook
|
||||||
DB_USERNAME=root
|
DB_USERNAME=root
|
||||||
DB_PASSWORD=
|
DB_PASSWORD=
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,75 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class Crew extends Model
|
class Crew extends Model
|
||||||
{
|
{
|
||||||
//
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'description',
|
||||||
|
'slug',
|
||||||
|
'image_id',
|
||||||
|
'cover_image_id',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function users(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function patches(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(CrewPatch::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function booted(): void
|
||||||
|
{
|
||||||
|
static::creating(function (Crew $crew) {
|
||||||
|
if (!$crew->slug) {
|
||||||
|
$crew->slug = self::generateUniqueSlug($crew->name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function generateUniqueSlug(?string $name): string
|
||||||
|
{
|
||||||
|
$base = Str::slug((string) $name);
|
||||||
|
|
||||||
|
if ($base === '') {
|
||||||
|
$base = self::randomAdventureSlugBase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::makeUniqueSlug($base);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function makeUniqueSlug(string $base): string
|
||||||
|
{
|
||||||
|
$slug = $base;
|
||||||
|
$i = 2;
|
||||||
|
|
||||||
|
while (self::where('slug', $slug)->exists()) {
|
||||||
|
$slug = $base . '-' . $i;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function randomAdventureSlugBase(): string
|
||||||
|
{
|
||||||
|
$adjectives = [
|
||||||
|
'brave', 'wild', 'stormy', 'golden', 'muddy', 'curious', 'sunny', 'frosty',
|
||||||
|
'rusty', 'proud', 'swift', 'steady', 'quiet', 'rowdy', 'tiny', 'giant',
|
||||||
|
];
|
||||||
|
|
||||||
|
$nouns = [
|
||||||
|
'otter', 'badger', 'fox', 'raven', 'wolf', 'bear', 'eagle', 'turtle',
|
||||||
|
'trail', 'camp', 'summit', 'river', 'forest', 'torch', 'map', 'compass',
|
||||||
|
];
|
||||||
|
|
||||||
|
return $adjectives[array_rand($adjectives)] . '-' . $nouns[array_rand($nouns)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class CrewMember extends Model
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
14
app/Models/CrewUser.php
Normal file
14
app/Models/CrewUser.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class CrewUser extends Model
|
||||||
|
{
|
||||||
|
public function crew(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Crew::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,12 +50,7 @@ class User extends Authenticatable
|
|||||||
|
|
||||||
public function crews(): BelongsToMany
|
public function crews(): BelongsToMany
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(
|
return $this->belongsToMany(Crew::class)->withTimestamps();
|
||||||
Crew::class,
|
|
||||||
'crew_members',
|
|
||||||
'user_id',
|
|
||||||
'crew_id'
|
|
||||||
)->withTimestamps();
|
|
||||||
}
|
}
|
||||||
public function settings(): HasMany
|
public function settings(): HasMany
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"workos/workos-php": "^4.29"
|
"workos/workos-php": "^4.29"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"barryvdh/laravel-debugbar": "^4.0",
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
"laravel/pail": "^1.2.2",
|
"laravel/pail": "^1.2.2",
|
||||||
"laravel/pint": "^1.24",
|
"laravel/pint": "^1.24",
|
||||||
|
|||||||
271
composer.lock
generated
271
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "e8ac2a3d2d0647f711ada077e6de914d",
|
"content-hash": "5d572cfde76b1527ac7869e725a2c838",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bacon/bacon-qr-code",
|
"name": "bacon/bacon-qr-code",
|
||||||
@@ -6905,6 +6905,105 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "barryvdh/laravel-debugbar",
|
||||||
|
"version": "v4.0.10",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/fruitcake/laravel-debugbar.git",
|
||||||
|
"reference": "96afd5efc93c2cb3140df356893381296259695b"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/96afd5efc93c2cb3140df356893381296259695b",
|
||||||
|
"reference": "96afd5efc93c2cb3140df356893381296259695b",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/routing": "^11|^12|^13.0",
|
||||||
|
"illuminate/session": "^11|^12|^13.0",
|
||||||
|
"illuminate/support": "^11|^12|^13.0",
|
||||||
|
"php": "^8.2",
|
||||||
|
"php-debugbar/php-debugbar": "^3.3.1",
|
||||||
|
"php-debugbar/symfony-bridge": "^1.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"larastan/larastan": "^3",
|
||||||
|
"laravel/octane": "^2",
|
||||||
|
"laravel/pennant": "^1",
|
||||||
|
"laravel/pint": "^1",
|
||||||
|
"laravel/telescope": "^5.16",
|
||||||
|
"livewire/livewire": "^3.7|^4",
|
||||||
|
"mockery/mockery": "^1.3.3",
|
||||||
|
"orchestra/testbench-dusk": "^9|^10",
|
||||||
|
"php-debugbar/twig-bridge": "^2.0",
|
||||||
|
"phpstan/phpstan-phpunit": "^2",
|
||||||
|
"phpstan/phpstan-strict-rules": "^2.0",
|
||||||
|
"phpunit/phpunit": "^11",
|
||||||
|
"shipmonk/phpstan-rules": "^4.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"aliases": {
|
||||||
|
"Debugbar": "Fruitcake\\LaravelDebugbar\\Facades\\Debugbar"
|
||||||
|
},
|
||||||
|
"providers": [
|
||||||
|
"Fruitcake\\LaravelDebugbar\\ServiceProvider"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "4.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/helpers.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Fruitcake\\LaravelDebugbar\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fruitcake",
|
||||||
|
"homepage": "https://fruitcake.nl"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP Debugbar integration for Laravel",
|
||||||
|
"keywords": [
|
||||||
|
"barryvdh",
|
||||||
|
"debug",
|
||||||
|
"debugbar",
|
||||||
|
"dev",
|
||||||
|
"laravel",
|
||||||
|
"profiler",
|
||||||
|
"webprofiler"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/fruitcake/laravel-debugbar/issues",
|
||||||
|
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.0.10"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://fruitcake.nl",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/barryvdh",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2026-02-26T11:45:48+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "fakerphp/faker",
|
"name": "fakerphp/faker",
|
||||||
"version": "v1.24.1",
|
"version": "v1.24.1",
|
||||||
@@ -7660,6 +7759,174 @@
|
|||||||
},
|
},
|
||||||
"time": "2022-02-21T01:04:05+00:00"
|
"time": "2022-02-21T01:04:05+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "php-debugbar/php-debugbar",
|
||||||
|
"version": "v3.4.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-debugbar/php-debugbar.git",
|
||||||
|
"reference": "ee9c718797a4c1fdf6c4d980cb3edcc1eeeddcc7"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/ee9c718797a4c1fdf6c4d980cb3edcc1eeeddcc7",
|
||||||
|
"reference": "ee9c718797a4c1fdf6c4d980cb3edcc1eeeddcc7",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^8.2",
|
||||||
|
"psr/log": "^1|^2|^3",
|
||||||
|
"symfony/var-dumper": "^5.4|^6|^7|^8"
|
||||||
|
},
|
||||||
|
"replace": {
|
||||||
|
"maximebf/debugbar": "self.version"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"dbrekelmans/bdi": "^1.4",
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.92",
|
||||||
|
"monolog/monolog": "^3.9",
|
||||||
|
"php-debugbar/doctrine-bridge": "^3@dev",
|
||||||
|
"php-debugbar/monolog-bridge": "^1@dev",
|
||||||
|
"php-debugbar/symfony-bridge": "^1@dev",
|
||||||
|
"php-debugbar/twig-bridge": "^2@dev",
|
||||||
|
"phpstan/phpstan": "^2.1",
|
||||||
|
"phpstan/phpstan-phpunit": "^2.0",
|
||||||
|
"phpstan/phpstan-strict-rules": "^2.0",
|
||||||
|
"phpunit/phpunit": "^10",
|
||||||
|
"predis/predis": "^3.3",
|
||||||
|
"shipmonk/phpstan-rules": "^4.3",
|
||||||
|
"symfony/browser-kit": "^6.4|7.0",
|
||||||
|
"symfony/dom-crawler": "^6.4|^7",
|
||||||
|
"symfony/event-dispatcher": "^5.4|^6.4|^7.3|^8.0",
|
||||||
|
"symfony/http-foundation": "^5.4|^6.4|^7.3|^8.0",
|
||||||
|
"symfony/mailer": "^5.4|^6.4|^7.3|^8.0",
|
||||||
|
"symfony/panther": "^1|^2.1",
|
||||||
|
"twig/twig": "^3.11.2"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"php-debugbar/doctrine-bridge": "To integrate Doctrine with php-debugbar.",
|
||||||
|
"php-debugbar/monolog-bridge": "To integrate Monolog with php-debugbar.",
|
||||||
|
"php-debugbar/symfony-bridge": "To integrate Symfony with php-debugbar.",
|
||||||
|
"php-debugbar/twig-bridge": "To integrate Twig with php-debugbar."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DebugBar\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Maxime Bouroumeau-Fuseau",
|
||||||
|
"email": "maxime.bouroumeau@gmail.com",
|
||||||
|
"homepage": "http://maximebf.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Debug bar in the browser for php application",
|
||||||
|
"homepage": "https://github.com/php-debugbar/php-debugbar",
|
||||||
|
"keywords": [
|
||||||
|
"debug",
|
||||||
|
"debug bar",
|
||||||
|
"debugbar",
|
||||||
|
"dev",
|
||||||
|
"profiler",
|
||||||
|
"toolbar"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
|
||||||
|
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.4.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://fruitcake.nl",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/barryvdh",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2026-02-26T11:40:30+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "php-debugbar/symfony-bridge",
|
||||||
|
"version": "v1.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-debugbar/symfony-bridge.git",
|
||||||
|
"reference": "e37d2debe5d316408b00d0ab2688d9c2cf59b5ad"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-debugbar/symfony-bridge/zipball/e37d2debe5d316408b00d0ab2688d9c2cf59b5ad",
|
||||||
|
"reference": "e37d2debe5d316408b00d0ab2688d9c2cf59b5ad",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^8.2",
|
||||||
|
"php-debugbar/php-debugbar": "^3.1",
|
||||||
|
"symfony/http-foundation": "^5.4|^6.4|^7.3|^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"dbrekelmans/bdi": "^1.4",
|
||||||
|
"phpunit/phpunit": "^10",
|
||||||
|
"symfony/browser-kit": "^6|^7",
|
||||||
|
"symfony/dom-crawler": "^6|^7",
|
||||||
|
"symfony/mailer": "^5.4|^6.4|^7.3|^8.0",
|
||||||
|
"symfony/panther": "^1|^2.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DebugBar\\Bridge\\Symfony\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Maxime Bouroumeau-Fuseau",
|
||||||
|
"email": "maxime.bouroumeau@gmail.com",
|
||||||
|
"homepage": "http://maximebf.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Barry vd. Heuvel",
|
||||||
|
"email": "barryvdh@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony bridge for PHP Debugbar",
|
||||||
|
"homepage": "https://github.com/php-debugbar/php-debugbar",
|
||||||
|
"keywords": [
|
||||||
|
"debugbar",
|
||||||
|
"dev",
|
||||||
|
"symfony"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/php-debugbar/symfony-bridge/issues",
|
||||||
|
"source": "https://github.com/php-debugbar/symfony-bridge/tree/v1.1.0"
|
||||||
|
},
|
||||||
|
"time": "2026-01-15T14:47:34+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/php-code-coverage",
|
"name": "phpunit/php-code-coverage",
|
||||||
"version": "11.0.12",
|
"version": "11.0.12",
|
||||||
@@ -9290,5 +9557,5 @@
|
|||||||
"php": "^8.2"
|
"php": "^8.2"
|
||||||
},
|
},
|
||||||
"platform-dev": {},
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.9.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,28 +3,38 @@
|
|||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
return new class extends Migration
|
return new class extends Migration
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
Schema::create('crews', function (Blueprint $table) {
|
Schema::create('crews', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
|
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
$table->string('description');
|
$table->text('description')->nullable();
|
||||||
$table->string('slug');
|
|
||||||
$table->foreignId('image_id')->constrained()->cascadeOnDelete();
|
// invite code
|
||||||
$table->foreignId('cover_image_id')->constrained('images')->cascadeOnDelete();
|
$table->string('slug')->unique();
|
||||||
|
|
||||||
|
// avatar image
|
||||||
|
$table->foreignId('image_id')
|
||||||
|
->nullable()
|
||||||
|
->constrained('images')
|
||||||
|
->nullOnDelete();
|
||||||
|
|
||||||
|
// optional cover image
|
||||||
|
$table->foreignId('cover_image_id')
|
||||||
|
->nullable()
|
||||||
|
->constrained('images')
|
||||||
|
->nullOnDelete();
|
||||||
|
|
||||||
|
$table->string('avatar_icon')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*/
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
Schema::dropIfExists('crews');
|
Schema::dropIfExists('crews');
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ return new class extends Migration
|
|||||||
*/
|
*/
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
Schema::create('crew_members', function (Blueprint $table) {
|
Schema::create('crew_user', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->foreignId('user_id')->constrained();
|
$table->foreignId('user_id')->constrained();
|
||||||
$table->foreignId('crew_id')->constrained();
|
$table->foreignId('crew_id')->constrained();
|
||||||
@@ -26,6 +26,6 @@ return new class extends Migration
|
|||||||
*/
|
*/
|
||||||
public function down(): void
|
public function down(): void
|
||||||
{
|
{
|
||||||
Schema::dropIfExists('crew_members');
|
Schema::dropIfExists('crew_user');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -13,7 +13,7 @@ return new class extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('crew_patches', function (Blueprint $table) {
|
Schema::create('crew_patches', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
|
$table->foreignId('crew_id')->constrained()->cascadeOnDelete();
|
||||||
$table->foreignId('crew_patch_id')->constrained()->cascadeOnDelete();
|
$table->foreignId('crew_patch_id')->constrained()->cascadeOnDelete();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
|||||||
209
package-lock.json
generated
209
package-lock.json
generated
@@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "sendit",
|
"name": "patchbook",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"name": "patchbook",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
@@ -506,9 +507,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
|
||||||
"integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==",
|
"integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -520,9 +521,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==",
|
"integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -534,9 +535,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==",
|
"integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -548,9 +549,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
|
||||||
"integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==",
|
"integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -562,9 +563,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==",
|
"integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -576,9 +577,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
|
||||||
"integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==",
|
"integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -590,9 +591,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
|
||||||
"integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==",
|
"integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -604,9 +605,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
|
||||||
"integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==",
|
"integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -618,9 +619,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==",
|
"integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -632,9 +633,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==",
|
"integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -646,9 +647,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==",
|
"integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@@ -660,9 +661,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loong64-musl": {
|
"node_modules/@rollup/rollup-linux-loong64-musl": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==",
|
"integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@@ -674,9 +675,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==",
|
"integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -688,9 +689,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-ppc64-musl": {
|
"node_modules/@rollup/rollup-linux-ppc64-musl": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==",
|
"integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -702,9 +703,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==",
|
"integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -716,9 +717,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==",
|
"integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -730,9 +731,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==",
|
"integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@@ -744,9 +745,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==",
|
"integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -758,9 +759,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==",
|
"integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -772,9 +773,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-openbsd-x64": {
|
"node_modules/@rollup/rollup-openbsd-x64": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
|
||||||
"integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==",
|
"integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -786,9 +787,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-openharmony-arm64": {
|
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==",
|
"integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -800,9 +801,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
|
||||||
"integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==",
|
"integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -814,9 +815,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
|
||||||
"integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==",
|
"integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -828,9 +829,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==",
|
"integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -842,9 +843,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
|
||||||
"integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==",
|
"integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -2085,9 +2086,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.57.1",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
|
||||||
"integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==",
|
"integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -2101,31 +2102,31 @@
|
|||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.57.1",
|
"@rollup/rollup-android-arm-eabi": "4.59.0",
|
||||||
"@rollup/rollup-android-arm64": "4.57.1",
|
"@rollup/rollup-android-arm64": "4.59.0",
|
||||||
"@rollup/rollup-darwin-arm64": "4.57.1",
|
"@rollup/rollup-darwin-arm64": "4.59.0",
|
||||||
"@rollup/rollup-darwin-x64": "4.57.1",
|
"@rollup/rollup-darwin-x64": "4.59.0",
|
||||||
"@rollup/rollup-freebsd-arm64": "4.57.1",
|
"@rollup/rollup-freebsd-arm64": "4.59.0",
|
||||||
"@rollup/rollup-freebsd-x64": "4.57.1",
|
"@rollup/rollup-freebsd-x64": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.57.1",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm-musleabihf": "4.57.1",
|
"@rollup/rollup-linux-arm-musleabihf": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.57.1",
|
"@rollup/rollup-linux-arm64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.57.1",
|
"@rollup/rollup-linux-arm64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-loong64-gnu": "4.57.1",
|
"@rollup/rollup-linux-loong64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-loong64-musl": "4.57.1",
|
"@rollup/rollup-linux-loong64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-ppc64-gnu": "4.57.1",
|
"@rollup/rollup-linux-ppc64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-ppc64-musl": "4.57.1",
|
"@rollup/rollup-linux-ppc64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.57.1",
|
"@rollup/rollup-linux-riscv64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-riscv64-musl": "4.57.1",
|
"@rollup/rollup-linux-riscv64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-s390x-gnu": "4.57.1",
|
"@rollup/rollup-linux-s390x-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.57.1",
|
"@rollup/rollup-linux-x64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.57.1",
|
"@rollup/rollup-linux-x64-musl": "4.59.0",
|
||||||
"@rollup/rollup-openbsd-x64": "4.57.1",
|
"@rollup/rollup-openbsd-x64": "4.59.0",
|
||||||
"@rollup/rollup-openharmony-arm64": "4.57.1",
|
"@rollup/rollup-openharmony-arm64": "4.59.0",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.57.1",
|
"@rollup/rollup-win32-arm64-msvc": "4.59.0",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.57.1",
|
"@rollup/rollup-win32-ia32-msvc": "4.59.0",
|
||||||
"@rollup/rollup-win32-x64-gnu": "4.57.1",
|
"@rollup/rollup-win32-x64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.57.1",
|
"@rollup/rollup-win32-x64-msvc": "4.59.0",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
419
resources/views/components/groups/⚡create.blade.php
Normal file
419
resources/views/components/groups/⚡create.blade.php
Normal file
@@ -0,0 +1,419 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Crew;
|
||||||
|
use App\Models\Image;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Livewire\Attributes\Computed;
|
||||||
|
use Livewire\Component;
|
||||||
|
use Livewire\WithFileUploads;
|
||||||
|
|
||||||
|
new class extends Component
|
||||||
|
{
|
||||||
|
use WithFileUploads;
|
||||||
|
|
||||||
|
public bool $isOpen = false;
|
||||||
|
|
||||||
|
public string $name = '';
|
||||||
|
public string $description = '';
|
||||||
|
|
||||||
|
// Avatar state
|
||||||
|
public bool $avatarModalOpen = false;
|
||||||
|
public string $avatarTab = 'icon'; // icon | photo
|
||||||
|
public string $iconSearch = '';
|
||||||
|
public ?string $avatarIcon = null;
|
||||||
|
|
||||||
|
/** @var \Livewire\Features\SupportFileUploads\TemporaryUploadedFile|null */
|
||||||
|
public $avatarPhoto = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Icon list using your installed Blade icon packs.
|
||||||
|
* Store the component string in DB (crews.avatar_icon).
|
||||||
|
*/
|
||||||
|
public array $icons = [
|
||||||
|
['component' => 'phosphor-mountains', 'label' => 'Mountains'],
|
||||||
|
['component' => 'phosphor-compass', 'label' => 'Compass'],
|
||||||
|
['component' => 'phosphor-tent', 'label' => 'Tent'],
|
||||||
|
['component' => 'phosphor-map-trifold', 'label' => 'Map'],
|
||||||
|
['component' => 'phosphor-footprints', 'label' => 'Footprints'],
|
||||||
|
['component' => 'phosphor-fire', 'label' => 'Fire'],
|
||||||
|
['component' => 'phosphor-star', 'label' => 'Star'],
|
||||||
|
['component' => 'phosphor-flag', 'label' => 'Flag'],
|
||||||
|
['component' => 'phosphor-trophy', 'label' => 'Trophy'],
|
||||||
|
['component' => 'phosphor-target', 'label' => 'Target'],
|
||||||
|
['component' => 'solar-sun-linear', 'label' => 'Sun'],
|
||||||
|
['component' => 'solar-moon-linear', 'label' => 'Moon'],
|
||||||
|
['component' => 'bi-heart', 'label' => 'Heart'],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function openModal(): void
|
||||||
|
{
|
||||||
|
$this->resetValidation();
|
||||||
|
$this->isOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function closeModal(): void
|
||||||
|
{
|
||||||
|
$this->isOpen = false;
|
||||||
|
$this->avatarModalOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function openAvatarModal(): void
|
||||||
|
{
|
||||||
|
$this->resetValidation();
|
||||||
|
$this->avatarModalOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function closeAvatarModal(): void
|
||||||
|
{
|
||||||
|
$this->avatarModalOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAvatarTab(string $tab): void
|
||||||
|
{
|
||||||
|
if (!in_array($tab, ['icon', 'photo'], true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->avatarTab = $tab;
|
||||||
|
$this->resetValidation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function selectIcon(string $component): void
|
||||||
|
{
|
||||||
|
$allowed = array_column($this->icons, 'component');
|
||||||
|
if (!in_array($component, $allowed, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->avatarIcon = $component;
|
||||||
|
$this->avatarPhoto = null;
|
||||||
|
$this->avatarTab = 'icon';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updatedAvatarPhoto(): void
|
||||||
|
{
|
||||||
|
if ($this->avatarPhoto) {
|
||||||
|
$this->avatarIcon = null;
|
||||||
|
$this->avatarTab = 'photo';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Computed]
|
||||||
|
public function filteredIcons(): array
|
||||||
|
{
|
||||||
|
$q = trim(mb_strtolower($this->iconSearch));
|
||||||
|
if ($q === '') {
|
||||||
|
return $this->icons;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_filter($this->icons, function (array $icon) use ($q) {
|
||||||
|
return str_contains(mb_strtolower($icon['label']), $q)
|
||||||
|
|| str_contains(mb_strtolower($icon['component']), $q);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Computed]
|
||||||
|
public function avatarPreviewType(): string
|
||||||
|
{
|
||||||
|
if ($this->avatarPhoto) {
|
||||||
|
return 'photo';
|
||||||
|
}
|
||||||
|
if ($this->avatarIcon) {
|
||||||
|
return 'icon';
|
||||||
|
}
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$this->validate([
|
||||||
|
'name' => ['required', 'string', 'max:60'],
|
||||||
|
'description' => ['nullable', 'string', 'max:140'],
|
||||||
|
'avatarIcon' => ['nullable', 'string', 'max:100'],
|
||||||
|
'avatarPhoto' => ['nullable', 'image', 'max:4096'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$crew = Crew::create([
|
||||||
|
'name' => $this->name,
|
||||||
|
'description' => $this->description ?: null,
|
||||||
|
'avatar_icon' => $this->avatarIcon,
|
||||||
|
'image_id' => null,
|
||||||
|
'cover_image_id' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($this->avatarPhoto) {
|
||||||
|
$disk = 'public';
|
||||||
|
|
||||||
|
$ext = $this->avatarPhoto->getClientOriginalExtension();
|
||||||
|
$ext = $ext ? mb_strtolower($ext) : 'jpg';
|
||||||
|
|
||||||
|
$path = "crews/{$crew->id}/avatar.{$ext}";
|
||||||
|
|
||||||
|
Storage::disk($disk)->putFileAs(
|
||||||
|
"crews/{$crew->id}",
|
||||||
|
$this->avatarPhoto,
|
||||||
|
"avatar.{$ext}"
|
||||||
|
);
|
||||||
|
|
||||||
|
$absolute = Storage::disk($disk)->path($path);
|
||||||
|
|
||||||
|
$width = null;
|
||||||
|
$height = null;
|
||||||
|
|
||||||
|
$sizeData = @getimagesize($absolute);
|
||||||
|
if (is_array($sizeData)) {
|
||||||
|
$width = $sizeData[0] ?? null;
|
||||||
|
$height = $sizeData[1] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$image = Image::create([
|
||||||
|
'disk' => $disk,
|
||||||
|
'bucket' => null,
|
||||||
|
'path' => $path,
|
||||||
|
'original_name' => $this->avatarPhoto->getClientOriginalName(),
|
||||||
|
'mime_type' => $this->avatarPhoto->getMimeType(),
|
||||||
|
'size' => $this->avatarPhoto->getSize(),
|
||||||
|
'width' => $width,
|
||||||
|
'height' => $height,
|
||||||
|
'variants' => null,
|
||||||
|
'visibility' => 'public',
|
||||||
|
'checksum' => null,
|
||||||
|
'exif_stripped' => true,
|
||||||
|
'uploaded_by_user_id' => Auth::id(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$crew->image_id = $image->id;
|
||||||
|
$crew->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
$crew->users()->attach(Auth::id());
|
||||||
|
|
||||||
|
// ToastMagic success
|
||||||
|
$this->dispatch('toastmagic', type: 'success', message: 'Group created');
|
||||||
|
|
||||||
|
return redirect('/groups');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="relative">
|
||||||
|
<button type="button" wire:click="openModal" class="btn-primary w-full text-base">
|
||||||
|
Create
|
||||||
|
</button>
|
||||||
|
|
||||||
|
@if($isOpen)
|
||||||
|
<div class="fixed inset-0 z-[9999]" role="dialog" aria-modal="true" wire:keydown.escape.window="closeModal">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="absolute inset-0 bg-black/50"
|
||||||
|
wire:click="closeModal"
|
||||||
|
aria-label="Close modal"
|
||||||
|
></button>
|
||||||
|
|
||||||
|
<div class="absolute inset-0 bg-card">
|
||||||
|
<div class="mx-auto flex h-full w-full max-w-[420px] flex-col px-6 pt-6 pb-8">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<button type="button" wire:click="closeModal" class="grid h-10 w-10 place-items-center rounded-xl bg-background ring-1 ring-border">
|
||||||
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||||
|
<path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<h3 class="text-lg font-semibold">Create Group</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6 rounded-2xl bg-background p-4 ring-1 ring-border">
|
||||||
|
<div class="mx-auto grid h-16 w-16 place-items-center rounded-2xl bg-muted">
|
||||||
|
@if($this->avatarPreviewType === 'photo')
|
||||||
|
<img src="{{ $avatarPhoto->temporaryUrl() }}" alt="Avatar preview" class="h-16 w-16 rounded-2xl object-cover" />
|
||||||
|
@elseif($this->avatarPreviewType === 'icon')
|
||||||
|
<x-dynamic-component :component="$avatarIcon" class="h-8 w-8 text-foreground" />
|
||||||
|
@else
|
||||||
|
<x-phosphor-mountains class="h-8 w-8 text-foreground/60" />
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 text-center">
|
||||||
|
<p class="text-sm font-semibold text-foreground">
|
||||||
|
{{ $name !== '' ? $name : 'Group Name' }}
|
||||||
|
</p>
|
||||||
|
<p class="mt-1 text-xs text-muted-foreground">
|
||||||
|
{{ $description !== '' ? $description : 'Group description...' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6">
|
||||||
|
<p class="text-sm font-semibold">Group Avatar</p>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
wire:click="openAvatarModal"
|
||||||
|
class="mt-3 flex w-full items-center gap-3 rounded-2xl bg-background p-4 ring-1 ring-border"
|
||||||
|
>
|
||||||
|
<div class="grid h-12 w-12 place-items-center rounded-2xl border border-dashed border-border bg-muted">
|
||||||
|
@if($this->avatarPreviewType === 'photo')
|
||||||
|
<img src="{{ $avatarPhoto->temporaryUrl() }}" alt="Avatar preview" class="h-12 w-12 rounded-2xl object-cover" />
|
||||||
|
@elseif($this->avatarPreviewType === 'icon')
|
||||||
|
<x-dynamic-component :component="$avatarIcon" class="h-6 w-6 text-foreground" />
|
||||||
|
@else
|
||||||
|
<x-phosphor-mountains class="h-6 w-6 text-foreground" />
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-left">
|
||||||
|
<p class="text-sm font-medium">Tap to pick an icon or upload a photo</p>
|
||||||
|
<p class="mt-0.5 text-xs text-muted-foreground">This will show on your group.</p>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6 flex flex-col gap-3">
|
||||||
|
<label class="rounded-2xl bg-background p-4 ring-1 ring-border">
|
||||||
|
<p class="text-xs text-muted-foreground">Group Name</p>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
wire:model.live="name"
|
||||||
|
class="mt-2 w-full rounded bg-transparent text-sm outline-none"
|
||||||
|
placeholder="e.g. Weekend Warriors"
|
||||||
|
/>
|
||||||
|
@error('name')
|
||||||
|
<p class="mt-2 text-xs text-red-500">{{ $message }}</p>
|
||||||
|
@enderror
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="rounded-2xl bg-background p-4 ring-1 ring-border">
|
||||||
|
<p class="text-xs text-muted-foreground">Description</p>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
wire:model.live="description"
|
||||||
|
class="mt-2 w-full rounded bg-transparent text-sm outline-none"
|
||||||
|
placeholder="What's this group about?"
|
||||||
|
/>
|
||||||
|
@error('description')
|
||||||
|
<p class="mt-2 text-xs text-red-500">{{ $message }}</p>
|
||||||
|
@enderror
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-auto pt-6">
|
||||||
|
<button type="button" wire:click="save" wire:loading.attr="disabled" class="btn-primary w-full text-base">
|
||||||
|
<span wire:loading.remove wire:target="save">Create Group</span>
|
||||||
|
<span wire:loading wire:target="save">Creating...</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Avatar Picker Modal --}}
|
||||||
|
@if($avatarModalOpen)
|
||||||
|
<div class="absolute inset-0 z-[10000]" role="dialog" aria-modal="true" wire:keydown.escape.window="closeAvatarModal">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="absolute inset-0 bg-black/50"
|
||||||
|
wire:click="closeAvatarModal"
|
||||||
|
aria-label="Close avatar modal"
|
||||||
|
></button>
|
||||||
|
|
||||||
|
<div class="absolute left-1/2 top-1/2 w-[92%] max-w-[420px] -translate-x-1/2 -translate-y-1/2 rounded-2xl bg-card p-5 shadow-xl ring-1 ring-border">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h4 class="text-base font-semibold">Group Avatar</h4>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
wire:click="closeAvatarModal"
|
||||||
|
class="grid h-9 w-9 place-items-center rounded-xl bg-background ring-1 ring-border"
|
||||||
|
aria-label="Close"
|
||||||
|
>
|
||||||
|
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||||
|
<path d="M6 6l12 12M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 rounded-2xl bg-muted p-1 ring-1 ring-border">
|
||||||
|
<div class="grid grid-cols-2 gap-1">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
wire:click="setAvatarTab('icon')"
|
||||||
|
class="rounded-xl px-3 py-2 text-sm font-medium {{ $avatarTab === 'icon' ? 'bg-card ring-1 ring-border' : 'opacity-70' }}"
|
||||||
|
>
|
||||||
|
Icon
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
wire:click="setAvatarTab('photo')"
|
||||||
|
class="rounded-xl px-3 py-2 text-sm font-medium {{ $avatarTab === 'photo' ? 'bg-card ring-1 ring-border' : 'opacity-70' }}"
|
||||||
|
>
|
||||||
|
Photo
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if($avatarTab === 'icon')
|
||||||
|
<div class="mt-4">
|
||||||
|
<div class="flex items-center gap-2 rounded-2xl bg-background px-3 py-2 ring-1 ring-border">
|
||||||
|
<svg class="h-4 w-4 opacity-60" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||||
|
<path d="M21 21l-4.3-4.3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
wire:model.live="iconSearch"
|
||||||
|
class="w-full bg-transparent text-sm outline-none"
|
||||||
|
placeholder="Search icons..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 max-h-[320px] overflow-auto pr-1">
|
||||||
|
<div class="grid grid-cols-6 gap-2 p-2">
|
||||||
|
@foreach($this->filteredIcons as $icon)
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
wire:click="selectIcon(@js($icon['component']))"
|
||||||
|
class="grid h-12 w-12 place-items-center rounded-xl ring-1 ring-border {{ $avatarIcon === $icon['component'] ? 'bg-primary/15' : 'bg-background' }}"
|
||||||
|
aria-label="Select icon {{ $icon['label'] }}"
|
||||||
|
title="{{ $icon['label'] }}"
|
||||||
|
>
|
||||||
|
<x-dynamic-component :component="$icon['component']" class="h-6 w-6" />
|
||||||
|
</button>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<div class="mt-5">
|
||||||
|
<label class="block cursor-pointer rounded-2xl bg-background p-5 ring-1 ring-border">
|
||||||
|
<div class="grid place-items-center rounded-2xl border border-dashed border-border bg-muted px-6 py-8 text-center">
|
||||||
|
<svg class="h-7 w-7" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||||
|
<path d="M9 7a3 3 0 1 0 6 0a3 3 0 1 0-6 0Z" stroke="currentColor" stroke-width="2"/>
|
||||||
|
<path d="M4 20l5-6 4 4 3-3 4 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v14" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
<p class="mt-2 text-sm font-medium">Upload Photo</p>
|
||||||
|
<p class="mt-1 text-xs text-muted-foreground">Choose a photo for your group</p>
|
||||||
|
|
||||||
|
@if($avatarPhoto)
|
||||||
|
<img src="{{ $avatarPhoto->temporaryUrl() }}" class="mt-4 h-20 w-20 rounded-2xl object-cover" alt="Uploaded preview" />
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="file" class="hidden" wire:model="avatarPhoto" accept="image/*" />
|
||||||
|
</label>
|
||||||
|
|
||||||
|
@error('avatarPhoto')
|
||||||
|
<p class="mt-2 text-xs text-red-500">{{ $message }}</p>
|
||||||
|
@enderror
|
||||||
|
|
||||||
|
<div class="mt-3 flex items-center justify-end">
|
||||||
|
<button type="button" wire:click="closeAvatarModal" class="btn-outline px-4 py-2 text-sm">
|
||||||
|
Done
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
13
resources/views/components/groups/⚡join.blade.php
Normal file
13
resources/views/components/groups/⚡join.blade.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
new class extends Component
|
||||||
|
{
|
||||||
|
//
|
||||||
|
};
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{-- Always remember that you are absolutely unique. Just like everyone else. - Margaret Mead --}}
|
||||||
|
</div>
|
||||||
37
resources/views/components/⚡group-card.blade.php
Normal file
37
resources/views/components/⚡group-card.blade.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Crew;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
new class extends Component {
|
||||||
|
public Crew $crew;
|
||||||
|
|
||||||
|
public function mount(Crew $crew): void
|
||||||
|
{
|
||||||
|
$this->crew = $crew;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="card bg-card flex items-center gap-4 rounded-xl transition-colors hover:bg-secondary/50 active:scale-[0.98] p-4">
|
||||||
|
<div class="grid h-10 w-10 place-items-center rounded-xl bg-primary/15 text-primary-foreground mb-2">
|
||||||
|
<x-bi-people class="h-6 w-6 text-primary"/>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 overflow-hidden">
|
||||||
|
<h3 class="truncate text-sm font-semibold">{{ $crew->name }}</h3>
|
||||||
|
<p>{{ $crew->description }}</p>
|
||||||
|
<div class="mt-1 flex items-center gap-3 text-xs text-muted-foreground">
|
||||||
|
<span class="flex items-center gap-1">
|
||||||
|
<x-bi-people class="h-3 w-3"/>
|
||||||
|
{{ $crew->users_count }}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{{ $crew->patches_count }} patches
|
||||||
|
</span>
|
||||||
|
<span class="text-primary font-medium">
|
||||||
|
{{ $crew->patches_count }} earned
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,17 +1,27 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
new class extends Component
|
new class extends Component
|
||||||
{
|
{
|
||||||
//
|
public Collection $crews;
|
||||||
|
|
||||||
|
public function mount(): void
|
||||||
|
{
|
||||||
|
$this->crews = Auth::user()
|
||||||
|
->crews()
|
||||||
|
->withCount(['users', 'patches'])
|
||||||
|
->get();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="flex flex-col gap-6 px-4 pt-6 pb-4">
|
<div class="flex flex-col gap-6 px-4 pt-6 pb-4">
|
||||||
<div>
|
<div>
|
||||||
<p class="text-sm text-muted-foreground">Welcome back,</p>
|
<p class="text-sm text-muted-foreground">Welcome back,</p>
|
||||||
<h1 class="text-2xl font-bold text-foreground">Alex Rivera</h1>
|
<h1 class="text-2xl font-bold text-foreground">{{ ucfirst(Auth::user()->name) }}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-3 gap-3">
|
<div class="grid grid-cols-3 gap-3">
|
||||||
@@ -19,23 +29,37 @@ new class extends Component
|
|||||||
<div class="grid h-10 w-10 place-items-center rounded-xl bg-primary/15 text-primary-foreground mb-2">
|
<div class="grid h-10 w-10 place-items-center rounded-xl bg-primary/15 text-primary-foreground mb-2">
|
||||||
<x-bi-people class="h-6 w-6 text-primary" />
|
<x-bi-people class="h-6 w-6 text-primary" />
|
||||||
</div>
|
</div>
|
||||||
<span class="font-bold text-xl">2</span>
|
<span class="font-bold text-xl">{{ $crews->count() }}</span>
|
||||||
<span class="text-muted-foreground text-sm">Groups</span>
|
<span class="text-muted-foreground text-sm">Groups</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col items-center gap-1 rounded-xl border border-border bg-card p-3">
|
<div class="flex flex-col items-center gap-1 rounded-xl border border-border bg-card p-3">
|
||||||
<div class="grid h-10 w-10 place-items-center rounded-xl bg-accent/15 text-primary-foreground mb-2">
|
<div class="grid h-10 w-10 place-items-center rounded-xl bg-accent/15 text-primary-foreground mb-2">
|
||||||
<x-solar-medal-ribbon-linear class="h-6 w-6 text-accent" />
|
<x-solar-medal-ribbon-linear class="h-6 w-6 text-accent" />
|
||||||
</div>
|
</div>
|
||||||
<span class="font-bold text-xl">2</span>
|
<span class="font-bold text-xl">0</span>
|
||||||
<span class="text-muted-foreground text-sm">Groups</span>
|
<span class="text-muted-foreground text-sm">Earned</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col items-center gap-1 rounded-xl border border-border bg-card p-3">
|
<div class="flex flex-col items-center gap-1 rounded-xl border border-border bg-card p-3">
|
||||||
<div class="grid h-10 w-10 place-items-center rounded-xl bg-card-foreground/15 text-primary-foreground mb-2">
|
<div class="grid h-10 w-10 place-items-center rounded-xl bg-card-foreground/15 text-primary-foreground mb-2">
|
||||||
<x-phosphor-trend-up class="h-6 w-6 text-card-foreground" />
|
<x-phosphor-trend-up class="h-6 w-6 text-card-foreground" />
|
||||||
</div>
|
</div>
|
||||||
<span class="font-bold text-xl">2</span>
|
<span class="font-bold text-xl">0</span>
|
||||||
<span class="text-muted-foreground text-sm">Groups</span>
|
<span class="text-muted-foreground text-sm">In progress</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="flex items-center justify-between mb-5 font-semibold">
|
||||||
|
<p class="text-foreground text-base">Your Groups</p>
|
||||||
|
<a class="text-primary" href="{{ route('groups') }}">View All</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
@foreach ($crews as $crew)
|
||||||
|
<livewire:group-card :crew="$crew" :key="$crew->id" />
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,13 +1,30 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
new class extends Component
|
new class extends Component {
|
||||||
|
public Collection $crews;
|
||||||
|
|
||||||
|
public function mount(): void
|
||||||
{
|
{
|
||||||
//
|
$this->crews = Auth::user()
|
||||||
|
->crews()
|
||||||
|
->withCount(['users', 'patches'])
|
||||||
|
->get();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div>
|
<div class="flex flex-col gap-3 px-4 pt-6 pb-4">
|
||||||
{{-- Order your soul. Reduce your wants. - Augustine --}}
|
<div class="flex items-center justify-between">
|
||||||
|
<h1 class="text-xl font-bold text-foreground">Your Groups</h1>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<button class="btn-outline w-full text-base bg-background">Join</button>
|
||||||
|
<livewire:groups.create/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@foreach($crews as $crew)
|
||||||
|
<livewire:group-card :crew="$crew" :key="$crew->id"/>
|
||||||
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
@@ -6,8 +6,9 @@ use Illuminate\Support\Facades\Route;
|
|||||||
Route::livewire('/', 'pages::landing');
|
Route::livewire('/', 'pages::landing');
|
||||||
|
|
||||||
Route::middleware(['auth'])->group(function () {
|
Route::middleware(['auth'])->group(function () {
|
||||||
Route::livewire('/profile', 'pages::profile');
|
Route::livewire('/profile', 'pages::profile')->name('profile');
|
||||||
Route::livewire('/dashboard', 'pages::dashboard');
|
Route::livewire('/dashboard', 'pages::dashboard')->name('dashboard');
|
||||||
|
Route::livewire('/groups', 'pages::groups')->name('groups');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('/login', function () {
|
Route::get('/login', function () {
|
||||||
|
|||||||
2
storage/debugbar/.gitignore
vendored
Normal file
2
storage/debugbar/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
@@ -11,14 +11,6 @@ export default defineConfig({
|
|||||||
tailwindcss(),
|
tailwindcss(),
|
||||||
],
|
],
|
||||||
server: {
|
server: {
|
||||||
host: '127.0.0.1',
|
|
||||||
port: 5173,
|
|
||||||
strictPort: true,
|
|
||||||
hmr: {
|
|
||||||
host: 'sendit.test',
|
|
||||||
protocol: 'ws',
|
|
||||||
port: 5173,
|
|
||||||
},
|
|
||||||
watch: {
|
watch: {
|
||||||
ignored: ['**/storage/framework/views/**'],
|
ignored: ['**/storage/framework/views/**'],
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user