generated from JustScreaMy/ProjectTemplate
responsibility
This commit is contained in:
parent
2c64e447bc
commit
100daca85a
17 changed files with 205 additions and 280 deletions
13
TODO
13
TODO
|
@ -1,13 +0,0 @@
|
|||
Nastylovat:
|
||||
- lazyload načítat o něco dříve (neli zrušit alespoň mimo galerii)
|
||||
- mobilní verze
|
||||
|
||||
Frontend:
|
||||
- přidat v galerii zvětsovač na obrázky
|
||||
- notyfi
|
||||
|
||||
Naplánovat:
|
||||
- kurzy + cena: vyskakovací okno na rezervaci s jménem lekce? jak to vyřešit s kalendářem? (stránka /rezervace)
|
||||
|
||||
Backend:
|
||||
- přidat posílání mailu panu vrchnímu
|
|
@ -20,6 +20,9 @@ env = environ.Env()
|
|||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
MEDIA_URL = '/media/'
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
||||
|
@ -162,9 +165,6 @@ STATIC_URL = '/static/'
|
|||
# os.path.join(BASE_DIR, 'static')
|
||||
# ]
|
||||
|
||||
MEDIA_URL = '/media/'
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
|
||||
|
|
|
@ -19,7 +19,7 @@ class ArticleImageSerializer(serializers.ModelSerializer):
|
|||
|
||||
@staticmethod
|
||||
def get_title(obj):
|
||||
return obj.article.title
|
||||
return obj.article.title if obj.article else ''
|
||||
|
||||
|
||||
class ArticleListSerializer(serializers.ModelSerializer):
|
||||
|
@ -38,7 +38,8 @@ class ArticleListSerializer(serializers.ModelSerializer):
|
|||
@staticmethod
|
||||
def get_image(obj):
|
||||
main_image = obj.images.order_by("main").first()
|
||||
return main_image.image.url if main_image else None
|
||||
url = 'http://localhost:8000'
|
||||
return f"{url}{main_image.image.url}" if main_image else None
|
||||
|
||||
|
||||
class EventListSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -4,6 +4,7 @@ from django.db.models import Q
|
|||
from post_office import mail
|
||||
|
||||
from rest_framework.generics import ListAPIView, CreateAPIView
|
||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||
from rest_framework.response import Response
|
||||
|
||||
from tko.models import Article, Event, ArticleImage
|
||||
|
@ -49,6 +50,7 @@ class AllArticleListView(ListAPIView):
|
|||
|
||||
|
||||
class GalleryView(ListAPIView):
|
||||
permission=[AllowAny]
|
||||
queryset = ArticleImage.objects.all().order_by("-article_id", "main")
|
||||
serializer_class = ArticleImageSerializer
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 3rem;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
|
@ -16,15 +15,14 @@ h1 {
|
|||
}
|
||||
|
||||
h2 {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 1.5rem;
|
||||
color: #CF3476;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 1.5rem;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
|
@ -32,7 +30,6 @@ h3 {
|
|||
}
|
||||
|
||||
h4 {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 1rem;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
|
@ -40,7 +37,6 @@ h4 {
|
|||
}
|
||||
|
||||
h5 {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 1rem;
|
||||
color: #aaa;
|
||||
margin-top: 1rem;
|
||||
|
@ -48,7 +44,7 @@ h5 {
|
|||
|
||||
@media (max-width: 600px) {
|
||||
h1 {
|
||||
font-size: 2rem; /* Smaller size for mobile */
|
||||
font-size: 1.8rem; /* Smaller size for mobile */
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
|
@ -61,6 +57,7 @@ h5 {
|
|||
min-width: 25rem;
|
||||
margin-left: calc(20% - 2.5rem);
|
||||
margin-right: calc(20% - 2.5rem);
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.app__logo {
|
||||
|
@ -69,30 +66,25 @@ h5 {
|
|||
}
|
||||
|
||||
.app__title {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 2rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.app__tab {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 2rem;
|
||||
color: #CF3476;
|
||||
}
|
||||
|
||||
.to_left {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.to_right {
|
||||
font-family: 'Futura', sans-serif;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.contact {
|
||||
margin: 20px calc(20% - 40px) 50px;
|
||||
min-width: 25rem;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
@ -102,12 +94,10 @@ h5 {
|
|||
font-size: 3rem;
|
||||
color: #333;
|
||||
margin-bottom: 1rem;
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.contact__dialog__title {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 2rem;
|
||||
color: #333;
|
||||
margin-bottom: 1rem;
|
||||
|
@ -121,6 +111,16 @@ h5 {
|
|||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.contact__title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.contact {
|
||||
min-width: unset;
|
||||
margin: 10px;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.v-dialog > .v-card {
|
||||
border-radius: 0 !important;
|
||||
height: 100vh;
|
||||
|
@ -134,61 +134,47 @@ h5 {
|
|||
}
|
||||
|
||||
.articles {
|
||||
margin-left: calc(20% - 2.5rem);
|
||||
margin-right: calc(20% - 2.5rem);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.article {
|
||||
padding: 10px;
|
||||
padding: 1rem;
|
||||
min-width: 40%;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 0 rgba(0, 0, 0, 0);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.article__image {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.carousel__image img {
|
||||
border-radius: 0.5rem;
|
||||
object-fit: contain !important;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.article__title {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 1.5rem;
|
||||
font-size: 1.4rem;
|
||||
color: #CF3476;
|
||||
text-align: left;
|
||||
margin-top: 0.1rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.article__date {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 0.8rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.article__text {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 1rem;
|
||||
text-align: left;
|
||||
min-height: 6rem;
|
||||
color: #666;
|
||||
color: #333;
|
||||
line-height: 1.5;
|
||||
padding: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.article__sign {
|
||||
font-family: 'Futura', sans-serif;
|
||||
text-align: right;
|
||||
font-size: 1rem;
|
||||
float: right;
|
||||
padding-right: 1rem;
|
||||
color: #333;
|
||||
font-style: italic;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.show_more {
|
||||
font-family: 'Futura', sans-serif;
|
||||
text-align: center;
|
||||
color: #CF3476;
|
||||
background: transparent;
|
||||
|
@ -243,7 +229,6 @@ h5 {
|
|||
}
|
||||
|
||||
.pricing__price {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 3rem;
|
||||
font-weight: bold;
|
||||
color: #CF3476;
|
||||
|
@ -251,9 +236,9 @@ h5 {
|
|||
}
|
||||
|
||||
.pricing__subtitle {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 1rem;
|
||||
color: #555;
|
||||
word-break: break-word;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
|
@ -262,9 +247,12 @@ h5 {
|
|||
min-width: 100%;
|
||||
}
|
||||
|
||||
.pricing-title,
|
||||
.pricing-title {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.pricing-desc {
|
||||
min-height: unset; /* Removes forced height to prevent breakage */
|
||||
min-height: unset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,7 +286,6 @@ h5 {
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Mobile Styles */
|
||||
@media (max-width: 600px) {
|
||||
.trainers__parallax {
|
||||
max-height: 30rem;
|
||||
|
@ -326,7 +313,6 @@ h5 {
|
|||
}
|
||||
|
||||
.advantage__title {
|
||||
font-family: 'Futura', sans-serif;
|
||||
padding: 0.5rem 0;
|
||||
color: #CF3476;
|
||||
font-size: 1.5rem;
|
||||
|
@ -335,7 +321,6 @@ h5 {
|
|||
}
|
||||
|
||||
.advantage__text {
|
||||
font-family: 'Futura', sans-serif;
|
||||
padding-bottom: 1rem;
|
||||
font-size: 1rem;
|
||||
color: #333;
|
||||
|
@ -362,7 +347,7 @@ h5 {
|
|||
.about {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
height: 100%;
|
||||
height: auto;
|
||||
max-width: 80%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
|
@ -370,7 +355,7 @@ h5 {
|
|||
}
|
||||
|
||||
.about__parallax {
|
||||
max-height: 30rem;
|
||||
max-height: 28rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
|
@ -381,57 +366,55 @@ h5 {
|
|||
|
||||
@media (max-width: 600px) {
|
||||
.history__parallax {
|
||||
max-height: 45rem;
|
||||
max-height: 58rem;
|
||||
}
|
||||
}
|
||||
|
||||
.about__title {
|
||||
font-family: 'Futura', sans-serif;
|
||||
font-size: 3rem;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
display: block;
|
||||
font-size: 2.5rem;
|
||||
color: #fff;
|
||||
margin-top: 1rem;
|
||||
font-weight: bold;
|
||||
word-break: break-word;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.about__subtitle {
|
||||
font-family: 'Futura', sans-serif;
|
||||
color: #FF3D8C;
|
||||
font-size: 1.3rem;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 1rem;
|
||||
word-break: break-word;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.about__text {
|
||||
font-family: 'Futura', sans-serif;
|
||||
color: #ddd;
|
||||
font-size: 1rem;
|
||||
text-align: center;
|
||||
font-size: 1.125rem;
|
||||
padding: 0 1rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.about {
|
||||
max-width: 100%;
|
||||
max-width: 95%;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.about__parallax {
|
||||
min-height: 32rem;
|
||||
}
|
||||
|
||||
.about__title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.about__subtitle {
|
||||
font-size: 1rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.about__text {
|
||||
font-size: 1rem;
|
||||
padding: 0 10px;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
<v-container id="about">
|
||||
<v-card class="about">
|
||||
<v-card-title class="about__title">Vítejte v tanečním klubu!</v-card-title>
|
||||
<v-card-subtitle class="about__subtitle">Vítejte na webu Tanečního klubu Ostrava!</v-card-subtitle>
|
||||
<v-card-subtitle class="about__subtitle">Objevte kouzlo tance s námi!</v-card-subtitle>
|
||||
<v-card-text class="about__text">
|
||||
Objevte kouzlo tance s námi! Ať už jste začátečník nebo zkušený tanečník, v našem klubu najdete místo, kde se můžete rozvíjet, bavit a sdílet svou vášeň pro pohyb. Nabízíme kurzy pro všechny věkové kategorie, od společenských tanců po moderní styly.
|
||||
Ať už jste začátečník nebo zkušený tanečník, v našem klubu najdete místo, kde se můžete rozvíjet, bavit a sdílet svou vášeň pro pohyb. Nabízíme kurzy pro všechny věkové kategorie, od společenských tanců po moderní styly.
|
||||
<br><br>
|
||||
Přidejte se k nám a nechte tanec proměnit váš život! 💃🕺
|
||||
<br><br>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<h1>Přínosy tance: Více než jen pohyb</h1>
|
||||
<h2>Tancem k lepšímu životu</h2>
|
||||
<h1>Přínosy tance</h1>
|
||||
<h2>Více než jen pohyb</h2>
|
||||
<v-card
|
||||
v-for="advantage in advantages"
|
||||
:key="advantage.id"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<v-card class="contact">
|
||||
<v-card class="contact pa-4">
|
||||
<v-card-title class="contact__title">Kontaktujte nás!</v-card-title>
|
||||
<dialog-contact-form />
|
||||
<lazy-dialog-contact-form />
|
||||
</v-card>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
<v-card class="pricing-box" @click="openDialog = true; chosenCourse = course">
|
||||
<div class="pricing-content">
|
||||
<h3 class="pricing-title">{{ course.name }}</h3>
|
||||
<v-card-subtitle>
|
||||
<v-card-subtitle v-if="course.time">
|
||||
<div class="pricing__subtitle">{{ course.time }}</div>
|
||||
</v-card-subtitle>
|
||||
<v-card-title>
|
||||
<v-card-title v-if="course.price">
|
||||
<div class="pricing__price">{{ course.price }}</div>
|
||||
</v-card-title>
|
||||
<v-card-text v-if="course.desc">
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
md="6"
|
||||
>
|
||||
<v-card class="article">
|
||||
<v-row class="article__title">{{ article.title }}</v-row>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-img
|
||||
:lazy-src="article.image"
|
||||
:src="article.image"
|
||||
aspect-ratio="1"
|
||||
cover
|
||||
class="article__image"
|
||||
@click="showCarousel = true"
|
||||
>
|
||||
|
@ -38,17 +38,16 @@
|
|||
cols="12"
|
||||
md="8"
|
||||
>
|
||||
<v-row class="article__title">{{ article.title }}</v-row>
|
||||
<v-row class="article__date">{{ article.date}}</v-row>
|
||||
|
||||
<v-row class="article__text">{{ article.content }}</v-row>
|
||||
<v-row class="article__sign">{{ article.author }}</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row class="article__sign">Dne {{ article.date}}, {{ article.author }}</v-row>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-btn to="/aktuality" class="show_more">
|
||||
<v-icon icon="mdi-chevron-down"/>Dalsí aktuality<v-icon icon="mdi-chevron-down"/>
|
||||
<v-btn to="/aktuality" class="show_more" v-if="!props.forAll">
|
||||
<v-icon icon="mdi-chevron-down"/>Další aktuality<v-icon icon="mdi-chevron-down"/>
|
||||
</v-btn>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
@ -57,6 +56,10 @@ import { useAPI } from "~/composables/useAPI";
|
|||
|
||||
const showCarousel = ref(false);
|
||||
|
||||
const props = defineProps<{
|
||||
forAll: boolean
|
||||
}>();
|
||||
|
||||
interface ArticleImage {
|
||||
image: string;
|
||||
}
|
||||
|
@ -73,7 +76,9 @@ interface Article {
|
|||
|
||||
const articles = ref<Article[]>([]);
|
||||
|
||||
const { error, data } = await useAPI<Article[]>('load-articles/', {method: "GET"});
|
||||
const endpoint = props.forAll ? 'load-all-articles/' : 'load-articles/';
|
||||
|
||||
const { error, data } = await useAPI<Article[]>(endpoint, {method: "GET"});
|
||||
|
||||
if ( data.value ){
|
||||
articles.value = data.value;
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
<template>
|
||||
<v-form v-model="valid">
|
||||
<v-snackbar
|
||||
v-model="showSnackbar"
|
||||
:color="snackbarColor"
|
||||
:timeout="5000"
|
||||
>
|
||||
{{ snackbarMessage }}
|
||||
</v-snackbar>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col
|
||||
|
@ -7,7 +14,11 @@
|
|||
md="4"
|
||||
>
|
||||
<v-text-field
|
||||
dense
|
||||
hide-details="auto"
|
||||
v-model="fullName"
|
||||
:error-messages="get(errorMessages, 'name')"
|
||||
@change="hideError('name')"
|
||||
label="Jméno"
|
||||
variant="underlined"
|
||||
></v-text-field>
|
||||
|
@ -18,7 +29,13 @@
|
|||
md="4"
|
||||
>
|
||||
<v-text-field
|
||||
dense
|
||||
hide-details="auto"
|
||||
type="email"
|
||||
autocomplete="email"
|
||||
v-model="email"
|
||||
:error-messages="get(errorMessages, 'email')"
|
||||
@change="hideError('email')"
|
||||
label="Emailová adresa"
|
||||
variant="underlined"
|
||||
></v-text-field>
|
||||
|
@ -29,7 +46,12 @@
|
|||
md="4"
|
||||
>
|
||||
<v-text-field
|
||||
dense
|
||||
hide-details="auto"
|
||||
type="tel"
|
||||
v-model="phone"
|
||||
:error-messages="get(errorMessages, 'phone_number')"
|
||||
@change="hideError('phone_number')"
|
||||
label="Telefonní číslo"
|
||||
variant="underlined"
|
||||
></v-text-field>
|
||||
|
@ -39,6 +61,8 @@
|
|||
<v-col>
|
||||
<v-textarea
|
||||
v-model="textField"
|
||||
:error-messages="get(errorMessages, 'content')"
|
||||
@change="hideError('content')"
|
||||
label="Váš dotaz"
|
||||
variant="underlined"
|
||||
/>
|
||||
|
@ -47,6 +71,8 @@
|
|||
<v-row>
|
||||
<v-col>
|
||||
<v-btn
|
||||
auto-grow
|
||||
rows="3"
|
||||
class="contact__button"
|
||||
type="submit"
|
||||
@click.prevent="sendContact"
|
||||
|
@ -63,14 +89,34 @@ import './assets/css/main.css'
|
|||
import {useAPI} from "~/composables/useAPI";
|
||||
|
||||
const valid = ref<boolean>(false);
|
||||
const errorMessages = ref<Record<string, string[]>>({});
|
||||
|
||||
const fullName = ref<string>("");
|
||||
const email = ref<string>("");
|
||||
const phone = ref<string>("");
|
||||
const textField = ref<string>("");
|
||||
|
||||
const showSnackbar = ref(false);
|
||||
const snackbarMessage = ref("");
|
||||
const snackbarColor = ref("red-accent-4")
|
||||
|
||||
function get(obj: any, path: string, defaultValue = undefined) {
|
||||
return path.split('.').reduce((acc, part) => acc && acc[part], obj) ?? defaultValue;
|
||||
}
|
||||
|
||||
function resetContractData() {
|
||||
fullName.value = "";
|
||||
email.value = "";
|
||||
phone.value = "";
|
||||
textField.value = "";
|
||||
}
|
||||
|
||||
function hideError (key: string) {
|
||||
delete errorMessages.value[key];
|
||||
}
|
||||
|
||||
async function sendContact() {
|
||||
const { data, error } = await useAPI('create-contact/', {
|
||||
const { error } = await useAPI('create-contact/', {
|
||||
method: "POST",
|
||||
body: {
|
||||
name: fullName.value,
|
||||
|
@ -79,6 +125,18 @@ async function sendContact() {
|
|||
content: textField.value,
|
||||
}
|
||||
});
|
||||
|
||||
if (error.value) {
|
||||
snackbarMessage.value = "Něco se pokazilo. Zkuste to znovu.";
|
||||
snackbarColor.value = "red-accent-4";
|
||||
errorMessages.value = error.value.data;
|
||||
} else {
|
||||
snackbarMessage.value = "Děkujeme! Vaše zpráva byla odeslána.";
|
||||
snackbarColor.value = "success";
|
||||
resetContractData();
|
||||
}
|
||||
|
||||
showSnackbar.value = true;
|
||||
}
|
||||
|
||||
</script>
|
|
@ -1,76 +1,58 @@
|
|||
<template>
|
||||
<ClientOnly>
|
||||
<v-layout>
|
||||
<v-layout style="margin-bottom: 3rem">
|
||||
<v-app-bar style="position: fixed">
|
||||
<v-app-bar-nav-icon
|
||||
@click="drawer = !drawer"
|
||||
class="d-flex d-sm-none"
|
||||
/>
|
||||
<div>
|
||||
<a href="/"><v-img class="app__logo" src="/logo.png" /></a>
|
||||
</div>
|
||||
<v-app-bar-title class="app__title">Taneční klub Ostrava</v-app-bar-title>
|
||||
<v-app-bar-title class="app__title" v-if="$vuetify.display.smAndUp">
|
||||
Taneční klub Ostrava
|
||||
</v-app-bar-title>
|
||||
|
||||
<v-tabs v-model="currentTab" class="d-none d-sm-flex app__tab">
|
||||
<div
|
||||
<v-tab
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
>
|
||||
<v-tab
|
||||
v-if="tab.ref"
|
||||
:text="tab.name"
|
||||
:value="tab.name"
|
||||
@click="useGoTo(tab.ref)"
|
||||
:href="tab.href ? tab.href : undefined"
|
||||
@click="handleNavigation(tab)"
|
||||
>
|
||||
{{ tab.name }}
|
||||
</v-tab>
|
||||
<v-tab
|
||||
v-if="tab.href"
|
||||
:text="tab.name"
|
||||
:value="tab.name"
|
||||
:href="tab.href"
|
||||
>
|
||||
{{ tab.name }}
|
||||
</v-tab>
|
||||
</div>
|
||||
</v-tabs>
|
||||
|
||||
<v-menu transition="slide-y-transition">
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-app-bar-nav-icon
|
||||
class="d-flex d-sm-none app__tab ml-auto"
|
||||
style="padding-right: 1rem"
|
||||
v-bind="props"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- <v-col-->
|
||||
<!-- class="text-right"-->
|
||||
<!-- @click="toggleTheme"-->
|
||||
<!-- >-->
|
||||
<!-- <big-icon icon="mdi-lightbulb-cfl"/>-->
|
||||
<!-- </v-col>-->
|
||||
</v-app-bar>
|
||||
|
||||
<v-fab
|
||||
class="ms-4 mb-4"
|
||||
></v-fab>
|
||||
|
||||
<v-navigation-drawer
|
||||
v-model="drawer"
|
||||
absolute
|
||||
fixed
|
||||
left
|
||||
<v-list>
|
||||
<v-list-item
|
||||
v-for="(item, i) in homeTabs"
|
||||
:key="i"
|
||||
:value="i"
|
||||
@click="handleNavigation(item)"
|
||||
>
|
||||
<v-list nav dense>
|
||||
<v-list-item v-for="(tab, index) in tabs" :key="index">
|
||||
<v-list-item-title @click="useGoTo(tab.ref)">{{ tab.name }}</v-list-item-title>
|
||||
<v-list-item-title>{{ item.name }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
</v-menu>
|
||||
</v-app-bar>
|
||||
</v-layout>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useGoTo } from "~/composables/useGoTo";
|
||||
import {useRoute} from "#vue-router";
|
||||
const route = useRoute();
|
||||
import { useRoute } from "#vue-router";
|
||||
|
||||
const currentTab = ref({ name: 'O nás', ref: "#about", href: "o-nas" });
|
||||
const drawer = ref(null)
|
||||
const route = useRoute();
|
||||
const currentTab = ref({ name: "O nás", ref: "#about", href: "o-nas" });
|
||||
|
||||
const homeTabs = [
|
||||
{ name: "O nás", ref: "#about", href: "" },
|
||||
|
@ -86,18 +68,17 @@ const otherTabs = [
|
|||
{ name: "Trenéři", ref: "", href: "/" },
|
||||
{ name: "Kurzy", ref: "", href: "/" },
|
||||
{ name: "Galerie", ref: "", href: "/galerie" },
|
||||
{ name: "Aktuality", ref: "", href: "/" },
|
||||
{ name: "Aktuality", ref: "", href: "/aktuality" },
|
||||
{ name: "Kontakty", ref: "", href: "/kontakty" },
|
||||
];
|
||||
|
||||
const tabs = computed(() => (route.path === "/" ? homeTabs : otherTabs));
|
||||
// import { useTheme } from 'vuetify'
|
||||
//
|
||||
// const theme = useTheme()
|
||||
//
|
||||
// function toggleTheme () {
|
||||
// theme.global.name.value = theme.global.current.value.dark ? 'light' : 'dark'
|
||||
// }
|
||||
|
||||
|
||||
const handleNavigation = (tab: any) => {
|
||||
if (tab.ref) {
|
||||
useGoTo(tab.ref);
|
||||
} else if (tab.href) {
|
||||
window.location.href = tab.href;
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,70 +1,3 @@
|
|||
<template v-if="articles">
|
||||
<h1 id="article">Aktuality</h1>
|
||||
<h2>Přečtěte si aktuality z našeho klubu</h2>
|
||||
<v-row>
|
||||
<v-col
|
||||
v-for="article in articles"
|
||||
:key="article.id"
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<v-card class="article">
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-img
|
||||
:lazy-src="article.image"
|
||||
:src="article.image"
|
||||
aspect-ratio="1"
|
||||
cover
|
||||
class="article__image"
|
||||
>
|
||||
<template v-slot:placeholder>
|
||||
<v-row>
|
||||
<v-progress-circular
|
||||
color="grey-lighten-5"
|
||||
indeterminate
|
||||
></v-progress-circular>
|
||||
</v-row>
|
||||
</template>
|
||||
</v-img>
|
||||
</v-col>
|
||||
<v-col
|
||||
cols="12"
|
||||
md="8"
|
||||
>
|
||||
<v-row class="article__title">{{ article.title }}</v-row>
|
||||
<v-row class="article__date">{{ article.date}}</v-row>
|
||||
<v-row class="article__text">{{ article.content }}</v-row>
|
||||
<v-row class="article__sign">{{ article.author }}</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<template>
|
||||
<lazy-news :for-all="true"/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import './assets/css/main.css'
|
||||
|
||||
import {useAPI} from "~/composables/useAPI";
|
||||
|
||||
interface Article {
|
||||
id: number;
|
||||
title: string;
|
||||
image: string;
|
||||
date: string;
|
||||
content: string;
|
||||
author: string;
|
||||
}
|
||||
|
||||
const articles = ref<Article[]>([]);
|
||||
|
||||
const { error, data } = await useAPI('load-all-articles/', {method: "GET"});
|
||||
|
||||
if ( data.value ){
|
||||
articles.value = data.value as Article[];
|
||||
}
|
||||
else if (error.value) {
|
||||
console.error("Error loading articles:", error.value);
|
||||
}
|
||||
</script>
|
|
@ -47,12 +47,20 @@ interface ArticleImage {
|
|||
|
||||
const gallery = ref<ArticleImage[]>([]);
|
||||
|
||||
const { error, data } = await useAPI<ArticleImage[]>('load-gallery/', {method: "GET"});
|
||||
loadImages();
|
||||
|
||||
if ( data.value ){
|
||||
async function loadImages(){
|
||||
const { error, data } = await useAPI<ArticleImage[]>('load-gallery/', {method: "GET"});
|
||||
|
||||
if ( data.value ){
|
||||
gallery.value = data.value as ArticleImage[];
|
||||
}
|
||||
else if (error.value) {
|
||||
}
|
||||
else if (error.value) {
|
||||
console.error("Error loading gallery:", error.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
|
@ -11,12 +11,12 @@
|
|||
</h2>
|
||||
</div>
|
||||
</v-parallax>
|
||||
<news/>
|
||||
<about/>
|
||||
<courses/>
|
||||
<trainers/>
|
||||
<advantages/>
|
||||
<history/>
|
||||
<lazy-news :for-all="false"/>
|
||||
<lazy-about/>
|
||||
<lazy-courses/>
|
||||
<lazy-trainers/>
|
||||
<lazy-advantages/>
|
||||
<lazy-history/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -1,37 +1,4 @@
|
|||
<template>
|
||||
<h1 id="courses">Kurzy</h1>
|
||||
<h2>Vyberte, co Vám nejlépe vyhovuje</h2>
|
||||
|
||||
<v-row>
|
||||
<v-col
|
||||
cols="12"
|
||||
md="4"
|
||||
v-for="(course, index) in courses"
|
||||
:key="index"
|
||||
>
|
||||
<v-card class="pricing-box">
|
||||
<h3>{{ course.name }}</h3>
|
||||
<v-card-subtitle><div class="pricing__subtitle">{{ course.time }}</div></v-card-subtitle>
|
||||
<v-card-title><div class="pricing__price">{{ course.price }}</div></v-card-title>
|
||||
<v-card-text v-if="course.desc"><div class="pricing__subtitle">{{ course.desc }}</div></v-card-text>
|
||||
<v-btn class="show_more"><v-icon icon="mdi-chevron-down"/>Kontaktujte nás<v-icon icon="mdi-chevron-down"/></v-btn>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<calendar/>
|
||||
<lazy-courses />
|
||||
<lazy-calendar/>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import './assets/css/main.css'
|
||||
|
||||
// TODO: vyskakovací okno s kontaktním formulářem po rozkliku :)
|
||||
|
||||
const courses = [
|
||||
{name: "Sportovní taneční klub", time: "", price: "", desc: "Připojte se k našemu tanečnímu klubu a rozvíjejte své taneční dovednosti v přátelském prostředí. Nabízíme různé styly tance pro všechny úrovně."},
|
||||
{name: "Svatební tance", time: "", price: "", desc: "Udělejte svůj první tanec nezapomenutelným. Pomůžeme Vám vytvořit choreografii na míru, která bude odrážet Váš jedinečný styl."},
|
||||
{name: "Příprava na plesovou sezónu", time: "", price: "", desc: "Chcete zazářit na plese? Připravíme Vás na plesovou sezónu a naučíme Vás elegantní taneční kroky a etiketu."},
|
||||
{name: "Individuální taneční kurzy", time: "", price: "", desc: "Učte se tančit vlastním tempem s individuálním přístupem. Naši zkušení lektoři se zaměří na Vaše potřeby a pomohou Vám dosáhnout Vašich tanečních cílů."},
|
||||
{name: "Individuální lekce", time: "", price: "", desc: "Zlepšete své taneční dovednosti s intenzivními individuálními lekcemi. Zaměřte se na konkrétní taneční techniky nebo styly, které Vás zajímají."},
|
||||
{name: "Pronájem sálu", time: "", price: "", desc: "Hledáte ideální prostor pro tanec nebo jinou aktivitu? Náš taneční sál je k dispozici k pronájmu pro Vaše akce."},
|
||||
]
|
||||
|
||||
</script>
|
BIN
services/frontend/public/image.jpg
Normal file
BIN
services/frontend/public/image.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 126 KiB |
Loading…
Reference in a new issue