diff --git a/app/app/Http/Pages/Host/Properties/NewProperty.php b/app/app/Http/Pages/Host/Properties/NewProperty.php index 84273d8..06dc1f4 100644 --- a/app/app/Http/Pages/Host/Properties/NewProperty.php +++ b/app/app/Http/Pages/Host/Properties/NewProperty.php @@ -5,6 +5,7 @@ use App\Livewire\Forms\HostPropertyForm; use App\Models\Amenity; use App\Models\AmenityGroup; +use Illuminate\Contracts\View\View; use Illuminate\Database\Eloquent\Collection; use Livewire\Attributes\Layout; use Livewire\Attributes\Validate; @@ -18,204 +19,152 @@ class NewProperty extends Component use WireToast, WithFileUploads; public HostPropertyForm $form; - public Collection $all_amenities; - public $selected_amenities; + public $all_amenities; + + #[Validate([ + 'selected_amenities' => 'nullable|array', + 'selected_amenities.*' => 'required|integer|min:0|max:9999', + ])] + public $selected_amenities = []; + + #[Validate([ + 'temp_photos' => 'nullable|array', + 'temp_photos.*' => 'image|mimes:jpg,jpeg,png,webp,bmp|extensions:jpg,jpeg,png,webp,bmp|max:10240' + ], as: [ + 'temp_photos' => 'selected photos', + 'temp_photos.*' => 'selected photo', + ])] public $temp_photos; - // protected function rules() - // { - // return [ - // 'property.name' => ['required', 'string', 'max:60', 'unique:properties.name'], - // 'property.address.line_1' => ['required', 'string', 'max:250'], - // 'property.address.line_2' => ['nullable', 'string', 'max:250'], - // 'property.address.city' => ['required', 'string', 'max:250'], - // 'property.address.state' => ['required', 'string', 'alpha', 'size:2'], - // 'property.address.postal' => ['required', 'string', 'numeric', 'digits:5', 'regex:/^\d{5}$/'], - // 'property.address.country' => ['required', 'string', 'alpha', 'size:2'], - // // Listing - // 'property.listing.type' => ['required'], - // 'property.listing.headline' => ['required', 'string', 'max:250'], - // 'property.listing.description' => ['nullable', 'string', 'max:3000'], - // 'property.listing.guests' => ['required', 'numeric', 'min:1', 'max:16'], - // 'property.listing.beds' => ['required', 'numeric', 'min:0', 'max:99'], - // 'property.listing.bedrooms' => ['required', 'numeric', 'min:0', 'max:99'], - // 'property.listing.bathrooms' => ['required', 'numeric', 'min:0', 'max:99'], - // 'property.listing.amenities' => ['required'], - // 'property.listing.amenities.*' => [], - // // Pricing - // 'property.rates.base' => ['required', 'numeric'], - // 'property.rates.tax' => ['required', 'numeric'], - // 'property.rates.fees' => [''], - // 'property.rates.fees.*' => [''], - // 'property.rates.fees.*.name' => ['required', 'string', 'max:250'], - // 'property.rates.fees.*.amount' => ['required', 'numeric'], - // 'property.rates.fees.*.type' => ['required', 'string'], - // 'property.photos' => ['required'], - // 'property.photos.*' => ['image', 'mimes:jpg,jpeg,png,webp', 'extensions:jpg,jpeg,png,webp', 'max:6144'], - // 'temp_photos.*' => ['image', 'mimes:jpg,jpeg,png,webp', 'extensions:jpg,jpeg,png,webp', 'max:6144'], - // 'property.options.visibility' => ['required'], - // 'property.options.min-nights' => ['required', 'numeric', 'min:1', 'max:30'], - // 'property.options.max-nights' => ['required', 'numeric', 'min:1', 'max:30'], - // 'property.options.slug' => ['required'], - // 'property.options.color' => ['required'], - // ]; - // } - - // protected function messages() - // { - // return [ - // 'property.rates.base.required' => 'Base rate required', - // 'property.rates.tax.required' => 'Tax rate required', - // ]; - // } - - // protected function validationAttributes() - // { - // return [ - // 'property.name' => 'Property Name', - // 'property.address.line_1' => 'Address Line 1', - // 'property.address.line_2' => 'Address Line 2', - // 'property.address.city' => 'City', - // 'property.address.state' => 'State', - // 'property.address.postal' => 'ZIP Code', - // 'property.address.country' => 'Country', - // 'property.listing.headline' => 'Listing Headline', - // 'property.listing.description' => 'Listing Description', - - // 'property.listing.guests' => 'number of guests', - // 'property.listing.beds' => 'number of beds', - // 'property.listing.bedrooms' => 'number of bedrooms', - // 'property.listing.bathrooms' => 'number of bathrooms', - - // 'property.listing.amenities' => 'amenities', - // 'property.listing.amenities.*' => 'amenity', - // 'property.rates.base' => 'base rate', - // 'property.rates.tax' => 'tax rate', - // 'property.rates.fees' => 'fees', - // 'property.rates.fees.*' => 'fee', - // 'property.rates.fees.*.name' => 'fee name', - // 'property.rates.fees.*.amount' => 'fee amount', - // 'property.rates.fees.*.type' => 'fee type', - // 'property.photos' => 'photos', - // 'property.photos.*' => 'photo', - // 'temp_photos.*' => 'photo', - // 'property.options.visibility' => 'visibility', - // 'property.options.min-nights' => 'minimum nights', - // 'property.options.max-nights' => 'maximum nights', - // ]; - // } - - - public function mount(): void - { - // Need to init this so the char counter will work. - // WHAT? - } - - public function render() + /** + * Runs on page load + * + * @return View + */ + function render(): View { return view('pages.host.properties.new-property'); } - public function load(): void + /** + * Runs on page load, after page rendered + * + * @return void + */ + function load(): void { - - $this->loadAmenities(); - // $this->property = [ - // 'name' => '', - // 'address' => [ - // 'street_1' => '', - // 'street_2' => '', - // 'city' => '', - // 'state' => '', - // 'postal' => '', - // 'country' => '', - // ], - // 'listing' => [ - // 'headline' => '', - // 'description' => '', - // 'guests' => 1, - // 'beds' => 0, - // 'bedrooms' => 0, - // 'bathrooms' => 0, - // 'amenities' => [], - // ], - // 'rates' => [ - // 'base' => '', - // 'tax' => '', - // 'fees' => [], - // ], - // 'photos' => [], - // 'options' => [ - // 'duration-min' => 1, - // 'duration-max' => 14, - // 'visibility' => 'private', - // ], - // ]; + // } - public function reload(): void + /** + * Runs when user clicks the "reset" form button at the bottom of the page. + * Resets the form and closes the reset confirmation modal + * + * @return void + */ + function reload(): void { - $this->property = []; - $this->load(); - $this->modal('reset-modal')->close(); - } + // Reset the entire form + $this->form->reset(); + // Close the reset modal + $this->modal('reset-confirm-modal')->close(); + } /** - * Amenities + * Open Amenities Modal + * Runs when the user attempts to open the amenities modal + * + * - Pulls all amenity groups with associated amenenites + * - Clears selected amenities + * - Loops through each existing amenities, adds to the selected amenities + * - + * + * @return void */ - public function loadAmenities(): void + function openAmenitiesModal(): void { + // Loading the amenity groups with associated amenities from database $this->all_amenities = AmenityGroup::with('amenities')->get(); - $this->form->amenities = []; - } - public function openAmenitiesModal(): void - { - // Loading the amenities if not already - if (!$this->all_amenities) { - $this->loadAmenities(); - } + // Reset the selected amenities $this->selected_amenities = []; + // Add existing selected amenities to the foreach ($this->form->amenities as $amenity) { $this->selected_amenities[] = $amenity->id; } + if ($this->selected_amenities) { + dd($this->selected_amenities); + } + + + // Close amenities modal $this->modal('amenities-modal')->show(); } /** - * ! asdf + * Save Amenities Changes + * + * Runs when the user presses the "save changes" button on the amenities modal + * + * + * @return void */ - public function updateAmenities(): void + public function saveAmenityChanges(): void { + // Clear out existing amenities $this->form->reset('amenities'); + // Set variable for flatMap $selected_amenities = $this->selected_amenities; - $this->form->amenities = $this->all_amenities->flatMap(function ($amenity_group) use ($selected_amenities) { + + // Validate amenities + $this->validateOnly('selected_amenities'); + + // Filters through the amenities groups, then each amenity, checks if amenity id exists + $new_amenities = $this->all_amenities->flatMap(function ($amenity_group) use ($selected_amenities) { return $amenity_group->amenities->filter(function ($amenity) use ($selected_amenities) { return in_array($amenity->id, $selected_amenities); }); }); - $this->validateOnly('amenities'); + // Adds each amenity to the form + foreach ($new_amenities as $new_amenity) { + $this->form->amenities[] = $new_amenity; + } + // Closes amenities modal $this->modal('amenities-modal')->close(); } - public function removeAmenity($amenity_id): void + /** + * Remove Amenity + * Removes an amenity from the existing amenities. + * + * @param string $amenity_id + * @return void + */ + public function removeAmenity(string $amenity_id): void { - $this->form->amenities = $this->form->amenities->filter(function ($amenity) use ($amenity_id) { + $new_amenities = collect($this->form->amenities)->filter(function ($amenity) use ($amenity_id) { return $amenity->id != $amenity_id; }); + + $this->form->reset('amenities'); + + foreach ($new_amenities as $amenity) { + $this->form->amenities[] = $amenity; + } } /** - * Rates & Fees + * Add new fee + * Adds a new fee to the fees array + * + * @return void */ - public function addFee(): void { array_push($this->form->fees, [ @@ -225,56 +174,74 @@ public function addFee(): void ]); } - public function removeFee($key): void + /** + * Remove fee + * Removes fee by fee array key from the fees array + * + * @param integer $fee_key - The array key of the fee the user wants removed + * @return void + */ + public function removeFee(int $fee_key): void { - unset($this->form->fees[$key]); + unset($this->form->fees[$fee_key]); } /** * Photos - * * When the user uploads photos, $temp_photos are cleared and only shows new photos. * This takes all photos from $temp_photos and adds them to $photos so when the user * uploads more photos, the previous photos are not cleared. * + * @param array $temp_photos - an array of photos uploaded via livewire not uploaded yet * @return void */ function updatedTempPhotos(): void { + // Validate temp photos $this->validateOnly('temp_photos.*'); - foreach ($this->temp_photos as $temp_photo) { - $this->property['photos'][] = $temp_photo; + // Loop through each temp photo, adding it to the form + foreach ($this->temp_photos as $selected_photo) { + $this->form->photos[] = $selected_photo; } + // Clear temp photos + // This is primarily to remove the "# selected files" from the file input $this->temp_photos = []; } /** - * Runs when the user deletes a specific photo from the photo's grid + * Runs when the user deletes a specific photo from the photo's grid, then re-indexs + * the array * - * @param int $key The array key of the photo the user wants to delete + * @param int $photos_array_key - The array key of the photo the user wants to remove * @return void */ - public function deletePhoto($key): void + public function removePhoto($photos_array_key): void { - // remove the photo - unset($this->property['photos'][$key]); + // Unset the photo from the form's photo array + unset($this->form->photos[$photos_array_key]); - // reset the array keys to - $this->property['photos'] = array_values($this->property['photos']); + // Re-index the array + $this->form->photos = array_values($this->form->photos); + // Why? When you have an array [1,2,3,4] and you delete key 3, the array + // will now look like [1,2,4], then you can re-index so it looks like [1,2,3] } /** * Runs when the user reorders photos. + * Most of the magic happens with wire:sortable, but this rearranges the photos based on + * a new order specified in the $photo_order_data, given by wire:sortable. + * + * https://github.com/livewire/sortable * - * @param array $data + * @param array $photo_order_data - * @return void */ - function updatePhotoOrder(array $data): void + function updatePhotoOrder(array $photo_order_data): void { - $this->property['photos'] = array_map(fn($item) => $this->property['photos'][$item['value']], $data); - toast()->debug('test')->push(); + // Reorder photos based on the order given in $photo_order_data + $this->form->photos = array_map(fn($item) => $this->form->photos[$item['value']], $photo_order_data); } /** @@ -282,8 +249,8 @@ function updatePhotoOrder(array $data): void */ public function submit(): void { + $this->dispatch('console', $this->form); + // Validate the form $this->validate(); - - dd($this->property); } } diff --git a/app/app/Http/Test.php b/app/app/Http/Test.php new file mode 100644 index 0000000..de7047b --- /dev/null +++ b/app/app/Http/Test.php @@ -0,0 +1,19 @@ + 'Add Property'])] +class Test extends Component +{ + + #[Validate('required|string|numeric|digits:5|regex:/^\d{5}$/', as: 'zip / postal code')] + public ?int $address_postal; + + public function render() + { + return view('test'); + } +} diff --git a/app/app/Livewire/Forms/HostPropertyForm.php b/app/app/Livewire/Forms/HostPropertyForm.php index 5c3c301..d0d395b 100644 --- a/app/app/Livewire/Forms/HostPropertyForm.php +++ b/app/app/Livewire/Forms/HostPropertyForm.php @@ -10,93 +10,103 @@ class HostPropertyForm extends Form { // Basic #[Validate('required|string|max:250|unique:properties,name', as: 'property name')] - public $name; + public ?string $name; #[Validate('required|string|max:250', as: 'street address')] - public $address_line1; + public ?string $address_line1; #[Validate('nullable|string|max:250', as: 'address line 2')] - public $address_line2; + public ?string $address_line2; #[Validate('required|string|max:250', as: 'city')] - public $address_city; + public ?string $address_city; #[Validate('required|string|alpha|size:2', as: 'state')] - public $address_state; + public ?string $address_state; - #[Validate('required|string|numeric|digits:5|regex:/^\d{5}$/', as: 'zip / postal code', onUpdate: false)] - public $address_postal; + #[Validate('required|string|numeric|digits:5|regex:/^\d{5}$/', as: 'zip / postal code')] + public ?int $address_postal; #[Validate('required|string|alpha|size:2', as: 'country')] - public $address_country; + public ?string $address_country; // Listing #[Validate('required|string|max:250', as: 'headline')] - public $listing_headline; + public ?string $listing_headline; #[Validate('required|string|max:3000', as: 'description')] - public $listing_description; + public string $listing_description = ""; #[Validate('required|integer|numeric|min:1|max:16', as: 'guest count')] - public $guest_count; + public int $guest_count = 1; #[Validate('required|integer|numeric|min:0|max:99', as: 'bed count')] - public $bed_count; + public int $bed_count = 0; #[Validate('required|integer|numeric|min:0|max:99', as: 'bedroom count')] - public $bedroom_count; + public int $bedroom_count = 0; #[Validate('required|decimal:0,1|numeric|min:0|max:99', as: 'bathroom count')] - public $bathroom_count; + public int $bathroom_count = 0; - #[Validate('required|string', as: 'property type')] - public $property_type; + #[Validate('required|integer|exists:App\Models\PropertyType,id', as: 'property type')] + public ?int $property_type; // #[Validate('required|array', as: 'amenities')] #[Validate([ 'amenities' => 'required|array', - 'amenities.*' => 'required|integer' + 'amenities.*' => 'required' ], as: [ 'amenities' => 'amenities', - 'amenities.*' => 'amenities', + 'amenities.*' => 'amenity item', ], message: [ 'amenities.required' => 'Amenities are required.', ])] - public $amenities; + public array $amenities = []; // Rates #[Validate('required|numeric|min:1|max:1000|decimal:0,2', as: 'base rate', onUpdate: false)] - public $base_rate; + public ?int $base_rate; #[Validate('required|numeric|min:0|max:99', as: 'tax rate', onUpdate: false)] - public $tax_rate; + public ?int $tax_rate; #[Validate([ - 'fees' => '', + 'fees' => 'nullable|array:name,amount,type', 'fees.*.name' => 'required|string|max:250', 'fees.*.amount' => 'required|numeric|min:0|max:1000|decimal:0,2', - 'fees.*.type' => 'required|', + 'fees.*.type' => 'required|in:fixed,variable', + ], as: [ + 'fees.*.name' => 'fee name', + 'fees.*.amount' => 'fee amount', + 'fees.*.type' => 'fee type', ])] - public array $fees; + public array $fees = []; // Photos - #[Validate('required|', as: '')] - public $selected_photos; + #[Validate([ + 'photos' => 'required', + 'photos.*' => 'required|image|mimes:jpg,jpeg,png,webp,bmp|extensions:jpg,jpeg,png,webp,bmp|max:10240', + ], as: [ + 'photos.' => 'photos', + 'photos.*' => 'photo', + ])] + public array $photos = []; // Options - #[Validate('required|', as: '')] - public $duration_min; + #[Validate('required|string|max:250|unique:properties,slug|regex:^[a-z0-9]+(?:-[a-z0-9]+)*$', as: 'url', onUpdate: false)] + public ?string $slug; - #[Validate('required|', as: '')] - public $duration_max; + #[Validate('required|integer|min:1|max:99', as: 'minimum nights')] + public int $duration_min = 1; - #[Validate('required|', as: '')] - public $slug; + #[Validate('required|integer|min:1|max:99', as: 'maximum nights')] + public int $duration_max = 14; - #[Validate('required|', as: '')] - public $visibility; + #[Validate('required|string|in:private,unlisted,public', as: 'visibility')] + public ?string $visibility; - #[Validate('required|', as: '')] - public $calendar_color; + #[Validate('required|regex:/^#[0-9A-Fa-f]{6}$/', as: 'color')] + public string $calendar_color = "#2563eb"; } diff --git a/app/resources/css/app.css b/app/resources/css/app.css index fe1f621..23f12c0 100644 --- a/app/resources/css/app.css +++ b/app/resources/css/app.css @@ -65,16 +65,16 @@ @apply -page-x-padding -page-y-padding; } .page-x-padding { - @apply px-4 tablet:px-6; + @apply px-4 tablet-lg:px-6; } .-page-x-padding { - @apply -mx-4 tablet:-mx-6; + @apply -mx-4 tablet-lg:-mx-6; } .page-y-padding { - @apply py-4 tablet:py-6; + @apply py-4 tablet-lg:py-6; } .-page-y-padding { - @apply -my-4 tablet:-my-6; + @apply -my-4 tablet-lg:-my-6; } .page-container { @@ -84,7 +84,7 @@ @apply page-padding mb-8 border-b border-gray-300 bg-white; } .page-title { - @apply text-2xl font-bold text-gray-700 tablet:font-bold; + @apply text-2xl font-bold text-gray-700 tablet-lg:font-bold; } .page-desc { @apply mt-2 text-muted; @@ -101,20 +101,20 @@ /* Cards */ /* .card-container { - @apply mx-0 w-full tablet-sm:mx-6; + @apply mx-0 w-full tablet:mx-6; } */ .card { - @apply has-border bg-white tablet-sm:rounded-xl; + @apply has-border bg-white tablet:rounded-xl; } .card-padding { - /* @apply px-6 py-8 tablet-sm:px-8; */ + /* @apply px-6 py-8 tablet:px-8; */ @apply page-padding; } .card-flex { @apply flex flex-col space-y-8; } /* .card-padding-sm { - @apply px-6 py-6 tablet-sm:px-8; + @apply px-6 py-6 tablet:px-8; } */ .card-header { @apply flex flex-col space-y-2; @@ -147,7 +147,7 @@ @apply grid grid-cols-1 gap-x-8 gap-y-4 laptop:grid-cols-3; } /* .form-section-details { - @apply page-x-padding flex flex-col justify-center space-y-0 tablet-sm:p-0; + @apply page-x-padding flex flex-col justify-center space-y-0 tablet:p-0; } .form-section-header { @apply text-lg font-semibold; @@ -193,7 +193,7 @@ } .form-input { @apply w-full border-0 bg-transparent p-0 placeholder:text-muted-light focus-within:placeholder-muted-lighter focus:outline-none focus:ring-0; - /* @apply has-border block w-full rounded-md border-0 bg-gray-100 px-3 py-2 text-lg leading-6 ring-inset placeholder:text-muted-light hover:shadow hover:ring-1 hover:ring-gray-400/60 focus:bg-white focus:placeholder-gray-200 focus:ring-2 focus:ring-inset focus:ring-primary dark:bg-gray-900/70 dark:ring-gray-700 dark:placeholder:text-gray-700 dark:focus:ring-primary tablet-sm:text-base; */ + /* @apply has-border block w-full rounded-md border-0 bg-gray-100 px-3 py-2 text-lg leading-6 ring-inset placeholder:text-muted-light hover:shadow hover:ring-1 hover:ring-gray-400/60 focus:bg-white focus:placeholder-gray-200 focus:ring-2 focus:ring-inset focus:ring-primary dark:bg-gray-900/70 dark:ring-gray-700 dark:placeholder:text-gray-700 dark:focus:ring-primary tablet:text-base; */ } .form-input-error { @apply !ring-2 !ring-red-500; @@ -349,7 +349,7 @@ @apply mx-auto flex max-w-screen-laptop flex-col space-y-10; } .frontend-section { - @apply flex flex-col space-y-5 tablet-sm:p-10; + @apply flex flex-col space-y-5 tablet:p-10; } .frontend-title { @apply text-3xl font-semibold; @@ -357,7 +357,7 @@ /* Properties */ .frontend-property-grid { - @apply grid grid-cols-1 gap-10 tablet-sm:grid-cols-3; + @apply grid grid-cols-1 gap-10 tablet:grid-cols-3; } } @@ -433,4 +433,7 @@ .label-space { @apply !mt-[31px]; } + .color-input > input{ + @apply p-0.5 + } } diff --git a/app/resources/js/_formatter.js b/app/resources/js/_formatter.js deleted file mode 100644 index 57104eb..0000000 --- a/app/resources/js/_formatter.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Formatters / Masks - * Cleave - https://github.com/nosir/cleave.js - */ -import Cleave from "cleave.js"; -function formatPhone(element) { - new Cleave(element, { - phone: true, - delimiter: " ", - phoneRegionCode: "US", - }); -} -function formatDate(element) { - new Cleave(element, { - date: true, - delimiter: "/", - datePattern: ["m", "d", "Y"], - }); -} -function formatZipCode(element) { - new Cleave(element, { - numericOnly: true, - blocks: [5], - rawValueTrimPrefix: true, - }); -} -function formatMoney(element) { - new Cleave(element, { - numeral: true, - numeralPositiveOnly: true, - numeralDecimalMark: ".", - delimiter: ",", - numeralDecimalScale: 2, - rawValueTrimPrefix: true, - }); -} - -document.querySelectorAll('[money="money"]').forEach((element) => { - formatMoney(element); -}); - -// document.querySelectorAll(".phone").forEach((element) => { -// formatPhone(element); -// }); -// document.querySelectorAll(".date").forEach((element) => { -// formatDate(element); -// }); -// document.querySelectorAll(".money").forEach((element) => { -// formatMoney(element); -// }); -// document.querySelectorAll(".zip-code").forEach((element) => { -// formatZipCode(element); -// }); -// window.addEventListener("maskAllElements", (event) => { -// document.querySelectorAll(".phone").forEach((element) => { -// formatPhone(element); -// }); -// document.querySelectorAll(".date").forEach((element) => { -// formatDate(element); -// }); -// document.querySelectorAll(".money").forEach((element) => { -// formatMoney(element); -// }); -// document.querySelectorAll(".zip-code").forEach((element) => { -// formatZipCode(element); -// }); -// }); diff --git a/app/resources/js/_masks.js b/app/resources/js/_masks.js new file mode 100644 index 0000000..3943210 --- /dev/null +++ b/app/resources/js/_masks.js @@ -0,0 +1,17 @@ + +/** + * This mask is to validate a url slug + * + * @param {string} text - the text to mask + * @returns + */ +function slugify(text) { + return text.toString().toLowerCase() + .replace(/\s+/g, '-') // Replace spaces with dashes + .replace(/[^\w\-]+/g, '') // Remove non-word characters + .replace(/\-\-+/g, '-') // Replace multiple dashes with a single dash + .replace(/^-+/, '') // Remove leading dashes + // .replace(/-+$/, ''); // Remove trailing dashes +} + +window.slugify = slugify diff --git a/app/resources/js/_photos.js b/app/resources/js/_photos.js index 79e4069..534e7cb 100644 --- a/app/resources/js/_photos.js +++ b/app/resources/js/_photos.js @@ -7,80 +7,4 @@ Alpine.data("photosuploader", () => ({ photosCount: 0, })); -// import "livewire-sortable"; - import "@nextapps-be/livewire-sortablejs"; - -// Livewire.hook("drag:start", function () { -// console.log("test"); -// }); - -// window.addEventListener("init-sortable", (event) => { -// // initSortablePhotos(); -// setTimeout(function () { -// //your code to be executed after 1 second -// initSortablePhotos(); -// }, 150); -// }); - -/** - * Draggable - v1.1.3 - * https://github.com/Shopify/draggable - */ -// import { Sortable } from "@shopify/draggable"; -// window.Sortable = Sortable; - -// var sortable = false; - -// function initSortablePhotos() { -// const sortableContainer = ".sortable"; -// const containers = document.querySelectorAll(sortableContainer); - -// // If there isn't any photos to sort, don't sort. -// if (containers.length === 0) { -// return false; -// } - -// // If there is an existing sortable instance, destroy it -// if (sortable) { -// sortable.destroy(); -// } - -// // Create the sortable instance -// sortable = new Sortable(containers, { -// draggable: ".sortable--item", -// handle: ".sortable--handle", -// mirror: { -// appendTo: sortableContainer, -// constrainDimensions: true, -// cursorOffsetX: 50, -// cursorOffsetY: 50, -// }, -// classes: { -// mirror: ["mirror", "drop-shadow-xl", "shadow-lg", "rounded-lg"], -// "draggable:over": ["opacity-0"], // Classes added on draggable element you are dragging over -// "source:dragging": ["opacity-20"], // Classes added on the draggable element that has been picked up -// "source:original": ["opacity-0"], // Classes added on the original source element, which is hidden on drag -// }, -// }); - -// sortable.on("sortable:stop", () => { - -// }); - -// // Do not allow users the sort the header photo -// sortable.on("drag:start", (event) => { -// const { sourceContainer } = event; // The sortable container -// const { source } = event; // The element/photo that the user clicked to drag - -// /** -// * Prevent the first photo from initiating a drag -// */ -// const firstPhoto = sourceContainer.children[0]; -// if (source === firstPhoto) { -// event.cancel(); -// } -// }); - -// return sortable; -// } diff --git a/app/resources/js/app.js b/app/resources/js/app.js index 06b9a61..1dfff80 100644 --- a/app/resources/js/app.js +++ b/app/resources/js/app.js @@ -24,6 +24,8 @@ Alpine.plugin(AlpineCollapse); Alpine.plugin(mask) // Alpine.plugin(AlpinePersist); Alpine.plugin(ToastComponent); +// Start Livewire +Livewire.start(); // Dev bar import "./_devbar"; @@ -31,18 +33,19 @@ import "./_devbar"; // Theme Mode import "./_themeMode"; + + + // Photos import "./_photos"; +// Masks +import "./_masks"; -// Start Livewire -Livewire.start(); - +// Custom dispatch event to write to browser console window.addEventListener("console", (event) => { console.log(event.detail); }); -import "./_formatter"; - window.addEventListener( "popstate", (event) => { diff --git a/app/resources/views/components/banner.blade.php b/app/resources/views/components/banner.blade.php index 2647cfd..b8d3b51 100644 --- a/app/resources/views/components/banner.blade.php +++ b/app/resources/views/components/banner.blade.php @@ -13,7 +13,7 @@
{{ $banner['title'] }} - + {!! $banner['description'] !!}
diff --git a/app/resources/views/components/utilities/dev-bar.blade.php b/app/resources/views/components/utilities/dev-bar.blade.php index 4ed0453..395f9ec 100644 --- a/app/resources/views/components/utilities/dev-bar.blade.php +++ b/app/resources/views/components/utilities/dev-bar.blade.php @@ -1,33 +1,33 @@ @env('local') -
+
-
-
-
+
+
{{-- Logo --}} -
+ @@ -33,13 +33,13 @@ @persist('profile-dropdown')
-
+ {{-- Container --}} -
+
{{-- Mobile Sidebar Overlay --}} -
+
{{-- Sidebar --}} -