galery-to-article #1

Merged
Beeebooo merged 4 commits from galery-to-article into master 2025-04-04 11:16:34 +02:00
10 changed files with 408 additions and 169 deletions
Showing only changes of commit 19210e1cc1 - Show all commits

1
TODO
View file

@ -4,6 +4,7 @@ Nastylovat:
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)

View file

@ -20,7 +20,7 @@ h2 {
font-size: 1.5rem;
color: #CF3476;
text-align: center;
margin-bottom: 0.5rem;
margin-bottom: 2rem;
}
h3 {
@ -46,6 +46,17 @@ h5 {
margin-top: 1rem;
}
@media (max-width: 600px) {
h1 {
font-size: 2rem; /* Smaller size for mobile */
margin-top: 1.5rem;
}
h2 {
font-size: 1.2rem; /* Slightly smaller h2 for mobile */
}
}
.sheet__box {
min-width: 25rem;
margin-left: calc(20% - 2.5rem);
@ -95,12 +106,33 @@ h5 {
font-weight: bold;
}
.contact__dialog__title {
font-family: 'Futura', sans-serif;
font-size: 2rem;
color: #333;
margin-bottom: 1rem;
font-weight: bold;
}
.contact__button {
width: 100%;
color: #ffffff;
background-color: #CF3476;
}
@media (max-width: 600px) {
.v-dialog > .v-card {
border-radius: 0 !important;
height: 100vh;
padding: 1rem;
}
.contact__dialog__title {
font-size: 1.5rem;
margin-bottom: 0.5rem;
}
}
.articles {
margin-left: calc(20% - 2.5rem);
margin-right: calc(20% - 2.5rem);
@ -170,35 +202,70 @@ h5 {
}
.pricing {
margin-left: calc(20% - 2.5rem);
margin-right: calc(20% - 2.5rem);
margin-left: auto;
margin-right: auto;
max-width: 1500px;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0.5rem;
}
.pricing-box {
padding: 1rem;
padding: 1.5rem;
text-align: center;
min-width: 25rem;
min-width: 18rem;
border-radius: 1rem;
height: 230px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
height: 100%;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transition: transform 0.3s ease, box-shadow 0.3s ease;
background: #fff;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.pricing-box:hover {
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.8);
transform: translateY(-5px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.25);
}
.pricing-content {
flex-grow: 1;
}
.pricing-title {
min-height: 3rem;
}
.pricing-desc {
min-height: 3rem;
}
.pricing__price {
font-family: 'Futura', sans-serif;
font-size: 3.5rem;
font-size: 3rem;
font-weight: bold;
color: #CF3476;
text-align: center;
margin-top: 0.5rem;
}
.pricing__subtitle {
font-family: 'Futura', sans-serif;
font-size: 1rem;
color: #333;
text-align: center;
color: #555;
margin-bottom: 0.5rem;
}
@media (max-width: 600px) {
.pricing-box {
min-width: 100%;
}
.pricing-title,
.pricing-desc {
min-height: unset; /* Removes forced height to prevent breakage */
}
}
.trainers__parallax {
@ -207,12 +274,45 @@ h5 {
}
.trainers {
min-width: 25rem;
margin-left: auto;
margin-right: auto;
max-width: 1500px;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0.5rem;
background: transparent;
box-shadow: none;
height: 100%;
margin-left: calc(20% - 2.5rem);
margin-right: calc(20% - 2.5rem);
text-align: center;
padding: 2rem;
}
.trainer-avatar {
width: 150px;
height: 150px;
margin: 20px auto;
border-radius: 50%;
border: 3px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
overflow: hidden;
}
/* Mobile Styles */
@media (max-width: 600px) {
.trainers__parallax {
max-height: 30rem;
}
.trainers {
max-width: 100%;
padding: 1rem;
}
.trainer-avatar {
width: 120px;
height: 120px;
}
}
.advantage {
@ -227,6 +327,7 @@ h5 {
.advantage__title {
font-family: 'Futura', sans-serif;
padding: 0.5rem 0;
color: #CF3476;
font-size: 1.5rem;
font-weight: bold;
@ -235,17 +336,37 @@ h5 {
.advantage__text {
font-family: 'Futura', sans-serif;
padding-bottom: 1rem;
font-size: 1rem;
color: #333;
}
@media (max-width: 600px) {
.advantage {
min-width: 100%;
margin: 0.5rem auto;
padding: 0.5rem;
box-shadow: 0 0 0 rgba(0, 0, 0, 0);
}
.advantage__title {
font-size: 1.3rem;
}
.advantage__text {
font-size: 1rem;
padding: 0 1.5rem;
}
}
.about {
min-width: 25rem;
background: transparent;
box-shadow: none;
height: 100%;
margin-left: calc(20% - 2.5rem);
margin-right: calc(20% - 2.5rem);
max-width: 80%;
margin: 0 auto;
text-align: center;
padding: 2rem;
}
.about__parallax {
@ -253,10 +374,23 @@ h5 {
margin-top: 2rem;
}
.history__parallax {
max-height: 34rem;
margin-top: 2rem;
}
@media (max-width: 600px) {
.history__parallax {
max-height: 45rem;
}
}
.about__title {
font-family: 'Futura', sans-serif;
font-size: 3rem;
text-align: center;
width: 100%;
display: block;
color: #fff;
margin-top: 1rem;
font-weight: bold;
@ -265,8 +399,10 @@ h5 {
.about__subtitle {
font-family: 'Futura', sans-serif;
color: #FF3D8C;
font-size: 1.5rem;
font-size: 1.3rem;
text-align: center;
width: 100%;
display: block;
margin-bottom: 0.5rem;
font-weight: bold;
}
@ -274,8 +410,29 @@ h5 {
.about__text {
font-family: 'Futura', sans-serif;
color: #ddd;
font-size: 1.2rem;
font-size: 1rem;
text-align: center;
padding: 0 1rem;
}
@media (max-width: 600px) {
.about {
max-width: 100%;
padding: 1rem;
}
.about__title {
font-size: 1.5rem;
}
.about__subtitle {
font-size: 1rem;
}
.about__text {
font-size: 1rem;
padding: 0 10px;
}
}
.footer {

View file

@ -6,16 +6,18 @@
:key="advantage.id"
class="advantage"
>
<v-row>
<v-col cols="12" md="1">
<v-row align="center" class="pa-2">
<v-col cols="auto">
<small-icon :icon="advantage.icon" />
</v-col>
<v-col>
<v-card-title class="advantage__title">
{{advantage.title}}
{{ advantage.title }}
</v-card-title>
</v-col>
</v-row>
<v-card-text class="advantage__text">
{{ advantage.subtitle }}
</v-card-text>

View file

@ -1,87 +1,9 @@
<template>
<v-card class="contact">
<v-form v-model="valid">
<v-container>
<v-card-title class="contact__title">Kontaktujte nás!</v-card-title>
<v-row>
<v-col
cols="12"
md="4"
>
<v-text-field
v-model="fullName"
label="Jméno"
variant="underlined"
></v-text-field>
</v-col>
<v-col
cols="12"
md="4"
>
<v-text-field
v-model="email"
label="Emailová adresa"
variant="underlined"
></v-text-field>
</v-col>
<v-col
cols="12"
md="4"
>
<v-text-field
v-model="phone"
label="Telefonní číslo"
variant="underlined"
></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col>
<v-textarea
v-model="textField"
label="Váš dotaz *"
variant="underlined"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-btn
class="contact__button"
type="submit"
@click.prevent="sendContact"
>
Poslat
</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
<v-card-title class="contact__title">Kontaktujte nás!</v-card-title>
<dialog-contact-form />
</v-card>
</template>
<script setup lang="ts">
import './assets/css/main.css'
import {useAPI} from "~/composables/useAPI";
const valid = ref<boolean>(false);
const fullName = ref<string>("");
const email = ref<string>("");
const phone = ref<string>("");
const textField = ref<string>("");
async function sendContact() {
const { data, error } = await useAPI('create-contact/', {
method: "POST",
body: {
name: fullName.value,
email: email.value,
phone_number: phone.value,
content: textField.value,
}
});
}
</script>

View file

@ -2,24 +2,62 @@
<h1 id="courses">Kurzy</h1>
<h2>Vyberte, co Vám nejlépe vyhovuje</h2>
<v-row class="pricing">
<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">
Kontaktujte nás
</v-btn>
</v-card>
</v-col>
</v-row>
<v-row class="pricing">
<v-col
cols="12"
sm="6"
md="4"
lg="3"
v-for="(course, index) in courses"
:key="index"
>
<v-card class="pricing-box" @click="openDialog = true; chosenCourse = course">
<div class="pricing-content">
<h3 class="pricing-title">{{ 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 pricing-desc">{{ course.desc }}</div>
</v-card-text>
</div>
<v-btn class="show_more">
Kontaktujte nás
</v-btn>
</v-card>
</v-col>
</v-row>
<template>
<v-dialog
v-model="openDialog"
:fullscreen="$vuetify.display.smAndDown"
scrollable
transition="dialog-bottom-transition"
>
<v-card class="contact pa-4">
<v-card-title class="contact__dialog__title d-flex align-center">
<span class="flex-grow-1 text-center" style="margin-left: 40px;">{{ chosenCourse.name }}</span>
<v-btn icon="mdi-close" variant="text" @click="openDialog = false"></v-btn>
</v-card-title>
<v-card-text v-if="chosenCourse.desc" class="text-center">
<div class="pricing__subtitle text-body-1">{{ chosenCourse.desc }}</div>
</v-card-text>
<v-divider class="my-4"></v-divider>
<v-card-title class="contact__dialog__title text-center">
Kontaktujte nás!
</v-card-title>
<dialog-contact-form class="mt-2" />
</v-card>
</v-dialog>
</template>
<!-- <v-btn to="/kurzy" class="show_more">-->
<!-- <v-icon icon="mdi-chevron-down"/>Více informací<v-icon icon="mdi-chevron-down"/>-->
<!-- </v-btn>-->
@ -27,7 +65,7 @@
<script setup lang="ts">
import './assets/css/main.css'
// TODO: vyskakovací okno s kontaktním formulářem po rozkliku :)
const openDialog = ref<boolean>(false);
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ě."},
@ -38,4 +76,5 @@ const courses = [
{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."},
]
const chosenCourse = ref(courses[0]);
</script>

View file

@ -1,6 +1,6 @@
<template>
<v-parallax
class="about__parallax"
class="history__parallax"
src="public/img/black-pink.jpg"
>
<v-container id="about">

View file

@ -1,26 +1,36 @@
<template>
<v-parallax
class="trainers__parallax"
src="public/img/black-pink.jpg"
>
<v-parallax class="trainers__parallax" src="public/img/black-pink.jpg">
<v-container id="trainers">
<v-card class="trainers">
<v-card-title class="about__title">Naši trenéři a lektoři</v-card-title>
<v-card-subtitle class="about__subtitle">Seznamte se s námi!</v-card-subtitle>
<v-row>
<v-col class="text-center" cols="12" md="3" v-for="lector in lectors" :key="lector.id">
<v-avatar
color="none"
rounded="1"
size="150"
style="margin: 30px"
<v-card class="trainers pa-4">
<v-card-title class="about__title ">Naši trenéři a lektoři</v-card-title>
<v-card-subtitle class="about__subtitle ">Seznamte se s námi!</v-card-subtitle>
<v-carousel cycle interval="4000" hide-delimiters show-arrows="hover">
<v-carousel-item v-for="(group, index) in trainerGroups" :key="index">
<v-row justify="center">
<v-col
v-for="(lector, index) in group"
:key="index"
cols="12"
sm="6"
md="4"
lg="3"
class="text-center"
>
<v-img :src="lector.img" cover></v-img>
</v-avatar>
<v-card-subtitle class="about__subtitle">{{lector.name}}</v-card-subtitle>
<v-card-text class="about__text">{{ lector.desc }}</v-card-text>
</v-col>
</v-row>
<v-avatar
color="none"
rounded="1"
size="150"
style="margin: 30px"
>
<v-img :src="lector.img" cover></v-img>
</v-avatar>
<v-card-subtitle class="about__subtitle">{{ lector.name }}</v-card-subtitle>
<v-card-text class="about__text">{{ lector.desc }}</v-card-text>
</v-col>
</v-row>
</v-carousel-item>
</v-carousel>
</v-card>
</v-container>
</v-parallax>
@ -30,28 +40,38 @@ import './assets/css/main.css'
const lectors = [
{
id: 1,
name: "Ondřej Gilar",
img: "/trainers/img.png",
desc: "Trenér - latinskoamerické tance a Pro-AM",
},
{
id: 2,
name: "Leona Hruštincová",
img: "/trainers/img.png",
desc: "Lektorka - tance pro děti",
},
{
id: 1,
name: "Ondřej Gilar",
img: "/trainers/img.png",
desc: "Trenér - latinskoamerické tance a Pro-AM",
},
{
id: 2,
name: "Leona Hruštincová",
img: "/trainers/img.png",
desc: "Lektorka - tance pro děti",
},
{
name: "Leona Hruštincová",
img: "/trainers/img.png",
desc: "Lektorka - tance pro děti",
},
]
const trainerGroups = computed(() => {
const groups: typeof lectors[] = [];
const perSlide = window.innerWidth >= 1280 ? 4 : window.innerWidth >= 600 ? 2 : 1;
for (let i = 0; i < lectors.length; i += perSlide) {
groups.push(lectors.slice(i, i + perSlide));
}
return groups;
});
</script>

View file

@ -0,0 +1,84 @@
<template>
<v-form v-model="valid">
<v-container>
<v-row>
<v-col
cols="12"
md="4"
>
<v-text-field
v-model="fullName"
label="Jméno"
variant="underlined"
></v-text-field>
</v-col>
<v-col
cols="12"
md="4"
>
<v-text-field
v-model="email"
label="Emailová adresa"
variant="underlined"
></v-text-field>
</v-col>
<v-col
cols="12"
md="4"
>
<v-text-field
v-model="phone"
label="Telefonní číslo"
variant="underlined"
></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col>
<v-textarea
v-model="textField"
label="Váš dotaz"
variant="underlined"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-btn
class="contact__button"
type="submit"
@click.prevent="sendContact"
>
Poslat
</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
</template>
<script setup lang="ts">
import './assets/css/main.css'
import {useAPI} from "~/composables/useAPI";
const valid = ref<boolean>(false);
const fullName = ref<string>("");
const email = ref<string>("");
const phone = ref<string>("");
const textField = ref<string>("");
async function sendContact() {
const { data, error } = await useAPI('create-contact/', {
method: "POST",
body: {
name: fullName.value,
email: email.value,
phone_number: phone.value,
content: textField.value,
}
});
}
</script>

View file

@ -3,23 +3,39 @@
<v-layout>
<v-app-bar style="position: fixed">
<v-app-bar-nav-icon
@click="drawer = !drawer"
class="d-flex d-sm-none"
@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-tabs
v-for="(tab, index) in tabs" :key="index"
v-model="currentTab"
align-with-title
class="d-none d-sm-flex app__tab"
>
<v-tab v-if="tab.ref" :text="tab.name" :value="tab.name" @click="useGoTo(tab.ref)"></v-tab>
<v-tab v-if="tab.href" :text="tab.name" :value="tab.name" :href="tab.href"></v-tab>
<v-tabs v-model="currentTab" class="d-none d-sm-flex app__tab">
<div
v-for="(tab, index) in tabs"
:key="index"
>
<v-tab
v-if="tab.ref"
:text="tab.name"
:value="tab.name"
@click="useGoTo(tab.ref)"
>
{{ 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-col-->
<!-- class="text-right"-->
<!-- @click="toggleTheme"-->
@ -29,7 +45,6 @@
</v-app-bar>
<v-fab
:key="currentTab.ref"
class="ms-4 mb-4"
></v-fab>
@ -39,10 +54,7 @@
fixed
left
>
<v-list
nav
dense
>
<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>
@ -54,9 +66,10 @@
<script setup lang="ts">
import { useGoTo } from "~/composables/useGoTo";
import {useRoute} from "#vue-router";
const route = useRoute();
const currentTab = ref({name: 'O nás', ref: "#about", href: "o-nas"});
const currentTab = ref({ name: 'O nás', ref: "#about", href: "o-nas" });
const drawer = ref(null)
const homeTabs = [
@ -69,15 +82,15 @@ const homeTabs = [
];
const otherTabs = [
{ name: "O nás", ref: "", href: "/#about" },
{ name: "Trenéři", ref: "", href: "/trenery" },
{ name: "Kurzy", ref: "", href: "/kurzy" },
{ name: "O nás", ref: "", href: "/" },
{ name: "Trenéři", ref: "", href: "/" },
{ name: "Kurzy", ref: "", href: "/" },
{ name: "Galerie", ref: "", href: "/galerie" },
{ name: "Aktuality", ref: "", href: "/aktuality" },
{ name: "Aktuality", ref: "", href: "/" },
{ name: "Kontakty", ref: "", href: "/kontakty" },
];
const tabs = computed(() => (route.path === "/" ? homeTabs : otherTabs))
const tabs = computed(() => (route.path === "/" ? homeTabs : otherTabs));
// import { useTheme } from 'vuetify'
//
// const theme = useTheme()
@ -86,4 +99,5 @@ const tabs = computed(() => (route.path === "/" ? homeTabs : otherTabs))
// theme.global.name.value = theme.global.current.value.dark ? 'light' : 'dark'
// }
</script>

View file

@ -49,7 +49,7 @@ export default defineNuxtPlugin((app) => {
defaults: {
SmallIcon: {
color: 'color',
style: [{ 'margin-left': '20px', 'margin-top': '15px', 'font-size': '30px'}]
style: [{ 'margin-left': '20px', 'font-size': '30px'}]
},
BigIcon: {
color: 'color',