This commit is contained in:
2026-04-26 22:02:24 +02:00
commit 73442783b7
1470 changed files with 43422 additions and 0 deletions

64
app/components/Embla.vue Normal file
View File

@@ -0,0 +1,64 @@
<script setup>
import emblaCarouselVue from "embla-carousel-vue";
import RitzenbergenLib from "../ritzenbergenlib.ts";
import { onMounted, ref } from "vue";
import EmblaItem from "./EmblaItem.vue";
const emblaApi = ref();
const [emblaRef, emblaInstance] = emblaCarouselVue({ loop: true });
let timeout=false;
onMounted(() => {
emblaApi.value = emblaInstance.value;
setInterval(()=>{
if(!timeout) emblaApi.value?.scrollNext();
}, 2000);
});
const prev = () => {
emblaApi.value?.scrollPrev();
addTimeout();
};
const next = () => {
emblaApi.value?.scrollNext();
addTimeout();
};
function addTimeout(){
timeout=true;
setTimeout(()=>{
timeout=false;
}, 4000);
}
defineProps({
src: {
type: Array,
required: true,
},
links: {
type: Array,
required: true,
},
});
</script>
<template>
<div class="embla" ref="emblaRef">
<div class="embla__container">
<EmblaItem v-for="el, i in src" :src="el" :link="links[i]" />
</div>
<button class="embla__button embla__button--prev" @click="prev">
<span class="mobi-mbri mobi-mbri-arrow-prev" aria-hidden="true"></span>
<span class="sr-only visually-hidden visually-hidden">Previous</span>
</button>
<button class="embla__button embla__button--next" @click="next">
<span class="mobi-mbri mobi-mbri-arrow-next" aria-hidden="true"></span>
<span class="sr-only visually-hidden visually-hidden">Next</span>
</button>
</div>
</template>
<style scoped></style>

View File

@@ -0,0 +1,26 @@
<script lang="ts">
export default {
props: ["src", "link"],
};
</script>
<template>
<div
class="embla__slide slider-image item"
style="margin-left: 1rem; margin-right: 1rem"
>
<div class="slide-content">
<div class="item-img">
<div class="item-wrapper">
<RouterLink :to="link">
<img
:src="
src
"
/>
</RouterLink>
</div>
</div>
</div>
</div>
</template>
<style></style>

View File

@@ -0,0 +1,147 @@
<script lang="ts" setup>
import RitzenbergenLib from "../ritzenbergenlib.ts";
import { defineProps, ref, watchEffect } from "vue";
const props = defineProps({
form: {
type: RitzenbergenLib.Formular,
required: true,
},
token: {
type: String,
required: false,
default: ""
}
});
const form = ref(props.form);
const results = ref([]);
const myfields = ref([]);
watchEffect(() => {
fetch(
RitzenbergenLib.RitzenbergenLib.api(
"/formulare/get_results.php?id=" + form.value.id
)
)
.then((res) => res.json())
.then((data) => {
if(data.error){
// Admin Rechte nötig
fetch(RitzenbergenLib.RitzenbergenLib.api("/admin/formulare/ergebnisse.php?formular="+form.value.id),{
headers: {
"Authorization":props.token
}
})
.then((res)=>res.json())
.then((data)=>{
results.value=data;
})
} else {
results.value = data;
}
});
myfields.value = [];
form.value.fields.forEach((field: RitzenbergenLib.Field) => {
if (myfields.value.find((el) => el.name == field.name) == undefined) {
myfields.value.push(field);
}
});
});
function prettyResult(result: any) {
if (result == undefined) {
return "";
}
if (result.value instanceof Array) {
let tempresult = result.value;
let cancel = false;
tempresult = tempresult.map((el) => {
let field = form.value.fields.find((f) => f.value == el);
if (field == undefined) {
cancel = true;
return el;
}
return field.displayvalue ?? el;
});
if (!cancel) result.value = tempresult;
return result.value.join(", ");
}
if (result.type == "radio") {
let field = form.value.fields.find((f) => f.value == result.value);
if (field != undefined) {
return field.displayvalue ?? result.value;
}
}
return result.value;
}
</script>
<template>
<h1>Ergebnisse {{ form.name }}</h1>
<div class="main">
<table>
<thead>
<tr>
<td v-for="(field, i) in myfields" :key="i">
{{ field.displayname ?? field.name }}
</td>
<td>Zeitstempel</td>
</tr>
</thead>
<tbody>
<tr v-for="(result, ri) in results" :key="ri">
<td
v-if="result.data != undefined"
v-for="(field, fi) in myfields"
:key="fi"
:style="
field.type == 'color'
? {
backgroundColor: result.data.find(
(el) => el.name == field.name
).value,
width: '10px',
height: '10px',
}
: {}
"
>
<span v-if="field.type != 'color'">{{
prettyResult(
result.data.find(
(el) =>
el.name == field.name ||
el.name + "[]" == field.name
)
)
}}</span>
<span v-else></span>
</td>
<td>{{ result.timestamp }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<style scoped>
@import "../assets/css/bulitipp2.css";
td {
min-width: 150px;
min-height: 0;
}
tbody, table, .main{
overflow-x: scroll;
}
thead tr td {
background-color: #efefef;
}
h1 {
text-align: center;
}
</style>

View File

@@ -0,0 +1,215 @@
<script lang="ts">
import "../assets/css/chatbox.css";
import RitzenbergenLib from "../ritzenbergenlib.ts";
export default {
name: "Kloenkasten",
data() {
return {
sender: "",
message: "",
email: "",
opened: false,
reloader: false,
RitzenbergenLib: RitzenbergenLib,
msgrefs: [],
};
},
computed: {
newMsg(): boolean {
if (this.messages == undefined) return false;
if (this.opened) this.open();
const lastOpened: Date = new Date(
parseInt(localStorage.getItem("kloenkasten_last_opened"))
);
const lastMsg = this.messages[this.messages.length - 1];
if (this.messages && lastMsg.timestamp > lastOpened) {
return true;
}
return false;
},
},
created() {
if (localStorage.getItem("kloenkasten_last_opened") == null) {
localStorage.setItem(
"kloenkasten_last_opened",
Date.now().toString()
);
}
},
methods: {
submitMsg() {
const url = new URL(
RitzenbergenLib.RitzenbergenLib.api("/kloenkasten_submit.php")
);
url.searchParams.append("sender", this.sender);
url.searchParams.append("email", this.email);
url.searchParams.append("message", this.message);
fetch(url.toString(), { method: "GET" }).then(() => {
this.reloader = !this.reloader;
this.sender = "";
this.email = "";
this.message = "";
});
},
open() {
this.opened = true;
localStorage.setItem(
"kloenkasten_last_opened",
Date.now().toString()
);
if(this.messages) window.setTimeout(
() =>
this.msgrefs[this.msgrefs.length - 1].scrollIntoView({
behavior: "smooth",
}),
50
);
},
},
asyncComputed: {
messages: {
get() {
const url = new URL(
RitzenbergenLib.RitzenbergenLib.api(
"/kloenkasten_nachrichten.php"
)
);
return fetch(url.toString(), { method: "GET" })
.then((response)=>{
if(response.ok) return response.json();
else throw new Error("fetch "+response.status);
})
.then((data) =>
data.map((msg) => {
msg.timestamp = new Date(msg.timestamp);
return msg;
})
).catch(()=>{
return false;
});
},
watch: ["reloader"],
},
},
};
</script>
<template>
<button
id="chatbox-button"
:class="{ newmsg: newMsg }"
@click="open"
>
<span class="material-symbols-outlined">chat</span>
<span :class="{ newmsgdot: newMsg, newmsgdotinvis: !newMsg }"></span>
</button>
<div v-show="opened" id="modalbox">
<div id="modalbox-header">
<span class="material-symbols-outlined">chat</span>
<h3 id="modalbox-title">Klönkasten</h3>
<span id="close-button" @click="opened = false">&times;</span>
</div>
<div id="chat-messages" v-if="messages">
<div
v-for="(msg, i) in messages"
:key="i"
:ref="(el) => (msgrefs[i] = el)"
>
<i>{{ msg.timestamp.toLocaleString() }}</i>
<div class="message own-message animate__animated">
<a :href="'mailto:' + msg.email" v-if="msg.email"
>{{ msg.name }}:
</a>
<span class="message-sender animate__animated" v-else
>{{ msg.name }}:
</span>
<span class="message-content animate__animated">{{
msg.message
}}</span>
</div>
</div>
<form id="chat-input" @submit.prevent="submitMsg">
<input
id="name-input"
v-model="sender"
type="text"
maxlength="64"
placeholder="Name"
required
/>
<input
id="email-input"
v-model="email"
type="email"
maxlength="128"
placeholder="E-Mail"
/>
<input
id="message-input"
v-model="message"
type="text"
placeholder="Nachricht"
maxlength="1024"
required
/>
<input type="submit" id="send-button" value="Senden" />
</form>
</div>
<div id="chat-messages" v-else>
<h3>Konnte Server nicht erreichen.</h3>
</div>
</div>
</template>
<style scoped>
@import url("https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0");
.newmsg {
animation: newmsgblink 3s infinite;
}
.newmsgdot{
width: 10px;
height: 10px;
background-color: #00ff00;
position: absolute;
border-radius: 50%;
top: 5px;
right: 5px;
z-index: 10;
}
.newmsgdotinvis{
display: none;
}
@keyframes newmsgblink {
0% {
transform: scale(1) rotate(0deg) translateX(0) translateY(0);
}
20% {
transform: scale(1.5) rotate(0deg) translateX(-10px) translateY(-10px);
}
25% {
transform: scale(1.5) rotate(10deg) translateX(-10px) translateY(-10px);
}
30% {
transform: scale(1.5) rotate(-10deg) translateX(-10px) translateY(-10px);
}
35% {
transform: scale(1.5) rotate(10deg) translateX(-10px) translateY(-10px);
}
40% {
transform: scale(1.5) rotate(-10deg) translateX(-10px) translateY(-10px);
}
45% {
transform: scale(1.5) rotate(0deg) translateX(-10px) translateY(-10px);
}
}
</style>

29
app/components/Modal.vue Normal file
View File

@@ -0,0 +1,29 @@
<script lang="ts">
export default {
emits: ["closemodal"],
props: ["content"],
mounted() {
(<HTMLElement>this.$refs.contentspan)
.querySelectorAll(".closelink")
.forEach((el) => {
el.addEventListener("click", () => {
this.$emit("closemodal");
});
});
},
};
</script>
<template>
<div class="modal">
<div class="modal-content">
<button class="closeBtn" @click="$emit('closemodal')">x</button>
<div class="modal-inner-content">
<slot></slot>
<span v-html="content" ref="contentspan"></span>
</div>
</div>
</div>
</template>
<style lang="css" scoped>
@import "../assets/modal";
</style>

View File

@@ -0,0 +1,79 @@
<script>
import Modal from "./Modal.vue";
export default {
data: function () {
return {
aboutVisible: false,
contactVisible: false,
};
},
components: {
Modal,
},
};
</script>
<template>
<section
class="footer3 cid-u6k7q0Blvk"
once="footers"
id="footer-6-u6k7q0Blvk"
>
<div class="container">
<div class="row">
<div class="row-links">
<ul class="header-menu">
<li class="header-menu-item mbr-fonts-style display-5">
<Modal v-show="aboutVisible" @closemodal="aboutVisible = false">
<br>
<h1>Über</h1>
<p>
Ritzenbergen ist ein kleines Dorf der Gemeinde Blender und
liegt dicht an der Weser.
<br />
<br />
Bei dieser Seite handelt es sich um eine private Homepage der
Dorfgemeinschaft Amedorf &amp; Ritzenbergen.
<br /><br />
© Front-End und Web Design: Mathis Kuhlenkamp, Jonas Kuhlenkamp <br />
© Back-End und Datenbanken: Jonas Kuhlenkamp
<br />
<br />
</p>
<RouterLink to="/adminpanel/login">Admin Login</RouterLink>
</Modal>
<button @click="aboutVisible=true" class="text-white btn-ueber openBtn">Über</button>
</li>
<li class="header-menu-item mbr-fonts-style display-5">
<Modal
v-show="contactVisible"
@closemodal="contactVisible = false"
>
<h1>Kontakt</h1>
<p>
Tom Kuhlenkamp <br />
tom@ritzenbergen.de
</p>
<br /><br />
</Modal>
<button
class="text-white btn-kontakt openBtn"
@click="contactVisible = true"
>
Kontakt
</button>
</li>
</ul>
</div>
<div class="col-12 mt-4">
<p class="mbr-fonts-style copyright display-7">
© 2026 Ritzenbergen. Alle Rechte vorbehalten. <br />
</p>
</div>
</div>
</div>
</section>
</template>
<style></style>

147
app/components/Navbar.vue Normal file
View File

@@ -0,0 +1,147 @@
<script lang="js">
export default {
name: "Navbar",
props: {
links: {
type: Array,
required: false,
},
buttontext: {
type: String,
required: false,
},
},
data(){
return {
datalinks: [
{ link: "/galerie", title: "Galerie" },
{ link: "/umgebung", title: "Umgebung" },
{ link: "/footer", title: "Kontakt" },
{ link: "/bulitipp", title: "BuLi-Tipp" },
],
buttontextdata: "Über Ritzenbergen",
isNavCollapsed: true,
isCollapsing: false,
}
},
created() {
if(this.links) this.datalinks = this.links;
if(this.buttontext) this.buttontextdata = this.buttontext;
},
methods: {
clickmain(){
if(this.buttontext){
this.$emit("clickbtn");
}else{
this.$router.push("/willkommen");
}
},
toggleCollapse(){
/*if (this.isNavCollapsed) {
document.body.classList.add("navbar-dropdown-open");
} else {
document.body.classList.remove("navbar-dropdown-open");
}*/
this.isCollapsing = true;
this.isNavCollapsed = !this.isNavCollapsed;
setTimeout(() => {
this.isCollapsing = false;
}, 300);
}
}
};
</script>
<template>
<section class="menu menu2 cid-u6k7q0wPq6" once="menu" id="menu-5-u6k7q0wPq6">
<nav class="navbar navbar-dropdown navbar-fixed-top navbar-expand-lg" :class="{ opened: !isNavCollapsed }">
<div class="container">
<div class="navbar-brand">
<span class="navbar-logo">
<span href="/">
<img
class="navbar-logo-img"
src="../assets/RitzenbergenOrtsschild.png"
style="height: 60px; padding-left: 5px"
/>
</span>
</span>
<span class="navbar-caption-wrap">
<span class="navbar-caption text-black display-4" href="/"
>Amedorf & Ritzenbergen</span
>
</span>
</div>
<button
class="navbar-toggler"
:class="{ collapsed: isNavCollapsed }"
type="button"
data-toggle="collapse"
data-bs-toggle="collapse"
data-target="#navbarSupportedContent"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarNavAltMarkup"
aria-expanded="false"
aria-label="Toggle navigation"
@click="toggleCollapse"
>
<div class="hamburger">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</button>
<div class="navbar-collapse opacityScroll" :class="{show: !isNavCollapsed, collapsing: isCollapsing, collapse: !isCollapsing}" id="navbarSupportedContent">
<ul class="navbar-nav nav-dropdown" data-app-modern-menu="true">
<li class="nav-item" v-for="link in datalinks">
<span
class="nav-link link text-black display-4"
:href="link.link"
aria-expanded="false"
>
{{ link.title }}
</span>
</li>
</ul>
<div class="navbar-buttons mbr-section-btn">
<span class="btn btn-primary display-4" @click="clickmain"
>{{ buttontextdata }}</span
>
</div>
</div>
</div>
</nav>
</section>
</template>
<style lang="scss" scoped>
.container {
font-family: "Inter Tight";
}
.btn-primary {
font-weight: 600;
}
.link {
font-weight: 400;
}
#navbarSupportedContent {
transition: all 0.2s ease-in-out;
height: auto;
}
#navbarSupportedContent:not(.show) {
max-height: 0;
padding: 0;
}
#navbarSupportedContent.show {
max-height: 1000px;
padding: 16px;
}
@media (min-width: 1201px) {
#navbarSupportedContent {
max-height: 1000px !important;
height: 100%;
}
}
</style>

View File

@@ -0,0 +1,36 @@
<script setup lang="ts">
import { useRoute, useRouter } from 'vue-router'
import { ref } from "vue";
import AdminPanelLib from "../../adminpanellib.ts";
import Navbar from "../Navbar.vue";
const route = useRoute();
const router = useRouter();
const token=ref(route.params.token);
const userinfo=ref({})
AdminPanelLib.AdminPanelLib.getUserInfo(token.value)
.then((result)=>{
if(result) return result;
else router.push({"path":"/adminpanel/login"});
})
.then((result)=>userinfo.value=result);
const links=[
{ "title":"Startseite", "link":"/adminpanel/"+token.value },
{ "title":"Formulare", "link":"/adminpanel/"+token.value+"/formulare" },
{ "title":"Events", "link":"/adminpanel/"+token.value+"/events" }
]
function logout(){
router.push({"path":"/adminpanel/login"});
}
</script>
<template>
<Navbar :links="links" buttontext="Abmelden" @clickbtn="logout"/>
</template>
<style scoped lang="scss">
</style>

View File

@@ -0,0 +1,64 @@
<script setup lang="ts">
import { ref, defineProps, computed } from "vue";
const props = defineProps({
modelValue: {
type: [String,Boolean,Number],
default: null,
},
nullable: {
type: Boolean,
default: false,
},
inputtype: {
type: String,
default: "text",
required: false
}
});
const firstValue = props.modelValue;
const isNull = ref(firstValue == null);
const emit = defineEmits(["update:modelValue", "isNull"]);
const value = computed({
get: () => props.modelValue,
set: (v) => {
emit("update:modelValue", v);
},
});
if(value.value==null && props.nullable==false){
isNull.value=false;
value.value="";
}
const editing = ref(false);
</script>
<template>
<form v-if="editing" @submit.prevent="editing = false">
<input
:type="props.inputtype"
:placeholder="firstValue"
v-model="value"
v-if="!isNull"
/>
<label for="nullCheckbox" v-if="nullable">Null: </label>
<input
id="nullCheckbox"
type="checkbox"
v-if="nullable"
@change="value=isNull?null:value"
v-model="isNull"
/>
<input type="submit" value="Speichern" />
</form>
<i v-else-if="value=='' && !isNull && props.inputtype!='checkbox'" @dblclick="editing=true">EMPTY</i>
<p v-else-if="!isNull" @dblclick="editing = true">{{ value }}</p>
<i v-else @dblclick="editing = true">NULL</i>
</template>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,106 @@
<script>
export default {
}
</script>
<template>
<div class="loading-container">
<div class="loading-main">
<h1>Lade...</h1>
<div class="dots-bars-6"></div>
</div>
</div>
</template>
<style scoped>
h1{
margin-bottom: 50px;
}
.loading-container {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: 0;
background-color: rgba(0, 0, 0, 0.5);
width: 100%;
height: 100%;
z-index: 100;
align-items: center;
justify-content: center;
display: flex;
}
.loading-main{
display: flex;
justify-content: center;
align-items: center;
height: 50%;
width: 50%;
background-color: white;
border-radius: 20px;
flex-direction: column;
}
.dots-bars-6 {
width: 40px;
height: 20px;
--c:radial-gradient(farthest-side,currentColor 93%,#0000);
background:
var(--c) 0 0,
var(--c) 50% 0;
background-size:8px 8px;
background-repeat: no-repeat;
position: relative;
clip-path: inset(-200% -100% 0 0);
animation: db6-0 1.5s linear infinite;
}
.dots-bars-6:before {
content: "";
position: absolute;
width: 8px;
height: 12px;
background:currentColor;
left:-16px;
top:0;
animation:
db6-1 1.5s linear infinite,
db6-2 0.5s cubic-bezier(0,200,.8,200) infinite;
}
.dots-bars-6:after {
content: "";
position: absolute;
inset:0 0 auto auto;
width:8px;
height: 8px;
border-radius: 50%;
background:currentColor;
animation: db6-3 1.5s linear infinite;
}
@keyframes db6-0 {
0%,30% {background-position: 0 0 ,50% 0 }
33% {background-position: 0 100%,50% 0 }
41%,63% {background-position: 0 0 ,50% 0 }
66% {background-position: 0 0 ,50% 100%}
74%,100%{background-position: 0 0 ,50% 0 }
}
@keyframes db6-1 {
90% {transform:translateY(0)}
95% {transform:translateY(15px)}
100% {transform:translateY(15px);left:calc(100% - 8px)}
}
@keyframes db6-2 {
100% {top:-0.1px}
}
@keyframes db6-3 {
0%,80%,100% {transform:translate(0)}
90% {transform:translate(26px)}
}
</style>

View File

@@ -0,0 +1,161 @@
<script lang="js">
import RitzenbergenLib from "../../ritzenbergenlib.ts";
import Modal from "../Modal.vue";
export default {
props: {
ergebnisse: {
type: Array,
required: true,
},
maxspieltag: {
type: Number,
required: true,
},
tipps: {
type: Array,
required: true,
},
users: {
type: Array,
required: true,
},
},
data() {
return {
RitzenbergenLib,
showmodal: false,
modalindex: 0,
};
},
components: {
Modal,
},
methods: {
ps(heim, gast, ergebnisHeim, ergebnisGast) {
if(heim == ergebnisHeim && gast == ergebnisGast) {
return 3;
}
const tippDiff = heim - gast;
const ergebnisDiff = ergebnisHeim - ergebnisGast;
if(tippDiff === ergebnisDiff) {
return 2;
}
if(heim > gast && ergebnisHeim > ergebnisGast) {
return 1;
}
if(heim < gast && ergebnisHeim < ergebnisGast) {
return 1;
}
return 0;
},
},
};
</script>
<template>
<section class="buli-results scroll-x" id="buliresults-section">
<br /><br />
<h2>Paarungsergebnisse {{ maxspieltag }}. Spieltag</h2>
<Modal v-if="showmodal" @closemodal="showmodal = false">
<h1 class="detailansichtSchriftart">
Detailansicht {{ maxspieltag }}. Spieltag
</h1>
<h2 class="detailansichtSchriftart">
{{ ergebnisse[modalindex].paarung.heim }} -
{{ ergebnisse[modalindex].paarung.gast }}
</h2>
<h1>
{{ ergebnisse[modalindex].heim }} -
{{ ergebnisse[modalindex].gast }}
</h1>
<table class="detailansichtSchriftart">
<tbody>
<tr>
<td>Name</td>
<td>Tipp</td>
<td>Punkte</td>
<td>Gesamtpunktzahl</td>
</tr>
<tr
v-for="(tipp, i) in tipps.filter(
(tipp) =>
tipp.tipp.paarungsid ==
ergebnisse[modalindex].paarung.id
)"
:key="i"
>
<td>
{{
users.filter((user) => user.id == tipp.user)[0]
.username
}}
</td>
<td>{{ tipp.tipp.heim }} - {{ tipp.tipp.gast }}</td>
<td>{{ ps(tipp.tipp.heim, tipp.tipp.gast, ergebnisse[modalindex].heim, ergebnisse[modalindex].gast) }}</td>
<td>
{{
users.filter((user) => user.id == tipp.user)[0]
.points
}}
</td>
</tr>
</tbody>
</table>
</Modal>
<table>
<tbody>
<tr>
<td>Paarung</td>
<td>Ergebnis</td>
</tr>
<tr v-for="(ergebnis, i) in ergebnisse" :key="i">
<td
@click="
showmodal = true;
modalindex = i;
"
>
<span class="as-link">
<span class="teams">
<span class="team">
<img
:src="
RitzenbergenLib.RitzenbergenLib.api(
'/bulitipp/get-image.php?team=' +
ergebnis.paarung.heim
)
"
alt=""
/>
<p>{{ ergebnis.paarung.heim }}</p>
</span>
<span class="vs"></span>
<span class="team">
<p>{{ ergebnis.paarung.gast }}</p>
<img
:src="
RitzenbergenLib.RitzenbergenLib.api(
'/bulitipp/get-image.php?team=' +
ergebnis.paarung.gast
)
"
alt=""
/>
</span>
</span>
</span>
</td>
<td>
<p>{{ ergebnis.heim }} - {{ ergebnis.gast }}</p>
</td>
</tr>
</tbody>
</table>
</section>
</template>
<style scoped>
@import "../../assets/css/bulitipp2.css";
h1 {
text-align: center;
}
</style>

View File

@@ -0,0 +1,98 @@
<script lang="ts">
import ritzenbergenlib from '../../ritzenbergenlib';
import Modal from '../Modal.vue';
export default {
props: {
users: {
type: Array,
required: true
},
spieltag: {
type: Number,
required: true
},
results: {
type: Array,
required: true
},
tipps: {
type: Array,
required: true
}
},
computed: {
},
data(){
return {
modalOpen: false,
currentuser: null
}
},
components: {
Modal
},
methods: {
getById(results,paarungsid){
return results.find((result) => {
return result.paarung.id === paarungsid;
});
},
},
asyncComputed: {
spiele: {
get(){
if(this.spieltag==null) return;
if(this.currentuser==null) return;
return ritzenbergenlib.Spiel.fetchSpiele(this.spieltag-1, this.currentuser.id);
},
watch: ["spieltag","currentuser"],
default: []
}
}
}
</script>
<template>
<section class="rangliste" id="rangliste-sektion">
<br /><br />
<Modal v-if="modalOpen" @closemodal="modalOpen = false">
<h1 class="detailansichtSchriftart">Detailansicht für {{ currentuser.username }}, {{ spieltag }}. Spieltag</h1>
<table>
<tr>
<td>Tipps von {{ currentuser.username }}</td>
<td>Ergebnis</td>
<td>Tipp</td>
<td>Punkte</td>
</tr>
<tr v-for="(spiel,i) in spiele">
<td>{{ spiel.paarung.heim }} - {{ spiel.paarung.gast }}</td>
<td>{{ spiel.result[0] }} - {{ spiel.result[1] }}</td>
<td v-if="spiel.tipp!=null">{{ spiel.tipp[0] }} - {{ spiel.tipp[1] }}</td>
<td v-else>-</td>
<td>{{ spiel.calcPoints() }}</td>
</tr>
</table>
</Modal>
<h2>Rangliste</h2>
<table>
<tbody>
<tr>
<td>Platz</td>
<td>Name</td>
<td>Punkte</td>
</tr>
<tr v-for="(user, i) in users">
<td>{{ i+1 }}</td>
<td @click="modalOpen=true; currentuser=user">
<span class="as-link">{{ user.username }}</span>
</td>
<td>{{ user.points }}</td>
</tr>
</tbody>
</table>
</section>
</template>
<style scoped>
@import "../../assets/css/bulitipp2.css";
</style>

View File

@@ -0,0 +1,105 @@
<script lang="ts">
import ritzenbergenlib from "../../ritzenbergenlib";
import Modal from "../Modal.vue";
export default {
props: {
users: {
type: Array,
required: true,
},
ts: {
type: null,
required: true,
},
},
methods: {
closeModal(){
this.modalOpen=false;
},
openModal(spieltag, user){
this.modalOpen=true;
this.spieltag=spieltag;
this.user=user;
},
},
components: {
Modal,
},
data(){
return {
modalOpen: false,
spieltag: null,
user: null,
RitzenbergenLib: ritzenbergenlib.RitzenbergenLib
}
},
computed: {
},
asyncComputed: {
modalContent: {
get(): Array<ritzenbergenlib.Spiel>{
if(this.spieltag==undefined) return [];
return ritzenbergenlib.Spiel.fetchSpiele(this.spieltag,this.ts[this.spieltag][this.user].user.id);
},
default: []
}
}
};
</script>
<template>
<Modal v-if="modalOpen" @closemodal="closeModal"
><h1 class="detailansichtSchriftart">
Detailansicht für {{ ts[spieltag][user].user.username }},
{{ spieltag + 1 }}. Spieltag
</h1>
<table>
<tr>
<td>Tipp von {{ ts[spieltag][user].user.username }}</td>
<td>Ergebnis</td>
<td>Tipp</td>
<td>Punkte</td>
</tr>
<tr v-for="spiel in modalContent">
<td>{{ spiel.paarung.heim }} - {{ spiel.paarung.gast }}</td>
<td>{{ spiel.result[0] }} - {{ spiel.result[1] }}</td>
<td v-if="spiel.tipp!=null">{{ spiel.tipp[0] }} - {{ spiel.tipp[1] }}</td>
<td v-else> - </td>
<td>{{ spiel.calcPoints() }}</td>
</tr>
</table>
</Modal>
<section class="buli-table" id="buli-table">
<br /><br />
<h2>Punktetabelle</h2>
<table>
<tbody>
<tr>
<td>Tag</td>
<td v-for="spieltag in ts[0]">{{ spieltag.user.username }}</td>
</tr>
<tr v-for="(spieltag, i) in ts">
<td>{{ i + 1 }}</td>
<!-- Open BTN -->
<td
class="as-link"
v-for="(userpoints, j) in spieltag"
@click="openModal(i, j)"
>
{{ userpoints.tsPoints }}
</td>
</tr>
<tr>
<td>Summe</td>
<td v-for="user in users">{{ user.points }}</td>
</tr>
</tbody>
</table>
</section>
</template>
<style scoped>
@import "../../assets/css/bulitipp2.css";
</style>

View File

@@ -0,0 +1,229 @@
<script lang="ts">
import ritzenbergenlib from "../../ritzenbergenlib";
import "../../assets/css/bulitipp2.css";
export default {
props: {
token: {
type: String,
required: false,
},
},
data() {
return {
spieltag: "",
vmodelspieltag: "",
tipps: [
new ritzenbergenlib.Tipp(null, null, null),
new ritzenbergenlib.Tipp(null, null, null),
new ritzenbergenlib.Tipp(null, null, null),
new ritzenbergenlib.Tipp(null, null, null),
new ritzenbergenlib.Tipp(null, null, null),
new ritzenbergenlib.Tipp(null, null, null),
new ritzenbergenlib.Tipp(null, null, null),
new ritzenbergenlib.Tipp(null, null, null),
new ritzenbergenlib.Tipp(null, null, null)
],
disabled: false,
schongetippt: true
};
},
asyncComputed: {
userinfo: {
get() {
if (this.token == null) return null;
return fetch(
ritzenbergenlib.RitzenbergenLib.api(
"/bulitipp/userinfo.php?token=" + this.token
)
)
.then((response) => response.json())
.catch((error) => {
console.error("Error fetching user info:", error);
return null;
});
},
default: null,
},
paarungen: {
get() {
if (this.spieltag == null) return null;
return fetch(
ritzenbergenlib.RitzenbergenLib.api(
"/bulitipp/paarungen.php?spieltag=" + this.spieltag
)
)
.then((response) => response.json())
.then((response) => response.data)
.then((response) =>
response.map((el) => {
return new ritzenbergenlib.Paarung(el[0], el[1], el[2]);
})
);
},
default: null,
},
maxtippspieltag: {
get(){
return fetch(
ritzenbergenlib.RitzenbergenLib.api(
"/bulitipp/maxtippspieltag.php"
)
)
.then((response) => response.text())
.then((text)=> parseInt(text))
}
},
maxspieltag: {
get(){
return fetch(
ritzenbergenlib.RitzenbergenLib.api(
"/bulitipp/maxspieltag.php"
)
)
.then((response) => response.text())
.then((text)=> parseInt(text))
}
},
mintippspieltag: {
get(): number {
if(this.maxspieltag==34){
this.disabled = true;
return 1;
}else{
this.disabled = false;
return this.maxspieltag + 1;
}
},
watch: ["maxspieltag"]
},
tippupdater:{
get(){
const params = new URLSearchParams({
spieltag: this.spieltag.toString()
});
return fetch(
ritzenbergenlib.RitzenbergenLib.api(
"/bulitipp/tippsuser.php?" + params.toString()),
{
method: "GET",
headers: {
Authorization: "Bearer " + this.token,
},
}
)
.then((response) => response.json())
.then((response) => {
if (response.length > 0) {
return response.map((el:any) => {
if(el==null){
this.schongetippt = false;
return new ritzenbergenlib.Tipp(null, null, null);
}
this.schongetippt=true;
return new ritzenbergenlib.Tipp(
el.paarung,
el.score1,
el.score2
);
});
}
}).then(response=>{
this.tipps=response;
return response;
});
},
watch: ["spieltag"]
},
zeitzutippen: {
get(){
return fetch(
ritzenbergenlib.RitzenbergenLib.api(
"/bulitipp/zeitzutippen.php"
)
)
.then((response) => response.json());
}
}
},
emits: ["logout"],
methods: {
getTeamImage(team: string) {
return ritzenbergenlib.RitzenbergenLib.api(
"/bulitipp/get-image.php?team=" + team
);
},
async tippen(){
this.tipps.forEach((tipp, i) => {
tipp.paarung = this.paarungen[i];
});
const params = new URLSearchParams({
spieltag: this.spieltag.toString(),
tipps: JSON.stringify(this.tipps)
});
let result=await fetch(
ritzenbergenlib.RitzenbergenLib.api("/bulitipp/tippeintragen.php?"+params.toString()),
{
method: "GET",
headers: {
Authorization: "Bearer " + this.token,
},
}
);
this.spieltag = "";
}
},
};
</script>
<template>
<div>
<div v-if="(spieltag == '' || spieltag == null) && userinfo != null">
<h1>Moin {{ userinfo.username }}!</h1>
<br />
<h4 v-if="zeitzutippen!=null">Du hast noch <span v-if="zeitzutippen.days!=0">{{ zeitzutippen.days }} Tage und </span>{{ zeitzutippen.hours }} Stunden Zeit, den {{ zeitzutippen.spieltag }}. Spieltag zu tippen.</h4>
<br />
<div v-if="disabled">
<h3>Gerade kann nicht getippt werden.</h3><br>
</div>
<form @submit.prevent="spieltag = parseInt(vmodelspieltag)">
<input
type="number"
v-model="vmodelspieltag"
:placeholder="'Spieltag (max: '+maxtippspieltag+')'"
:min="mintippspieltag"
:max="maxtippspieltag"
required
:disabled="disabled"
/>
<input type="submit" value="Tippen" :disabled="disabled" />
<br /><br />
<input type="button" value="Ausloggen" @click="$emit('logout')" class="red-button" />
</form>
</div>
<div class="tippenEintragen" v-else>
<form @submit.prevent="tippen" id="mainform">
<span class="paarung" v-for="(paarung,i) in paarungen" :key="paarung.id">
<img :src="getTeamImage(paarung.heim)" alt="" />
<span class="team-name">{{ paarung.heim }}</span>
<input v-model="tipps[i].heim" type="number" min="0" class="score" required />
<span class="vs"></span>
<input v-model="tipps[i].gast" type="number" min="0" class="score" required />
<span class="team-name">{{ paarung.gast }}</span>
<img :src="getTeamImage(paarung.gast)" alt="" /><br />
</span>
<input type="submit" :value="schongetippt?'Tipps aktualisieren':'Tippen'" class="green-button"/>
<br /><br />
<input type="button" value="Abbrechen" @click="spieltag = ''" class="red-button" />
</form>
</div>
</div>
</template>
<style scoped>
img {
width: 30px;
}
</style>

View File

@@ -0,0 +1,40 @@
<script lang="ts">
import CryptoJS from 'crypto-js';
export default {
data() {
return {
kuerzel: "",
password: ""
}
},
methods: {
login(){
this.$emit("login", this.kuerzel, CryptoJS.SHA256(this.password).toString(CryptoJS.enc.Hex));
this.kuerzel="";
this.password="";
}
},
props: {
wrongpassword: {
type: Boolean,
default: false
}
},
emits: ["login"]
}
</script>
<template>
<div>
<h1>Einloggen</h1>
<form @submit.prevent="login">
<input type="text" placeholder="Kürzel" v-model="kuerzel" required />
<input type="password" placeholder="Passwort" v-model="password" required />
<input type="submit" value="Einloggen">
<div v-if="wrongpassword">
Falsches Passwort oder Kürzel! Bitte versuche es erneut.
</div>
</form>
</div>
</template>

View File

@@ -0,0 +1,72 @@
<script lang="ts">
import Modal from "../Modal.vue"
export default {
props: {
users: {
type: Array,
required: true
},
spieltag: {
type: Number,
required: false
},
tipps: {
type: Array,
required: true
},
paarungen: {
type: Array,
required: true
}
},
data(){
return {
currentuser: null,
modalOpen: false
}
},
components: {
Modal
}
}
</script>
<template>
<section class="uebersicht scroll-x">
<table>
<tbody>
<tr>
<td v-for="user in users" @click="currentuser=user; modalOpen=true">{{ user.kuerzel }}</td>
</tr>
<tr>
<td v-for="user in users" :style='{"color": user.hatgetippt()?"green":"red"}' @click="currentuser=user; modalOpen=true">{{ user.points }}</td>
</tr>
</tbody>
</table>
</section>
<Modal v-if="modalOpen" @closemodal="modalOpen=false">
<div v-if="spieltag!=undefined">
<h1>Detailansicht für {{ currentuser.username }}, {{ spieltag }}. Spieltag</h1>
<table>
<thead>
<tr>
<td>Paarung</td>
<td>Tipp von {{ currentuser.username }}</td>
</tr>
</thead>
<tbody>
<tr v-for="tipp, i in tipps.filter(t=>t.user==currentuser.id)">
<td>{{ paarungen[i].heim }} - {{ paarungen[i].gast }}</td>
<td>{{ tipp.tipp.heim }} - {{ tipp.tipp.gast }}</td>
</tr>
</tbody>
</table>
</div>
<div v-else>
<h1>Lade...</h1>
</div>
</Modal>
</template>
<style scoped>
@import "../../assets/css/bulitipp2.css";
</style>

View File

@@ -0,0 +1,111 @@
<script lang="ts" setup>
import RitzenbergenLib from "../../ritzenbergenlib.ts";
import {ref} from "vue";
async function loadImage(path: string) {
try{
const response = await fetch(RitzenbergenLib.RitzenbergenLib.api(path), {
headers: {
"Accept":"image/png"
}
});
if(!response.ok) return false;
const blob = await response.blob();
return URL.createObjectURL(blob);
}
catch(e){
console.warn(e);
}
}
loadImage("randomimage.php?path=/doppelkopf&recursive=1&tn=1&color=white&text=Doppelkopf&size=3").then((url)=>{
images.value[0]=url;
});
loadImage("randomimage.php?path=/erntefest&recursive=1&tn=1&color=white&text=Erntefest&size=3").then((url)=>{
images.value[1]=url;
});
loadImage("randomimage.php?path=/fussball&recursive=1&tn=1&color=white&text=Fußballturnier&size=3").then((url)=>{
images.value[2]=url;
});
loadImage("randomimage.php?path=/osterfeuer&recursive=1&tn=1&color=white&text=Osterfeuer&size=3").then((url)=>{
images.value[3]=url;
});
const images=ref([]);
</script>
<template>
<section
class="gallery09 cid-u6k7q0xbqP"
id="gallery-9-u6k7q0xbqP"
v-if="images[0]"
>
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-12 col-lg-4 main-text">
<div class="">
<h5
class="mbr-section-title mbr-fonts-style mt-0 mb-4 display-2"
>
<strong>Bilderbuch Ritzenbergen</strong>
</h5>
<h6
class="mbr-section-subtitle mbr-fonts-style mt-0 mb-4 display-7"
>
Klicke auf ein Bild um in unsere Galerie zu
gelangen. Die Bilder sind nach Jahreszahl und
Kategorie geordnet.
</h6>
</div>
</div>
<div class="col-lg-8 side-features row">
<div
class="item features-image col-12 col-md-6 col-lg-6 active"
>
<div class="item-wrapper">
<div class="item-img">
<RouterLink to="/galerie/doppelkopf"
><img :src="images[0]"
/></RouterLink>
</div>
</div>
</div>
<div
class="item features-image col-12 col-md-6 col-lg-6 active"
>
<div class="item-wrapper">
<div class="item-img">
<RouterLink to="/galerie/erntefest"
><img :src="images[1]"
/></RouterLink>
</div>
</div>
</div>
<div
class="item features-image col-12 col-md-6 col-lg-6 active"
>
<div class="item-wrapper">
<div class="item-img">
<RouterLink to="/galerie/fussball"
><img :src="images[2]"
/></RouterLink>
</div>
</div>
</div>
<div
class="item features-image col-12 col-md-6 col-lg-6 active"
>
<div class="item-wrapper">
<div class="item-img">
<RouterLink to="/galerie/osterfeuer"
><img :src="images[3]"
/></RouterLink>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<style></style>

View File

@@ -0,0 +1,162 @@
<script lang="ts" setup>
import RitzenbergenLib from "../../ritzenbergenlib";
import Modal from "../Modal.vue";
import MarkdownRender from "vue-renderer-markdown";
import "katex/dist/katex.min.css";
import Forms from "./Forms.vue";
import { ref } from "vue";
import { EventType, MyEvent } from "../../dto/event.dto.js";
const initdone=ref(false);
const events = ref<MyEvent[]>([]);
const openedModals=ref<number[]>([]);
const modaltypes=[EventType.html,EventType.markdown];
async function init() {
events.value=(await RitzenbergenLib.graphqlClient.request<{events: MyEvent[]}>
(`{
events {
id
eventname
type
minitext
datum
content
link
foto
formular
}
}`)).events;
console.log(events.value);
}
init().then(()=>{
initdone.value=true;
});
function format_date(date: string){
return new Date(date).toDateString();
}
function vorschautext(str: string){
return str;
}
</script>
<template>
<section class="features03 cid-u6k7q0xyDG" id="news-1-u6k7q0xyDG" v-if="initdone">
<div class="container-fluid">
<div class="row justify-content-center mb-5">
<div class="col-12 content-head">
<div class="mbr-section-head">
<h4
class="mbr-section-title mbr-fonts-style align-center mb-0 display-2"
>
<strong>Termine & Neuigkeiten</strong>
</h4>
</div>
</div>
</div>
<div class="row" v-if="events">
<!-- Events -->
<h5 class="align-center" v-if="events.length == 0">
Es stehen keine Events an.
</h5>
<div
v-for="(event, i) in events"
:key="i"
class="item features-image col-12 col-md-6 col-lg-3"
:class="{ active: i % 4 == 0 }"
>
<Modal
v-show="
openedModals.includes(event.id) &&
modaltypes.includes(event.type)
"
@closemodal="
openedModals.splice(
openedModals.indexOf(event.id),
1
)
"
>
<MarkdownRender
v-if="event.type == EventType.markdown"
:content="event.content"
/>
<div v-else v-html="event.content"></div>
<Forms v-if="event.formular" :formid="event.formular"/>
</Modal>
<div class="item-wrapper">
<div class="item-img mb-3">
<img :src="RitzenbergenLib.RitzenbergenLib.get_img(event.foto)" />
</div>
<div class="item-content align-left">
<h6
class="item-subtitle mbr-fonts-style mt-0 mb-3 display-5"
>
<strong
><a
class="text-black fw-bold"
:data-id="event.id"
>{{ event.eventname }}</a
></strong
>
</h6>
<p class="mbr-text mbr-fonts-style mb-3 display-7">
{{ format_date(event.datum) }}
</p>
<p class="mbr-text mbr-fonts-style mb-3 display-7">
{{ vorschautext(event.minitext) }}
</p>
<div class="mbr-section-btn item-footer">
<a
:download="
event.type == 'dlink'
? event.link
: undefined
"
:href="event.link"
><button
class="btn item-btn btn-primary display-7"
:data-id="event.id"
@click="openedModals.push(event.id)"
>
<span v-if="event.type == 'link'"
>Einladung öffnen</span
>
<span v-else-if="event.type == 'dlink'"
>Einladung runterladen</span
>
<span
v-else-if="event.type == 'fotos'"
@click="galerie(event.content)"
>Fotos ansehen</span
>
<span v-else>Mehr</span>
</button></a
>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-else>
<h1>Keine Internetverbindung!</h1>
</div>
</div>
</section>
</template>
<style></style>

View File

@@ -0,0 +1,184 @@
<script lang="ts" setup>
import RitzenbergenLib from "../../ritzenbergenlib";
import FormResults from "../FormResults.vue";
import { ref } from "vue";
import Modal from "../Modal.vue";
import { Formular } from "../../dto/formular.dto";
async function init() {
forms.value=await RitzenbergenLib.graphqlClient.request<{formulare: Formular[] }>(`
{
formulare {
id
name
minitext
ispublic
fields {
id
name
displayname
displayvalue
placeholder
type
title
required
maxlength
min
max
checked
value
}
}
}
`
).then(data=>data.formulare);
console.log(forms.value);
}
const forms = ref([] as Formular[]);
const props=defineProps({
formid: {
type: [Number, null],
required: false,
default: null
}
});
init();
function submit($event: Event) {
const url = new URL(
RitzenbergenLib.RitzenbergenLib.api("/formulare/submit.php")
);
const formData = new FormData(<HTMLFormElement>$event.target);
fetch(url.toString(), {
method: "POST",
body: formData
}).then(() => {
init();
values.value={};
});
}
const modalOpened=ref<boolean>(false);
const openedForm=ref<Formular|null>(null);
function openModal(form: Formular){
openedForm.value=form;
modalOpened.value=true;
}
const values=ref({});
</script>
<template>
<Modal v-if="openedForm && openedForm.ispublic" v-show="modalOpened" @closemodal="modalOpened=false">
<FormResults v-if="modalOpened" :form="openedForm"/>
</Modal>
<section ref="anmeldeformular" id="anmeldeformular">
<section class="form5 cid-u6k7q0BfGa">
<div class="container" v-for="(form, i) in forms" :key="i">
<div class="row justify-content-center">
<div class="col-12 content-head">
<div class="mbr-section-head mb-5">
<h3
class="mbr-section-title mbr-fonts-style align-center mb-0 display-2"
>
<strong>{{ form.name }}</strong>
</h3>
<br />
<h5 style="text-align: center">
<b @click="openModal(form)" class="fakelink" v-if="form.ispublic">{{ form.minitext }}
</b> <b v-else>{{ form.minitext }}</b> <br />
</h5>
<br />
</div>
</div>
</div>
<div class="row justify-content-center">
<div
class="col-lg-8 mx-auto mbr-form"
data-form-type="formoid"
>
<form
class="mbr-form form-with-styler"
data-form-title="Form Name"
:data-formid="form.id"
:data-i="i"
@submit.prevent="submit"
>
<div v-for="(field, j) in form.fields" :key="j">
<label
v-if="field.placeholder == null"
:for="'field-' + field.id"
>
{{
field.displayvalue ?? field.displayname ?? field.name
}}:
<span v-if="field.type == 'range'"
><br />{{ values[field.id] }}</span
>
</label>
<FormKit
v-if="field.type != 'textarea'"
:id="'field-' + field.id"
:type="field.type"
:name="field.name"
:placeholder="field.placeholder"
:required="field.required"
:maxlength="field.maxlength"
:min="field.min"
:max="field.max"
:checked="field.checked"
:title="field.title"
:value="field.value"
v-model="values[field.id]"
/>
<textarea
v-else
:id="'field-' + field.id"
:name="field.name"
:placeholder="field.placeholder"
:required="field.required"
:maxlength="field.maxlength"
:title="field.title"
:value="field.value"
></textarea>
</div>
<div
class="col-lg-12 col-md-12 col-sm-12 align-center mbr-section-btn"
>
<button
type="submit"
class="btn btn-primary display-7 formular-submit-button"
>
Absenden
</button>
</div>
<input type="hidden" :value="form.id" name="internalformid" />
</form>
</div>
</div>
<br/>
<br/>
<br/>
<br/>
</div>
</section>
</section>
</template>
<style scoped>
label {
margin-right: 10px;
}
.fakelink{
color: blue;
text-decoration: underline;
cursor: pointer;
}
</style>

View File

@@ -0,0 +1,60 @@
<template>
<div class="parallax-wrapper">
<div
class="jarallax"
ref="parallaxEl"
data-speed="0.5"
>
<div class="jarallax-img" style="background-image: url('https://ritzenbergen.de/Fotos/erntefest2011.jpg');">
</div>
<div class="container content cid-u6k7q0zosO">
<slot></slot>
</div>
</div>
</div>
</template>
<script>
import { jarallax } from 'jarallax';
import 'jarallax/dist/jarallax.css'; // optional, falls du Styles möchtest
export default {
name: 'ParallaxSection',
mounted() {
jarallax(this.$refs.parallaxEl);
},
beforeDestroy() {
jarallax(this.$refs.parallaxEl, 'destroy');
},
};
</script>
<style scoped>
.parallax-wrapper {
overflow: hidden;
}
.jarallax-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
z-index: -1;
}
.container {
position: relative;
z-index: 1;
padding: 100px;
text-align: center;
}
slot{
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,82 @@
<script>
import Jarallax from './Jarallax.vue';
export default {
components: {
Jarallax,
},
}
</script>
<template>
<Jarallax>
<div class="row justify-content-center">
<div class="card col-12 col-md-12 col-lg-10">
<div class="card-wrapper">
<div class="card-box align-center">
<h1 class="card-title mbr-fonts-style mb-4 display-1">
<strong style="color: black;">Entdecke die Umgebung</strong>
</h1>
<p class="mbr-text mbr-fonts-style mb-4 display-7">
Hier findest du nützliche Links aus der Umgebung
</p>
<section class="umgebung">
<div>
<ul>
<b>
<li><a href="https://alt-blender.de" target="_blank">alt-blender.de - Historische Fotos und
Dokumente aus
Blender und umzu</a></li>
</b>
<b>
<li><a href="https://www.verden.de/" target="_blank">Verden/Aller</a></li>
</b>
<b>
<li><a href="https://www.langwedel.de/" target="_blank">Flecken Langwedel</a></li>
</b>
<b>
<li><a href="https://www.feuerwehr-blender.de/" target="_blank">Freiwillige Feuerwehr
Blender</a></li>
</b>
<b>
<li><a href="https://www.browiede.de/" target="_blank">Landgasthaus Browiede</a></li>
</b>
<b>
<li><a href="https://www.mittelweserverband.de/" target="_blank">Mittelweserverband</a></li>
</b>
<b>
<li><a href="http://angelverein-doerverden.de/" target="_blank">Angelverein Dörverden</a></li>
</b>
<b>
<li><a href="https://www.theater-holtum.de/" target="_blank">Theatergruppe des gemischten
Chores "Polyhymnia"
Holtum Marsch</a></li>
</b>
<b>
<li><a href="https://www.thedinghausen.de/" target="_blank">Samtgemeinde Thedinghausen</a>
</li>
</b>
<b>
<li><a href="https://www.tsv-blender.de/">TSV Blender</a></li>
</b>
<b>
<li><a href="https://tsvintschede.de-zign.de/">TSV "Weserstrand" Intschede</a></li>
</b>
<b>
<li><a href="https://www.intscheder-bauernhofeis.de/">Intscheder Bauernhofeis</a></li>
</b>
</ul>
</div>
</section>
</div>
</div>
</div>
</div>
</Jarallax>
</template>
<style>
li{
list-style: none;
}
</style>

View File

@@ -0,0 +1,43 @@
<script lang="ts">
export default {
}
</script>
<template>
<section
class="header16 cid-u6k7q0xIhk mbr-fullscreen mbr-parallax-background"
id="hero-17-u6k7q0xIhk"
>
<div
class="mbr-overlay"
style="opacity: 0.3; background-color: rgb(0, 0, 0)"
></div>
<div class="container-fluid">
<div class="row">
<div class="content-wrap col-12 col-md-10">
<h1
class="mbr-section-title mbr-fonts-style mbr-white mb-4 display-1"
>
<strong>Willkommen auf ritzenbergen.de</strong>
</h1>
<p class="mbr-fonts-style mbr-text mbr-white mb-4 display-7">
Dies ist eine private Homepage über das Dorfleben in Amedorf und
Ritzenbergen
</p>
<div class="mbr-section-btn">
<a
class="btn btn-white-outline display-7"
href="#gallery-9-u6k7q0xbqP"
>Erkunden</a
>
</div>
</div>
</div>
</div>
</section>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,27 @@
<script lang="ts">
export default {
}
</script>
<template>
<section class="article12 cid-u6k7q0yKNv" id="about-us-12-u6k7q0yKNv">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12 col-lg-10">
<h3 class="mbr-section-title mbr-fonts-style mb-4 mt-0 display-2">
<strong>Willkommen in Ritzenbergen</strong>
</h3>
<p class="mbr-text mbr-fonts-style display-7">Ritzenbergen, ehemalig "Rikinburg" wurde nur ein einziges Mal im
Jahr 935 in der historischen Überlieferung erwähnt. In diesem Jahr wurde sie vom Edelherren Willarius der
Bremer Kirche geschenkt. Eine Identifikation dieser Burg mit einem auf einer Karte des Amtes Thedinghausen
von 1765 eingetragenen Hügel von etwa 150 m Durchmesser oberhalb eines alten Weserarms in Ritzenbergen ist
aber bisher nicht gesichert.</p>
<p class="mbr-text mbr-fonts-style display-7">Die Gemeinde Amedorf/Ritzenbergen wurde zusammen mit der
Gemeinde Holtum-Marsch im Jahr 1968 in die Gemeinde Blender eingegliedert.</p>
<p class="mbr-text mbr-fonts-style display-7">In der Galerie findest du viele Fotos aus den letzten Jahren.</p>
</div>
</div>
</div>
</section>
</template>
<style scoped></style>