[TASK] add overlays sidebar
This commit is contained in:
parent
5f82b8a786
commit
abb82ceb5a
47
frontend/js/sidebar.ts
Normal file
47
frontend/js/sidebar.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
export class Sidebar {
|
||||||
|
element: HTMLElement | null;
|
||||||
|
trigger: string;
|
||||||
|
contentWrapper: HTMLElement| null;
|
||||||
|
closeBtn: any;
|
||||||
|
overlay: HTMLElement| null;
|
||||||
|
isOpen: boolean;
|
||||||
|
|
||||||
|
constructor(trigger: string) {
|
||||||
|
this.trigger = trigger;
|
||||||
|
this.element = document.getElementById(trigger);
|
||||||
|
this.contentWrapper = document.querySelector('body');
|
||||||
|
this.overlay = document.querySelector('.sidebar-overlay[data-trigger='+ this.trigger + ']');
|
||||||
|
if(this.element) {
|
||||||
|
this.closeBtn = this.element.querySelector('[data-trigger='+ this.trigger + ']');
|
||||||
|
}
|
||||||
|
this.isOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkStatus() {
|
||||||
|
return this.isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle() {
|
||||||
|
this.isOpen = !this.isOpen;
|
||||||
|
if(this.trigger) {
|
||||||
|
document.getElementById(this.trigger)?.classList.toggle('open');
|
||||||
|
}
|
||||||
|
if( this.contentWrapper) {
|
||||||
|
this.contentWrapper.classList.toggle('overlay');
|
||||||
|
}
|
||||||
|
if(this.overlay) {
|
||||||
|
this.overlay.classList.toggle('show');
|
||||||
|
}
|
||||||
|
if(this.element) {
|
||||||
|
this.element.ariaModal = (this.element.ariaModal === 'true') ? 'false' : 'true';
|
||||||
|
if(this.isOpen){
|
||||||
|
const focusElement= this.element.querySelector('.focus-js') as HTMLElement | null;
|
||||||
|
if(focusElement) {
|
||||||
|
focusElement.focus();
|
||||||
|
} else {
|
||||||
|
this.closeBtn.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
|
import { Sidebar } from './js/sidebar';
|
||||||
import './scss/app.scss'
|
import './scss/app.scss'
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
console.log("init");
|
|
||||||
initSearch();
|
initSearch();
|
||||||
|
initSidebar();
|
||||||
});
|
});
|
||||||
|
|
||||||
function initSearch() {
|
function initSearch() {
|
||||||
@ -40,3 +41,20 @@ function filterElements(input: string) {
|
|||||||
resultWrapper.innerHTML = (amountShownElements === 0 ? 'Kein Ergebnis gefunden' : '<strong>' + amountShownElements + '</strong>' + (amountShownElements > 1 ? ' Ergebnisse' : ' Ergebnis') + ' gefunden');
|
resultWrapper.innerHTML = (amountShownElements === 0 ? 'Kein Ergebnis gefunden' : '<strong>' + amountShownElements + '</strong>' + (amountShownElements > 1 ? ' Ergebnisse' : ' Ergebnis') + ' gefunden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initSidebar() {
|
||||||
|
const sidebarTrigger = <NodeListOf<HTMLElement>>document.querySelectorAll('[data-trigger]');
|
||||||
|
|
||||||
|
if(sidebarTrigger) {
|
||||||
|
Array.prototype.forEach.call(sidebarTrigger, (triggerElement: HTMLElement) => {
|
||||||
|
if(triggerElement.dataset.trigger) {
|
||||||
|
const sidebar = new Sidebar(triggerElement.dataset.trigger);
|
||||||
|
|
||||||
|
triggerElement.addEventListener('click', () => {
|
||||||
|
sidebar.toggle();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,3 +1,87 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
/* purgecss start ignore */
|
||||||
|
.sidebar {
|
||||||
|
position: fixed;
|
||||||
|
overflow-y: scroll;
|
||||||
|
top: 0;
|
||||||
|
background: white;
|
||||||
|
z-index: 2000;
|
||||||
|
width: 0;
|
||||||
|
box-shadow: 0 1rem 3rem rgba(0,0,0,.175);
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
background-color: rgba(255, 255, 255, 100%);
|
||||||
|
display: block;
|
||||||
|
height: 100vh;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 375px;
|
||||||
|
z-index: 40000;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.slide-in {
|
||||||
|
transition-duration: 75ms;
|
||||||
|
transition-property: all;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.from-right {
|
||||||
|
right: -24rem;
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.from-left {
|
||||||
|
left: -24rem;
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-overlay {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 1025;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-close {
|
||||||
|
border-radius: 100%;
|
||||||
|
width: 27.5px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
background: white !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-footer {
|
||||||
|
position: fixed;
|
||||||
|
margin: 0 -8px -4px;
|
||||||
|
width: 374px;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-header {
|
||||||
|
position: fixed;
|
||||||
|
width: 375px;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* purgecss end ignore */
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
{% extends "base" %}
|
{% extends "base" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="max-w-screen-lg w-full grid gap-4">
|
<div class="max-w-screen-lg w-full grid sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
{% if flash %}
|
{% if flash %}
|
||||||
{% if flash.0 == "success" %}
|
{% if flash.0 == "success" %}
|
||||||
<div class="bg-[#4ade80] text-white px-3 py-1 rounded-md text-center">
|
<div class="sm:col-span-2 lg:col-span-3 bg-[#4ade80] text-white px-3 py-1 rounded-md text-center">
|
||||||
{{ flash.1 }}
|
{{ flash.1 }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if flash.0 == "error" %}
|
{% if flash.0 == "error" %}
|
||||||
<div class="bg-[#f43f5e] text-white px-3 py-1 rounded-md text-center">
|
<div class="sm:col-span-2 lg:col-span-3 bg-[#f43f5e] text-white px-3 py-1 rounded-md text-center">
|
||||||
{{ flash.1 }}
|
{{ flash.1 }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h1 class="text-center text-3xl uppercase tracking-wide font-bold text-primary-900">Ausfahrten</h1>
|
<h1 class="text-center text-3xl uppercase tracking-wide font-bold text-primary-900 sm:col-span-2 lg:col-span-3">Ausfahrten</h1>
|
||||||
|
|
||||||
{% for day in days %}
|
{% for day in days %}
|
||||||
<div class="bg-white p-3 rounded-md">
|
<div class="bg-white p-3 rounded-md">
|
||||||
<h2 class="text-md font-bold mb-2 uppercase tracking-wide">{{ day.day| date(format="%d.%m.%Y") }}</h2>
|
<h2 class="mb-2 text-md font-bold uppercase tracking-wide">{{ day.day| date(format="%d.%m.%Y") }}</h2>
|
||||||
|
|
||||||
{% for planned_event in day.planned_events %}
|
{% for planned_event in day.planned_events %}
|
||||||
<h3>Planned event '{{ planned_event.name }}'</h3>
|
<h3>Planned event '{{ planned_event.name }}'</h3>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
{% for cox in planned_event.cox %}
|
{% for cox in planned_event.cox %}
|
||||||
{{ cox }}
|
{{ cox }}
|
||||||
{% if cox == loggedin_user.name %}
|
{% if cox == loggedin_user.name %}
|
||||||
<a href="/cox/remove/{{ planned_event.id }}">ABMELDEN</a>
|
<a href="/cox/remove/{{ planned_event.id }}" class="rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer">ABMELDEN</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<br />
|
<br />
|
||||||
@ -41,45 +41,88 @@
|
|||||||
{% for rower in planned_event.rower%}
|
{% for rower in planned_event.rower%}
|
||||||
{{ rower.name }} (angemeldet seit {{ rower.registered_at }})
|
{{ rower.name }} (angemeldet seit {{ rower.registered_at }})
|
||||||
{% if rower.name == loggedin_user.name %}
|
{% if rower.name == loggedin_user.name %}
|
||||||
<a href="/remove/{{ planned_event.trip_details_id }}">ABMELDEN</a>
|
<a href="/remove/{{ planned_event.trip_details_id }}" class="rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer">ABMELDEN</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if planned_event.max_people > planned_event.rower | length %}
|
{% if planned_event.max_people > planned_event.rower | length %}
|
||||||
<a href="/join/{{ planned_event.trip_details_id }}">MITRUDERN</a>
|
<a href="/join/{{ planned_event.trip_details_id }}" class="rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer">MITRUDERN</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
{% if loggedin_user.is_cox %}
|
{% if loggedin_user.is_cox %}
|
||||||
<a href="/cox/join/{{ planned_event.id }}">STEUERN</a>
|
<a href="/cox/join/{{ planned_event.id }}" class="rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer">STEUERN</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if loggedin_user.is_admin %}
|
{% if loggedin_user.is_admin %}
|
||||||
<a href="/admin/planned-event/{{ planned_event.id }}/delete">DELETE</a>
|
<a href="/admin/planned-event/{{ planned_event.id }}/delete" class="rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer">DELETE</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if day.trips | length > 0 %}
|
||||||
|
<div class="grid grid-cols-1 gap-3 divide-y mb-3">
|
||||||
{% for trip in day.trips %}
|
{% for trip in day.trips %}
|
||||||
<h3>Ausfahrt von {{ trip.cox_name }}</h3>
|
<div>
|
||||||
Planned starting time: {{ trip.planned_starting_time }}<br />
|
<div class="flex justify-between">
|
||||||
Max people: {{ trip.max_people }}<br />
|
<div><strong class="text-primary-900">{{ trip.planned_starting_time }} Uhr</strong> <small class="text-gray-600">({{ trip.cox_name }})</small></div>
|
||||||
Notes: {{ trip.notes }}<br />
|
<a href="#" data-sidebar="true" data-trigger="detailTrip{{ trip.trip_details_id }}" class="inline-block text-primary-600 hover:text-primary-900 underline mr-3">Details</a>
|
||||||
Folgende Ruderer haben sich schon angemeldet:
|
</div>
|
||||||
{% for rower in trip.rower %}
|
|
||||||
{{ rower.name }} (angemeldet seit {{ rower.registered_at }})
|
|
||||||
{% if rower.name == loggedin_user.name %}
|
|
||||||
<a href="/remove/{{ trip.trip_details_id }}">ABMELDEN</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% if trip.max_people > trip.rower | length and trip.cox_id != loggedin_user.id %}
|
{% if trip.max_people > trip.rower | length and trip.cox_id != loggedin_user.id %}
|
||||||
<a href="/join/{{ trip.trip_details_id }}">MITRUDERN</a>
|
<a href="/join/{{ trip.trip_details_id }}" class="inline-block mt-1 rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer">MITRUDERN</a>
|
||||||
|
{% endif %}
|
||||||
|
{% for rower in trip.rower %}
|
||||||
|
{% if rower.name == loggedin_user.name %}
|
||||||
|
<a href="/remove/{{ trip.trip_details_id }}" class="inline-block mt-1 rounded-md bg-[#f43f5e] px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer">ABMELDEN</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="sidebar slide-in from-right" id="detailTrip{{ trip.trip_details_id }}" aria-modal="false">
|
||||||
|
<div class="bg-primary-900 text-white px-2 py-3 flex justify-between sidebar-header">
|
||||||
|
<div class="ps-1">
|
||||||
|
<strong>{{ trip.planned_starting_time }} Uhr</strong> ({{ trip.cox_name }})
|
||||||
|
{% if trip.notes %}
|
||||||
|
<small class="block">{{ trip.notes }}</small>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button type="button" title="Details schließen" class="sidebar-close border-0 bg-primary-600 text-black" data-trigger="detailTrip{{ trip.trip_details_id }}">
|
||||||
|
x
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="px-2 pt-2" style="margin-top: 63px; margin-bottom: 157px">
|
||||||
|
<div class="text-primay-900 bg-primary-100 text-center p-1 mt-1">{{ trip.max_people }} Ruderer können sich für diese Ausfahrt anmelden</div>
|
||||||
|
|
||||||
|
{% if trip.rower | length > 0 %}
|
||||||
|
<div class="mt-2">
|
||||||
|
<div class="font-bold">Anmeldungen:</div>
|
||||||
|
{% for rower in trip.rower %}
|
||||||
|
{{ rower.name }} <span class="hidden">(angemeldet seit {{ rower.registered_at }})</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-overlay" data-trigger="detailTrip{{ trip.trip_details_id }}"></div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if loggedin_user.is_admin %}
|
{% if loggedin_user.is_admin %}
|
||||||
<h3>Add planned event</h3>
|
<a href="#" data-sidebar="true" data-trigger="plannedTrip{{ loop.index }}" class="inline-block text-primary-600 hover:text-primary-900 underline mr-3">Event hinzufügen</a>
|
||||||
|
|
||||||
|
<div class="sidebar slide-in from-right" id="plannedTrip{{ loop.index }}" aria-modal="false">
|
||||||
|
<div class="bg-primary-900 text-white px-2 py-3 flex justify-between sidebar-header">
|
||||||
|
<div>
|
||||||
|
<span class="ps-1">
|
||||||
|
Event
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button type="button" title="Add planned event schließen" class="sidebar-close border-0 bg-primary-600 text-black" data-trigger="plannedTrip{{ loop.index }}">
|
||||||
|
x
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="px-2 pt-2" style="margin-top: 63px; margin-bottom: 157px">
|
||||||
<form action="/admin/planned-event" method="post">
|
<form action="/admin/planned-event" method="post">
|
||||||
<input type="hidden" name="day" value="{{ day.day }}" />
|
<input type="hidden" name="day" value="{{ day.day }}" />
|
||||||
<input type="text" name="name" placeholder="name (e.g. USI)" />
|
<input type="text" name="name" placeholder="name (e.g. USI)" />
|
||||||
@ -91,10 +134,26 @@
|
|||||||
|
|
||||||
<input value="Anlegen" class="w-28 rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer" type="submit" />
|
<input value="Anlegen" class="w-28 rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer" type="submit" />
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-overlay" data-trigger="plannedTrip{{ loop.index }}"></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if loggedin_user.is_cox%}
|
{% if loggedin_user.is_cox%}
|
||||||
<h3>Add trip</h3>
|
<a href="#" data-sidebar="true" data-trigger="trip{{ loop.index }}" class="inline-block text-primary-600 hover:text-primary-900 underline">Ausfahrt hinzufügen</a>
|
||||||
|
|
||||||
|
<div class="sidebar slide-in from-right" id="trip{{ loop.index }}" aria-modal="false">
|
||||||
|
<div class="bg-primary-900 text-white px-2 py-3 flex justify-between sidebar-header">
|
||||||
|
<div>
|
||||||
|
<span class="ps-1">
|
||||||
|
Ausfahrt
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button type="button" title="Add trip schließen" class="sidebar-close border-0 bg-primary-600 text-black" data-trigger="trip{{ loop.index }}">
|
||||||
|
x
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="px-2 pt-2" style="margin-top: 63px; margin-bottom: 157px">
|
||||||
<form action="/cox/trip" method="post">
|
<form action="/cox/trip" method="post">
|
||||||
<input type="hidden" name="day" value="{{ day.day }}" />
|
<input type="hidden" name="day" value="{{ day.day }}" />
|
||||||
<input type="text" name="planned_starting_time" placeholder="Startzeit" />
|
<input type="text" name="planned_starting_time" placeholder="Startzeit" />
|
||||||
@ -103,6 +162,9 @@
|
|||||||
|
|
||||||
<input value="Anlegen" class="w-28 rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer" type="submit" />
|
<input value="Anlegen" class="w-28 rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer" type="submit" />
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-overlay" data-trigger="trip{{ loop.index }}"></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user