Feature: Create Event - First Step Frontend #17

Merged
igorpropisnov merged 20 commits from feature/create-event into main 2024-08-22 14:58:36 +02:00
4 changed files with 69 additions and 36 deletions
Showing only changes of commit 584f34f947 - Show all commits

View File

@ -1,5 +1,5 @@
<div class="flex flex-col h-full"> <div class="flex flex-col h-full">
<div class="w-full bg-neutral max-w-full sticky top-0 z-20 pt-2"> <div class="w-full bg-base-100 max-w-full sticky top-0 z-10 pt-4">
<ul class="steps steps-horizontal w-full py-2"> <ul class="steps steps-horizontal w-full py-2">
@for (step of steps; track $index) { @for (step of steps; track $index) {
<li <li
@ -30,34 +30,38 @@
</div> </div>
<div <div
class="w-full bg-neutral max-w-full sticky bottom-0 z-20 px-4 sm:px-8 py-4"> class="w-full bg-base-100 max-w-full sticky bottom-0 z-10 px-4 sm:px-8 py-4">
<div class="flex justify-between max-w-4xl mx-auto"> <div class="flex justify-between max-w-4xl mx-auto">
<div>
@if (currentStep() > 0) {
<button <button
type="button" type="button"
class="btn btn-primary" class="btn btn-primary btn-outline"
(click)="prevStep()" (click)="prevStep()"
[disabled]="currentStep() === 0" [disabled]="currentStep() === 0"
[class.opacity-50]="currentStep() === 0"> [class.opacity-50]="currentStep() === 0">
@if (currentStep() > 0) {
<span> <span>
Back to Back to
<span class="font-bold">{{ steps[currentStep() - 1] }}</span> <span class="font-bold">{{ steps[currentStep() - 1] }}</span>
</span> </span>
}
</button> </button>
}
</div>
<div>
@if (currentStep() < steps.length - 1) {
<button <button
type="button" type="button"
class="btn btn-primary" class="btn btn-primary btn-outline"
(click)="nextStep()" (click)="nextStep()"
[disabled]="currentStep() === steps.length - 1" [disabled]="currentStep() === steps.length - 1"
[class.opacity-50]="currentStep() === steps.length - 1"> [class.opacity-50]="currentStep() === steps.length - 1">
@if (currentStep() < steps.length - 1) {
<span> <span>
Next to Next to
<span class="font-bold">{{ steps[currentStep() + 1] }}</span> <span class="font-bold">{{ steps[currentStep() + 1] }}</span>
</span> </span>
}
</button> </button>
}
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -65,10 +65,6 @@
<span class="label-text-alt"></span> <span class="label-text-alt"></span>
</div> </div>
</label> </label>
<div>
<pre>{{ form().value | json }}</pre>
</div>
</div> </div>
</form> </form>

View File

@ -24,7 +24,8 @@
viewBox="0 0 24 24" viewBox="0 0 24 24"
stroke-width="1.5" stroke-width="1.5"
stroke="currentColor" stroke="currentColor"
class="size-6" class="size-6 cursor-pointer"
(click)="toggleDropdown()"
[class.rotate-180]="showDropdown()"> [class.rotate-180]="showDropdown()">
<path <path
stroke-linecap="round" stroke-linecap="round"
@ -34,6 +35,8 @@
</label> </label>
@if (showDropdown()) { @if (showDropdown()) {
<ul <ul
(mouseenter)="onDropdownMouseEnter()"
(mouseleave)="onDropdownMouseLeave()"
class="menu bg-base-100 w-full mt-1 shadow-lg rounded-box absolute top-full left-0 z-10"> class="menu bg-base-100 w-full mt-1 shadow-lg rounded-box absolute top-full left-0 z-10">
@if (filteredItems().length > 0) { @if (filteredItems().length > 0) {
@for (item of filteredItems(); track item) { @for (item of filteredItems(); track item) {
@ -61,7 +64,7 @@
</svg> </svg>
} @else { } @else {
<div <div
class="tooltip tooltip-info" class="tooltip tooltip-primary tooltip-left"
data-tip="Edit this location's details. You can modify the name, address, or any other relevant information associated with this place."> data-tip="Edit this location's details. You can modify the name, address, or any other relevant information associated with this place.">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"

View File

@ -1,7 +1,9 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { import {
Component, Component,
ElementRef,
forwardRef, forwardRef,
HostListener,
input, input,
InputSignal, InputSignal,
output, output,
@ -57,6 +59,16 @@ export class DropdownComponent implements ControlValueAccessor, Validator {
public itemSelected: OutputEmitterRef<string> = output<string>(); public itemSelected: OutputEmitterRef<string> = output<string>();
public submitNewItems: OutputEmitterRef<boolean> = output<boolean>(); public submitNewItems: OutputEmitterRef<boolean> = output<boolean>();
public itemEdit: OutputEmitterRef<string> = output<string>(); public itemEdit: OutputEmitterRef<string> = output<string>();
private isMouseInDropdown: WritableSignal<boolean> = signal<boolean>(false);
public constructor(private readonly elementRef: ElementRef) {}
@HostListener('document:click', ['$event'])
public onDocumentClick(event: MouseEvent): void {
if (!this.elementRef.nativeElement.contains(event.target)) {
this.closeDropdown();
}
}
public writeValue(value: string | null): void { public writeValue(value: string | null): void {
if (value && this.isValidOption(value)) { if (value && this.isValidOption(value)) {
@ -88,6 +100,23 @@ export class DropdownComponent implements ControlValueAccessor, Validator {
return null; return null;
} }
public onDropdownMouseEnter(): void {
this.isMouseInDropdown.set(true);
}
public onDropdownMouseLeave(): void {
this.isMouseInDropdown.set(false);
}
public closeDropdown(): void {
this.showDropdown.set(false);
this.isMouseInDropdown.set(false);
}
public toggleDropdown(): void {
this.showDropdown.set(!this.showDropdown());
}
public onInput(event: Event): void { public onInput(event: Event): void {
const value = (event.target as HTMLInputElement).value; const value = (event.target as HTMLInputElement).value;
@ -113,7 +142,8 @@ export class DropdownComponent implements ControlValueAccessor, Validator {
this.itemSelected.emit(''); this.itemSelected.emit('');
} }
this.showDropdown.set(true); this.showDropdown.set(matchingItems.length > 0 || value.trim() !== '');
this.onTouched(); this.onTouched();
} }
@ -142,7 +172,7 @@ export class DropdownComponent implements ControlValueAccessor, Validator {
if (this.isValidOption(item)) { if (this.isValidOption(item)) {
this.searchTerm.set(item); this.searchTerm.set(item);
this.selectedItem.set(item); this.selectedItem.set(item);
this.showDropdown.set(false); this.closeDropdown();
this.itemSelected.emit(item); this.itemSelected.emit(item);
this.onChange(item); this.onChange(item);
this.onTouched(); this.onTouched();
@ -150,6 +180,7 @@ export class DropdownComponent implements ControlValueAccessor, Validator {
} }
public submitNewItem(): void { public submitNewItem(): void {
this.closeDropdown();
this.submitNewItems.emit(true); this.submitNewItems.emit(true);
} }
@ -161,15 +192,14 @@ export class DropdownComponent implements ControlValueAccessor, Validator {
} }
public onFocus(): void { public onFocus(): void {
this.showDropdown.set(true);
this.filteredItems.set(this.items()); this.filteredItems.set(this.items());
} }
public onBlur(): void { public onBlur(): void {
setTimeout(() => { if (!this.isMouseInDropdown) {
this.showDropdown.set(false); this.closeDropdown();
this.onTouched(); this.onTouched();
}, 100); }
} }
private isValidOption(value: string): boolean { private isValidOption(value: string): boolean {