Compare commits
19 Commits
86ec4a640e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
4c36900314
|
|||
|
80186fe737
|
|||
|
50eaf2787d
|
|||
|
7e3cbb0397
|
|||
|
b788a615ba
|
|||
|
2be2e1977b
|
|||
|
01dd736bbc
|
|||
|
48e89305e0
|
|||
|
f4d6f195b3
|
|||
|
21f130e280
|
|||
|
f5f199f510
|
|||
|
7d2b3555f5
|
|||
|
ea6eecc00b
|
|||
|
aa0942ba82
|
|||
|
146aeb9d38
|
|||
|
f9d2c2e367
|
|||
|
be5342f006
|
|||
|
3a3e29e288
|
|||
|
7f663e4368
|
23
CLAUDE.md
Normal file
23
CLAUDE.md
Normal file
@@ -0,0 +1,23 @@
|
||||
You are able to use the Svelte MCP server, where you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively:
|
||||
|
||||
## Available MCP Tools:
|
||||
|
||||
### 1. list-sections
|
||||
|
||||
Use this FIRST to discover all available documentation sections. Returns a structured list with titles, use_cases, and paths.
|
||||
When asked about Svelte or SvelteKit topics, ALWAYS use this tool at the start of the chat to find relevant sections.
|
||||
|
||||
### 2. get-documentation
|
||||
|
||||
Retrieves full documentation content for specific sections. Accepts single or multiple sections.
|
||||
After calling the list-sections tool, you MUST analyze the returned documentation sections (especially the use_cases field) and then use the get-documentation tool to fetch ALL documentation sections that are relevant for the user's task.
|
||||
|
||||
### 3. svelte-autofixer
|
||||
|
||||
Analyzes Svelte code and returns issues and suggestions.
|
||||
You MUST use this tool whenever writing Svelte code before sending it to the user. Keep calling it until no issues or suggestions are returned.
|
||||
|
||||
### 4. playground-link
|
||||
|
||||
Generates a Svelte Playground link with the provided code.
|
||||
After completing the code, ask the user if they want a playground link. Only call this tool after user confirmation and NEVER if code was written to files in their project.
|
||||
@@ -44,5 +44,10 @@
|
||||
"mongoose": "^8.0.0",
|
||||
"node-cron": "^4.2.1",
|
||||
"sharp": "^0.33.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild"
|
||||
]
|
||||
}
|
||||
}
|
||||
272
src/app.css
Normal file
272
src/app.css
Normal file
@@ -0,0 +1,272 @@
|
||||
/* ============================================
|
||||
BOCKEN.ORG CENTRALIZED STYLES
|
||||
============================================ */
|
||||
|
||||
/* ============================================
|
||||
FONT DEFINITIONS
|
||||
============================================ */
|
||||
|
||||
@font-face {
|
||||
font-family: 'crosses';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(/fonts/crosses.woff2) format('woff2'),
|
||||
url(/fonts/crosses.ttf) format('truetype');
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
COLOR SYSTEM
|
||||
Based on Nord Theme with semantic naming
|
||||
============================================ */
|
||||
|
||||
:root {
|
||||
/* ============================================
|
||||
BASE NORD COLORS
|
||||
Keep original Nord colors for reference
|
||||
============================================ */
|
||||
--nord0: #2E3440;
|
||||
--nord1: #3B4252;
|
||||
--nord2: #434C5E;
|
||||
--nord3: #4C566A;
|
||||
--nord4: #D8DEE9;
|
||||
--nord5: #E5E9F0;
|
||||
--nord6: #ECEFF4;
|
||||
--nord7: #8FBCBB;
|
||||
--nord8: #88C0D0;
|
||||
--nord9: #81A1C1;
|
||||
--nord10: #5E81AC;
|
||||
--nord11: #BF616A;
|
||||
--nord12: #D08770;
|
||||
--nord13: #EBCB8B;
|
||||
--nord14: #A3BE8C;
|
||||
--nord15: #B48EAD;
|
||||
|
||||
/* Named color aliases (backward compatibility) */
|
||||
--lightblue: var(--nord9);
|
||||
--blue: var(--nord10);
|
||||
--red: var(--nord11);
|
||||
--orange: var(--nord12);
|
||||
--yellow: var(--nord13);
|
||||
--green: var(--nord14);
|
||||
--purple: var(--nord15);
|
||||
|
||||
/* ============================================
|
||||
SEMANTIC COLOR SYSTEM - LIGHT MODE
|
||||
============================================ */
|
||||
|
||||
/* Primary Color - Main interactive elements */
|
||||
--color-primary: var(--nord10);
|
||||
--color-primary-hover: var(--nord9);
|
||||
--color-primary-active: var(--nord8);
|
||||
|
||||
/* Accent Color - Call-to-action, emphasis */
|
||||
--color-accent: var(--nord11);
|
||||
--color-accent-hover: #d07179;
|
||||
--color-accent-active: #a04e56;
|
||||
|
||||
/* Secondary Accent - Alternative emphasis */
|
||||
--color-secondary: var(--nord12);
|
||||
--color-secondary-hover: #e09880;
|
||||
--color-secondary-active: #b87060;
|
||||
|
||||
/* Background Colors */
|
||||
--color-bg-primary: #fbf9f3;
|
||||
--color-bg-secondary: var(--nord5);
|
||||
--color-bg-tertiary: var(--nord6);
|
||||
--color-bg-elevated: var(--nord4);
|
||||
|
||||
/* Surface Colors (cards, panels, etc.) */
|
||||
--color-surface: var(--nord6);
|
||||
--color-surface-hover: var(--nord5);
|
||||
|
||||
/* Text Colors */
|
||||
--color-text-primary: var(--nord0);
|
||||
--color-text-secondary: var(--nord3);
|
||||
--color-text-tertiary: var(--nord2);
|
||||
--color-text-inverse: white;
|
||||
--color-text-on-primary: white;
|
||||
--color-text-on-accent: white;
|
||||
--color-text-muted: var(--nord4);
|
||||
|
||||
/* UI Element Colors */
|
||||
--color-ui-dark: var(--nord0);
|
||||
--color-ui-mid: var(--nord3);
|
||||
--color-ui-light: var(--nord4);
|
||||
--color-ui-hover: var(--nord3);
|
||||
|
||||
/* Border Colors */
|
||||
--color-border: var(--nord4);
|
||||
--color-border-hover: var(--nord3);
|
||||
|
||||
/* Link Colors */
|
||||
--color-link: var(--nord11);
|
||||
--color-link-visited: var(--nord15);
|
||||
--color-link-hover: var(--color-accent-hover);
|
||||
|
||||
/* Status Colors */
|
||||
--color-success: var(--nord14);
|
||||
--color-warning: var(--nord13);
|
||||
--color-error: var(--nord11);
|
||||
--color-info: var(--nord10);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
DARK MODE COLOR OVERRIDES
|
||||
============================================ */
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
/* Dark mode custom colors */
|
||||
--nord6-dark: #292c31;
|
||||
--accent-dark: #1f1f21;
|
||||
--background-dark: #21201b;
|
||||
--font-default-dark: #ffffff;
|
||||
|
||||
/* Primary Color - Same but adjusted for dark backgrounds */
|
||||
--color-primary: var(--nord9);
|
||||
--color-primary-hover: var(--nord8);
|
||||
--color-primary-active: var(--nord7);
|
||||
|
||||
/* Accent Color - Slightly lighter for dark mode */
|
||||
--color-accent: #d07179;
|
||||
--color-accent-hover: #e08189;
|
||||
--color-accent-active: var(--nord11);
|
||||
|
||||
/* Secondary Accent */
|
||||
--color-secondary: #e09880;
|
||||
--color-secondary-hover: #f0a890;
|
||||
--color-secondary-active: var(--nord12);
|
||||
|
||||
/* Background Colors */
|
||||
--color-bg-primary: var(--background-dark);
|
||||
--color-bg-secondary: var(--accent-dark);
|
||||
--color-bg-tertiary: var(--nord6-dark);
|
||||
--color-bg-elevated: var(--nord0);
|
||||
|
||||
/* Surface Colors */
|
||||
--color-surface: var(--nord0);
|
||||
--color-surface-hover: var(--nord1);
|
||||
|
||||
/* Text Colors */
|
||||
--color-text-primary: var(--font-default-dark);
|
||||
--color-text-secondary: var(--nord4);
|
||||
--color-text-tertiary: var(--nord5);
|
||||
--color-text-inverse: var(--nord0);
|
||||
--color-text-on-primary: white;
|
||||
--color-text-on-accent: white;
|
||||
--color-text-muted: var(--nord3);
|
||||
|
||||
/* UI Element Colors */
|
||||
--color-ui-dark: var(--nord6);
|
||||
--color-ui-mid: var(--nord4);
|
||||
--color-ui-light: var(--nord3);
|
||||
--color-ui-hover: var(--nord2);
|
||||
|
||||
/* Border Colors */
|
||||
--color-border: var(--nord2);
|
||||
--color-border-hover: var(--nord3);
|
||||
|
||||
/* Link Colors */
|
||||
--color-link: #d07179;
|
||||
--color-link-visited: #c89fb6;
|
||||
--color-link-hover: var(--color-accent-hover);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
BASE STYLES
|
||||
============================================ */
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
font-family: Helvetica, Arial, "Noto Sans", sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: var(--color-bg-primary);
|
||||
color: var(--color-text-primary);
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
LINK STYLES
|
||||
============================================ */
|
||||
|
||||
a:not(:visited) {
|
||||
color: var(--color-link);
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: var(--color-link-visited);
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus-visible {
|
||||
color: var(--color-link-hover);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
FORM STYLES
|
||||
============================================ */
|
||||
|
||||
form {
|
||||
background-color: var(--color-bg-secondary);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 600px;
|
||||
gap: 0.5em;
|
||||
margin-inline: auto;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-block: 2rem;
|
||||
margin-block: 2rem;
|
||||
}
|
||||
|
||||
form label {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
form input {
|
||||
display: block;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
form:not(.search) button {
|
||||
background-color: var(--color-accent);
|
||||
color: var(--color-text-on-accent);
|
||||
border: none;
|
||||
padding: 0.5em 1em;
|
||||
font-size: 1.3em;
|
||||
border-radius: 1000px;
|
||||
margin-top: 1em;
|
||||
transition: 100ms;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
form:not(.search) button:hover,
|
||||
form:not(.search) button:focus-visible {
|
||||
background-color: var(--color-accent-hover);
|
||||
scale: 1.1;
|
||||
}
|
||||
|
||||
form:not(.search) button:active {
|
||||
background-color: var(--color-accent-active);
|
||||
}
|
||||
|
||||
form p {
|
||||
max-width: 400px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
form h4 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
form {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,7 @@ async function authorization({ event, resolve }) {
|
||||
// Bible verse functionality for error pages
|
||||
async function getRandomVerse(fetch: typeof globalThis.fetch): Promise<any> {
|
||||
try {
|
||||
const response = await fetch('/api/bible-quote');
|
||||
const response = await fetch('/api/glaube/bibel/zufallszitat');
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ background-color: var(--red);
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
z-index: 100;
|
||||
}
|
||||
@media screen and (max-width: 500px) {
|
||||
.container{
|
||||
|
||||
@@ -323,6 +323,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.chart-container {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
canvas {
|
||||
max-width: 100%;
|
||||
height: 100% !important;
|
||||
|
||||
259
src/lib/components/BibleModal.svelte
Normal file
259
src/lib/components/BibleModal.svelte
Normal file
@@ -0,0 +1,259 @@
|
||||
<script lang="ts">
|
||||
import type { VerseData } from '$lib/data/mysteryDescriptions';
|
||||
|
||||
export let reference: string = '';
|
||||
export let title: string = '';
|
||||
export let verseData: VerseData | null = null;
|
||||
export let onClose: () => void;
|
||||
|
||||
let book: string = verseData?.book || '';
|
||||
let chapter: number = verseData?.chapter || 0;
|
||||
let verses: Array<{ verse: number; text: string }> = verseData?.verses || [];
|
||||
let loading = false;
|
||||
let error = verseData ? '' : 'Keine Versdaten verfügbar';
|
||||
|
||||
function handleBackdropClick(event: MouseEvent) {
|
||||
if (event.target === event.currentTarget) {
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') {
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={handleKeydown} />
|
||||
|
||||
<div class="modal-backdrop" on:click={handleBackdropClick} role="presentation">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div class="header-content">
|
||||
{#if title}
|
||||
<h3 class="modal-title">
|
||||
{#if title.includes(':')}
|
||||
{title.split(':')[0]}:<br>{title.split(':')[1]}
|
||||
{:else}
|
||||
{title}
|
||||
{/if}
|
||||
</h3>
|
||||
{/if}
|
||||
<p class="modal-reference">{reference}</p>
|
||||
</div>
|
||||
<button class="close-button" on:click={onClose} aria-label="Schließen">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
{#if loading}
|
||||
<p class="loading">Lädt...</p>
|
||||
{:else if error}
|
||||
<p class="error">{error}</p>
|
||||
{:else if verses.length > 0}
|
||||
<div class="verses">
|
||||
{#each verses as verse}
|
||||
<p class="verse">
|
||||
<span class="verse-number">{verse.verse}</span>
|
||||
<span class="verse-text">{verse.text}</span>
|
||||
</p>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<p class="error">Keine Verse gefunden</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.modal-backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
padding: 1rem;
|
||||
animation: show-backdrop 200ms ease forwards;
|
||||
}
|
||||
|
||||
@keyframes show-backdrop {
|
||||
from {
|
||||
backdrop-filter: blur(0px);
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
to {
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.modal-backdrop {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
@keyframes show-backdrop {
|
||||
from {
|
||||
backdrop-filter: blur(0px);
|
||||
background: rgba(255, 255, 255, 0);
|
||||
}
|
||||
to {
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: var(--nord0);
|
||||
border-radius: 12px;
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
max-height: 80vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.modal-content {
|
||||
background: var(--nord6);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding: 1.5rem;
|
||||
border-bottom: 1px solid var(--nord3);
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.modal-header {
|
||||
border-bottom: 1px solid var(--nord4);
|
||||
}
|
||||
}
|
||||
|
||||
.header-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
margin: 0;
|
||||
color: var(--nord10);
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.modal-reference {
|
||||
margin: 0;
|
||||
color: var(--nord8);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
position: absolute;
|
||||
top: -1rem;
|
||||
right: -1rem;
|
||||
background-color: var(--nord11);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 1rem;
|
||||
border-radius: 1000px;
|
||||
color: white;
|
||||
transition: 200ms;
|
||||
box-shadow: 0 0 1em 0.2em rgba(0, 0, 0, 0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.close-button svg {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
background-color: var(--nord0);
|
||||
transform: scale(1.2, 1.2);
|
||||
box-shadow: 0 0 1em 0.4em rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.close-button:active {
|
||||
transition: 50ms;
|
||||
scale: 0.8 0.8;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.error {
|
||||
text-align: center;
|
||||
color: var(--nord4);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.loading,
|
||||
.error {
|
||||
color: var(--nord2);
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--nord11);
|
||||
}
|
||||
|
||||
.verses {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.verse {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
line-height: 1.6;
|
||||
color: var(--nord4);
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.verse {
|
||||
color: var(--nord0);
|
||||
}
|
||||
}
|
||||
|
||||
.verse-number {
|
||||
color: var(--nord10);
|
||||
font-weight: 700;
|
||||
min-width: 2rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.verse-text {
|
||||
flex: 1;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -92,7 +92,7 @@ const img_name=recipe.short_name + ".webp?v=" + recipe.dateModified
|
||||
font-size: 1.5em;
|
||||
box-shadow: 0em 0em 1em 0.1em rgba(0, 0, 0, 0.6);
|
||||
transition: 100ms;
|
||||
z-index: 10;
|
||||
z-index: 5;
|
||||
text-decoration: none;
|
||||
}
|
||||
#image{
|
||||
@@ -179,7 +179,7 @@ const img_name=recipe.short_name + ".webp?v=" + recipe.dateModified
|
||||
box-shadow: 0em 0em 0.2em 0.05em rgba(0, 0, 0, 0.3);
|
||||
border: none;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
z-index: 2;
|
||||
display: inline-block;
|
||||
}
|
||||
.tag:hover,
|
||||
@@ -207,7 +207,7 @@ const img_name=recipe.short_name + ".webp?v=" + recipe.dateModified
|
||||
transition: 100ms;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
z-index: 2;
|
||||
display: inline-block;
|
||||
}
|
||||
.card_title .category:hover,
|
||||
|
||||
@@ -10,9 +10,6 @@ export let onClick;
|
||||
|
||||
<style>
|
||||
.counter-button {
|
||||
position: absolute;
|
||||
bottom: 0.5rem;
|
||||
right: 0.5rem;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
border-radius: 50%;
|
||||
|
||||
@@ -242,4 +242,14 @@
|
||||
font-size: 0.85rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.debt-breakdown {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.debt-section {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -333,6 +333,7 @@
|
||||
.balance-card {
|
||||
min-width: unset;
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.balance-card.enhanced {
|
||||
@@ -343,6 +344,7 @@
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
align-items: flex-start;
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.transaction-count {
|
||||
|
||||
@@ -61,7 +61,6 @@ nav[hidden]{
|
||||
{
|
||||
cursor: pointer;
|
||||
color: var(--red);
|
||||
transform: scale(1.1,1.1);
|
||||
}
|
||||
:global(.site_header) {
|
||||
padding-block: 1.5rem;
|
||||
|
||||
15
src/lib/components/prayers/BruderKlausGebet.svelte
Normal file
15
src/lib/components/prayers/BruderKlausGebet.svelte
Normal file
@@ -0,0 +1,15 @@
|
||||
<p>
|
||||
<v lang="de">Mein Herr und mein Gott,</v>
|
||||
<v lang="de">nimm alles von mir,</v>
|
||||
<v lang="de">was mich hindert zu Dir.</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang="de">Mein Herr und mein Gott,</v>
|
||||
<v lang="de">gib alles mir,</v>
|
||||
<v lang="de">was mich führet zu Dir.</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang="de">Mein Herr und mein Gott,</v>
|
||||
<v lang="de">nimm mich mir</v>
|
||||
<v lang="de">und gib mich ganz zu eigen Dir.</v>
|
||||
</p>
|
||||
@@ -47,7 +47,7 @@
|
||||
<v lang="la">Et resurréxit tértia die,</v>
|
||||
<v lang="de">Er ist auferstanden am dritten Tage,</v>
|
||||
<v lang="la">secúndum Scriptúras.</v>
|
||||
<v lang="de">gemäß der Schrift;</v>
|
||||
<v lang="de">gemäss der Schrift;</v>
|
||||
<v lang="la">Et ascéndit in cáelum:</v>
|
||||
<v lang="de">Er ist aufgefahren in den Himmel</v>
|
||||
<v lang="la">sedet ad déxteram Patris.</v>
|
||||
|
||||
52
src/lib/components/prayers/Gloria.svelte
Normal file
52
src/lib/components/prayers/Gloria.svelte
Normal file
@@ -0,0 +1,52 @@
|
||||
<p>
|
||||
<v lang="la">Glória in excélsis <i><sup>⚬</sup></i> Deo.</v>
|
||||
<v lang="de">Ehre sei <i><sup>⚬</sup></i> Gott in der Höhe.</v>
|
||||
<v lang="la">Et in terra pax homínibus</v>
|
||||
<v lang="de">Und auf Erden Friede den Mesnchen,</v>
|
||||
<v lang="la">bonæ voluntátis.</v>
|
||||
<v lang="de">die guten Willens sind.</v>
|
||||
<v lang="la">Laudámus te.</v>
|
||||
<v lang="de">Wir loben Dich.</v>
|
||||
<v lang="la">Benedícimus te.</v>
|
||||
<v lang="de">Wir preisen Dich.</v>
|
||||
<v lang="la"><i><sup>⚬</sup></i> Adorámus te.</v>
|
||||
<v lang="de"><i><sup>⚬</sup></i> Wir beten Dich an.</v>
|
||||
<v lang="la">Glorificámus te.</v>
|
||||
<v lang="de">Wir verherrlichen Dich.</v>
|
||||
<v lang="la"><i><sup>⚬</sup></i> Grátias ágimus tibi</v>
|
||||
<v lang="de"><i><sup>⚬</sup></i> Wir sagen Dir Dank</v>
|
||||
<v lang="la">propter magnam glóriam tuam.</v>
|
||||
<v lang="de">ob Deiner grossen Herrlichkeit.</v>
|
||||
<v lang="la">Dómine Deus, Rex cæléstis,</v>
|
||||
<v lang="de">Herr und Gott, König des Himmels,</v>
|
||||
<v lang="la">Deus Pater omnípotens.</v>
|
||||
<v lang="de">Gott allmächtiger Vater!</v>
|
||||
<v lang="la">Dómine Fili unigénite, <i><sup>⚬</sup></i> Jesu Christe.</v>
|
||||
<v lang="de">Herr <i><sup>⚬</sup></i> Jesus Christus, eingeborener Sohn!</v>
|
||||
<v lang="la">Dómine Deus, Agnus Dei,</v>
|
||||
<v lang="de">Herr und Gott, Lamm Gottes,</v>
|
||||
<v lang="la">Fílius Patris.</v>
|
||||
<v lang="de">Sohn des Vaters!</v>
|
||||
<v lang="la">Qui tollis peccáta mundi,</v>
|
||||
<v lang="de">Du nimmst hinweg die Sünden der Welt:</v>
|
||||
<v lang="la">miserére nobis.</v>
|
||||
<v lang="de">erbarme Dich unser.</v>
|
||||
<v lang="la">Qui tollis peccáta mundi,</v>
|
||||
<v lang="de">Du nimmst hinwerg die Sünden der Welt.</v>
|
||||
<v lang="la"><i><sup>⚬</sup></i> súscipe depreciatiónem nostram.</v>
|
||||
<v lang="de"><i><sup>⚬</sup></i> nimm unser Flehen gnädig auf.</v>
|
||||
<v lang="la">Qui sedes ad déxteram Patris,</v>
|
||||
<v lang="de">Du sitzt zur Rechten des Vaters:</v>
|
||||
<v lang="la">miserére nobis.</v>
|
||||
<v lang="de">erbarme Dich unser.</v>
|
||||
<v lang="la">Quóniam tu solus Sanctus.</v>
|
||||
<v lang="de">Denn Du allein bist der Heilige.</v>
|
||||
<v lang="la">Tu solus Altíssimus,</v>
|
||||
<v lang="de">Du allein der Höchste,</v>
|
||||
<v lang="la"><i><sup>⚬</sup></i> Jesu Christe.</v>
|
||||
<v lang="de"><i><sup>⚬</sup></i> Jesus Christus,</v>
|
||||
<v lang="la">Cum Sancto Spíritu</v>
|
||||
<v lang="de">Mit dem Hl. Geiste,</v>
|
||||
<v lang="la"><i>♱</i> in glória Dei Patris. Amen.</v>
|
||||
<v lang="de"><i>♱</i> in der Herrlichkeit Gottes des Vaters. Amen.</v>
|
||||
</p>
|
||||
@@ -1,7 +1,7 @@
|
||||
<p>
|
||||
<v lang="la">Glória Patri, et Fílio, et Spirítui Sancto.</v>
|
||||
<v lang="de">Ehre sei dem Vater und dem Sohne und dem Hl. Geiste.</v>
|
||||
<v lang="la">Sicute erat in princípio, et nunc, et semper:</v>
|
||||
<v lang="la">Sicut erat in princípio, et nunc, et semper:</v>
|
||||
<v lang="de">Wie es war am Anfang, so auch jetzt und allezeit</v>
|
||||
<v lang="la">et in sǽcula sæculórum. Amen.</v>
|
||||
<v lang="de">und in Ewigkeit. Amen.</v>
|
||||
|
||||
8
src/lib/components/prayers/JosephGebet.svelte
Normal file
8
src/lib/components/prayers/JosephGebet.svelte
Normal file
@@ -0,0 +1,8 @@
|
||||
<p>
|
||||
<v>Jungfräulicher Vater Jesu,</v>
|
||||
<v>Reinster Bräutigam Mariä,</v>
|
||||
<v>Sankt Joseph, bitte Tag für Tag bei Jesus, dem Sohn Gottes.</v>
|
||||
<v>Seine Kraft und Gnade soll uns stärken,</v>
|
||||
<v>dass wir siegreich streiten im Leben</v>
|
||||
<v>und die Krone von Ihm erhalten im Sterben.</v>
|
||||
</p>
|
||||
22
src/lib/components/prayers/MichaelGebet.svelte
Normal file
22
src/lib/components/prayers/MichaelGebet.svelte
Normal file
@@ -0,0 +1,22 @@
|
||||
<p>
|
||||
<v lang="la">Sáncte Míchael Archángele,</v>
|
||||
<v lang="de">Heiliger Erzengel Michael,</v>
|
||||
<v lang="la">defénde nos in proélio,</v>
|
||||
<v lang="de">verteidige uns im Kampfe!</v>
|
||||
<v lang="la">cóntra nequítam et insídias</v>
|
||||
<v lang="de">Gegen die Bosheit und Nachstellungen</v>
|
||||
<v lang="la">diáboli ésto præsídium.</v>
|
||||
<v lang="de">des Teufels sei unser Schutz. </v>
|
||||
<v lang="la">Ímperet ílli Déus, súpplices deprecámur:</v>
|
||||
<v lang="de">»Gott gebiete ihm!«, so bitten wir flehentlich.</v>
|
||||
<v lang="la">tuque, Prínceps milítæ cæléstis,</v>
|
||||
<v lang="de">Du aber, Fürst der himmlischen Heerscharen,</v>
|
||||
<v lang="la">Sátanam aliósque spíritus malígnos,</v>
|
||||
<v lang="de">stosse den Satan und die anderen bösen Geister,</v>
|
||||
<v lang="la">qui ad perditiónem animárum</v>
|
||||
<v lang="la">pervagántur in múndo,</v>
|
||||
<v lang="de">die in der Welt umhergehen,</v>
|
||||
<v lang="de">um die Seelen zu verderben,</v>
|
||||
<v lang="la">divína virtúte, in inférnum detrúde. Amen.</v>
|
||||
<v lang="de">durch die Kraft Gottes in die Hölle. Amen.</v>
|
||||
</p>
|
||||
24
src/lib/components/prayers/RosaryFinalPrayer.svelte
Normal file
24
src/lib/components/prayers/RosaryFinalPrayer.svelte
Normal file
@@ -0,0 +1,24 @@
|
||||
<p>
|
||||
<v lang="la">Orémus:</v>
|
||||
<v lang="de">Lasset uns beten:</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang="la">Déus, cújus Unigénitus,</v>
|
||||
<v lang="de">O Gott, dessen eingeborner Sohn</v>
|
||||
<v lang="la">pér vítam, mórtem ét resurrectiónem súam</v>
|
||||
<v lang="de">durch sein Leben, seinen Tod und seine Auferstehung</v>
|
||||
<v lang="la">nóbis salútis ætérnæ præmia comparávit:</v>
|
||||
<v lang="de">uns die Belohnung des ewigen Lebens verdient hat,</v>
|
||||
<v lang="la">concéde, quæsumus;</v>
|
||||
<v lang="de">verleihe uns, wir bitten dich,</v>
|
||||
<v lang="la">út, hæc mystéria sanctíssimo beátæ Maríæ Vírginis Rosário recoléntes;</v>
|
||||
<v lang="de">dass wir, indem wir die Geheimisse des heiligen Rosenkranzes der allerseligsten Jungfrau ehren,</v>
|
||||
<v lang="la">ét imitémur quód cóntinent,</v>
|
||||
<v lang="de">was sie enthalten nachahmen</v>
|
||||
<v lang="la">ét quód promíttunt, assequámur.</v>
|
||||
<v lang="de">und dadurch erlangen, was uns in denselben verheissen ist.</v>
|
||||
<v lang="la">Pér eúmdem Chrístum Dóminum nóstrum.</v>
|
||||
<v lang="de">Durch unsern Herrn Jesus Christus.</v>
|
||||
<v lang="la">Ámen.</v>
|
||||
<v lang="de">Amen.</v>
|
||||
</p>
|
||||
@@ -1,11 +1,11 @@
|
||||
<p>
|
||||
<v lang="la">Salve, Regína,</v>
|
||||
<v lang="de">Sei gegrüßt, o Königin,</v>
|
||||
<v lang="de">Sei gegrüsst, o Königin,</v>
|
||||
<v lang="la">máter misericórdiae;</v>
|
||||
<v lang="de">Mutter der Barmherzigkeit,</v>
|
||||
<v lang="la">Víta, dulcédo et spes nóstra, sálve.</v>
|
||||
<v lang="de">unser Leben, unsre Wonne</v>
|
||||
<v lang="de">und unsere Hoffnung, sei gegrüßt!</v>
|
||||
<v lang="de">und unsere Hoffnung, sei gegrüsst!</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang="la">Ad te clamámus, éxsules fílii Hévae.</v>
|
||||
@@ -23,5 +23,5 @@
|
||||
<v lang="la">nóbis post hoc exsílíum osténde.</v>
|
||||
<v lang="de">die gebenedeite Frucht deines Leibes.</v>
|
||||
<v lang="la">O clémens, o pía, o dúlcis Vírgo María.</v>
|
||||
<v lang="de">O gütige, o milde, o süße Jungfrau Maria.</v>
|
||||
<v lang="de">O gütige, o milde, o süsse Jungfrau Maria.</v>
|
||||
</p>
|
||||
|
||||
@@ -19,6 +19,7 @@ i{
|
||||
font-style: normal;
|
||||
color: var(--nord11);
|
||||
font-weight: 900;
|
||||
font-family: 'crosses', sans-serif;
|
||||
}
|
||||
i.txt {
|
||||
font-size: 70%;
|
||||
|
||||
107
src/lib/data/mysteryDescriptions.ts
Normal file
107
src/lib/data/mysteryDescriptions.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
export interface MysteryReference {
|
||||
title: string;
|
||||
reference: string;
|
||||
}
|
||||
|
||||
export interface VerseData {
|
||||
book: string;
|
||||
chapter: number;
|
||||
verses: Array<{ verse: number; text: string }>;
|
||||
}
|
||||
|
||||
export interface MysteryDescription extends MysteryReference {
|
||||
text: string;
|
||||
verseData?: VerseData | null;
|
||||
}
|
||||
|
||||
// Only store references - texts will be fetched at build time
|
||||
export const mysteryReferences = {
|
||||
lichtreichen: [
|
||||
{
|
||||
title: "Das erste lichtreiche Geheimnis: Die Taufe im Jordan.",
|
||||
reference: "Mt 3, 16-17"
|
||||
},
|
||||
{
|
||||
title: "Das zweite lichtreiche Geheimnis: Die Hochzeit von Kana.",
|
||||
reference: "Joh 2, 1-5"
|
||||
},
|
||||
{
|
||||
title: "Das dritte lichtreiche Geheimnis: Die Verkündigung des Reiches Gottes.",
|
||||
reference: "Mk 1, 15"
|
||||
},
|
||||
{
|
||||
title: "Das vierte lichtreiche Geheimnis: Die Verklärung.",
|
||||
reference: "Mt 17, 1-2"
|
||||
},
|
||||
{
|
||||
title: "Das fünfte lichtreiche Geheimnis: Die heiligste Eucharistie (Das Altarssakrament).",
|
||||
reference: "Mt 26, 26"
|
||||
}
|
||||
],
|
||||
freudenreich: [
|
||||
{
|
||||
title: "Das erste freudenreiche Geheimnis: Die Verkündigung des Erzengles Gabriel an die Jungfrau Maria.",
|
||||
reference: "Lk 1, 26-27"
|
||||
},
|
||||
{
|
||||
title: "Das zweite freudenreiche Geheimnis: Der Besuch Marias bei Elisabeth.",
|
||||
reference: "Lk 1, 39-42"
|
||||
},
|
||||
{
|
||||
title: "Das dritte freudenreiche Geheimnis: Die Geburt Jesu im Stall von Bethlehem.",
|
||||
reference: "Lk 2, 1-7"
|
||||
},
|
||||
{
|
||||
title: "Das vierte freudenreiche Geheimnis: Jesus wird von Maria und Josef im Tempel dargebracht.",
|
||||
reference: "Lk 2, 21-24"
|
||||
},
|
||||
{
|
||||
title: "Das fünfte freudenreiche Geheimnis: Jesus wird im Tempel wiedergefunden.",
|
||||
reference: "Lk 2, 41-47"
|
||||
}
|
||||
],
|
||||
schmerzhaften: [
|
||||
{
|
||||
title: "Das erste schmerzhafte Geheimnis: Die Todesangst Jesu.",
|
||||
reference: "Mt 26, 36-39"
|
||||
},
|
||||
{
|
||||
title: "Das zweite schmerzhafte Geheimnis: Die Geißelung Jesu.",
|
||||
reference: "Mt 27, 26"
|
||||
},
|
||||
{
|
||||
title: "Das dritte schmerzhafte Geheimnis: Die Dornenkrönung.",
|
||||
reference: "Mt 27, 27-29"
|
||||
},
|
||||
{
|
||||
title: "Das vierte schmerzhafte Geheimnis: Jesus trägt das schwere Kreuz.",
|
||||
reference: "Mk 15, 21-22"
|
||||
},
|
||||
{
|
||||
title: "Das fünfte schmerzhafte Geheimnis: Die Kreuzigung Jesu.",
|
||||
reference: "Lk 23, 33-46"
|
||||
}
|
||||
],
|
||||
glorreichen: [
|
||||
{
|
||||
title: "Das erste glorreiche Geheimnis: Die Auferstehung Jesu.",
|
||||
reference: "Lk 24, 1-6"
|
||||
},
|
||||
{
|
||||
title: "Das zweite glorreiche Geheimnis: Die Himmerfahrt Jesu.",
|
||||
reference: "Mk 16, 19"
|
||||
},
|
||||
{
|
||||
title: "Das dritte glorreiche Geheimnis: Die Herabkunft des Heiligen Geistes im Abendmahlssaal.",
|
||||
reference: "Apg 2, 1-4"
|
||||
},
|
||||
{
|
||||
title: "Das vierte glorreiche Geheimnis: Die Aufnahme Marias in den Himmel.",
|
||||
reference: "Lk 1, 48-49"
|
||||
},
|
||||
{
|
||||
title: "Das fünfte glorreiche Geheimnis: Die Krönung Marias zur Königin des Himmels und der Erde.",
|
||||
reference: "Offb 12, 1"
|
||||
}
|
||||
]
|
||||
} as const;
|
||||
@@ -77,7 +77,6 @@ export const GET: RequestHandler = async ({ url, locals }) => {
|
||||
];
|
||||
|
||||
const results = await Payment.aggregate(pipeline);
|
||||
console.log('Aggregation results:', results);
|
||||
|
||||
// Transform data into chart-friendly format
|
||||
const monthsMap = new Map();
|
||||
|
||||
@@ -21,7 +21,6 @@ export const POST: RequestHandler = async ({ request }) => {
|
||||
|
||||
try {
|
||||
const now = new Date();
|
||||
console.log(`[Cron] Starting recurring payments processing at ${now.toISOString()}`);
|
||||
|
||||
// Find all active recurring payments that are due
|
||||
const duePayments = await RecurringPayment.find({
|
||||
@@ -34,16 +33,12 @@ export const POST: RequestHandler = async ({ request }) => {
|
||||
]
|
||||
});
|
||||
|
||||
console.log(`[Cron] Found ${duePayments.length} due recurring payments`);
|
||||
|
||||
const results = [];
|
||||
let successCount = 0;
|
||||
let failureCount = 0;
|
||||
|
||||
for (const recurringPayment of duePayments) {
|
||||
try {
|
||||
console.log(`[Cron] Processing recurring payment: ${recurringPayment.title} (${recurringPayment._id})`);
|
||||
|
||||
// Create the payment
|
||||
const payment = await Payment.create({
|
||||
title: `${recurringPayment.title} (Auto)`,
|
||||
@@ -89,8 +84,6 @@ export const POST: RequestHandler = async ({ request }) => {
|
||||
success: true
|
||||
});
|
||||
|
||||
console.log(`[Cron] Successfully processed: ${recurringPayment.title}, next execution: ${nextExecutionDate.toISOString()}`);
|
||||
|
||||
} catch (paymentError) {
|
||||
console.error(`[Cron] Error processing recurring payment ${recurringPayment._id}:`, paymentError);
|
||||
failureCount++;
|
||||
@@ -104,8 +97,6 @@ export const POST: RequestHandler = async ({ request }) => {
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[Cron] Completed processing. Success: ${successCount}, Failures: ${failureCount}`);
|
||||
|
||||
return json({
|
||||
success: true,
|
||||
timestamp: now.toISOString(),
|
||||
|
||||
@@ -33,7 +33,6 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
|
||||
switch (action) {
|
||||
case 'execute':
|
||||
console.log(`[API] Manual execution requested by ${auth.user.nickname}`);
|
||||
await recurringPaymentScheduler.executeNow();
|
||||
return json({
|
||||
success: true,
|
||||
|
||||
122
src/routes/api/glaube/bibel/[reference]/+server.ts
Normal file
122
src/routes/api/glaube/bibel/[reference]/+server.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import { json, error } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
|
||||
interface BibleVerse {
|
||||
bookName: string;
|
||||
abbreviation: string;
|
||||
bookNumber: number;
|
||||
chapter: number;
|
||||
verseNumber: number;
|
||||
text: string;
|
||||
}
|
||||
|
||||
// Cache for parsed verses to avoid reading file repeatedly
|
||||
let cachedVerses: BibleVerse[] | null = null;
|
||||
|
||||
async function loadVerses(fetch: typeof globalThis.fetch): Promise<BibleVerse[]> {
|
||||
if (cachedVerses) {
|
||||
return cachedVerses;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/allioli.tsv');
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const content = await response.text();
|
||||
const lines = content.trim().split('\n');
|
||||
|
||||
cachedVerses = lines.map(line => {
|
||||
const [bookName, abbreviation, bookNumber, chapter, verseNumber, text] = line.split('\t');
|
||||
return {
|
||||
bookName,
|
||||
abbreviation,
|
||||
bookNumber: parseInt(bookNumber),
|
||||
chapter: parseInt(chapter),
|
||||
verseNumber: parseInt(verseNumber),
|
||||
text
|
||||
};
|
||||
});
|
||||
|
||||
return cachedVerses;
|
||||
} catch (err) {
|
||||
console.error('Error loading Bible verses:', err);
|
||||
throw new Error('Failed to load Bible verses');
|
||||
}
|
||||
}
|
||||
|
||||
function parseReference(reference: string): { bookRef: string; isFullName: boolean; chapter: number; startVerse: number; endVerse: number } | null {
|
||||
// Parse various reference formats:
|
||||
// "Mt 3, 16-17", "Mt3:16-17", "Mt 3:16-17", "Lk1:3", "Matthäus 3, 16-17"
|
||||
// Match book name (letters and umlauts), optional space, chapter, separator (: or ,), optional space, verse(s)
|
||||
const match = reference.match(/^([A-Za-zäöüÄÖÜß]+)\s*(\d+)[\s,:]+(\d+)(?:[-:](\d+))?$/);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [, bookRef, chapterStr, startVerseStr, endVerseStr] = match;
|
||||
|
||||
// If book reference is longer than 5 characters, assume it's a full name
|
||||
// Otherwise, assume it's an abbreviation
|
||||
const isFullName = bookRef.length > 5;
|
||||
|
||||
return {
|
||||
bookRef,
|
||||
isFullName,
|
||||
chapter: parseInt(chapterStr),
|
||||
startVerse: parseInt(startVerseStr),
|
||||
endVerse: endVerseStr ? parseInt(endVerseStr) : parseInt(startVerseStr)
|
||||
};
|
||||
}
|
||||
|
||||
function getVersesByReference(verses: BibleVerse[], reference: string): BibleVerse[] {
|
||||
const parsed = parseReference(reference);
|
||||
if (!parsed) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return verses.filter(v => {
|
||||
// Match based on whether we're using full name or abbreviation
|
||||
const bookMatches = parsed.isFullName
|
||||
? v.bookName === parsed.bookRef
|
||||
: v.abbreviation === parsed.bookRef;
|
||||
|
||||
return bookMatches &&
|
||||
v.chapter === parsed.chapter &&
|
||||
v.verseNumber >= parsed.startVerse &&
|
||||
v.verseNumber <= parsed.endVerse;
|
||||
});
|
||||
}
|
||||
|
||||
export const GET: RequestHandler = async ({ params, fetch }) => {
|
||||
const reference = params.reference;
|
||||
|
||||
if (!reference) {
|
||||
return error(400, 'Missing reference parameter');
|
||||
}
|
||||
|
||||
try {
|
||||
const verses = await loadVerses(fetch);
|
||||
const matchedVerses = getVersesByReference(verses, reference);
|
||||
|
||||
if (matchedVerses.length === 0) {
|
||||
return error(404, 'No verses found for the given reference');
|
||||
}
|
||||
|
||||
// Extract book and chapter from first verse (they're all the same)
|
||||
const firstVerse = matchedVerses[0];
|
||||
|
||||
return json({
|
||||
reference,
|
||||
book: firstVerse.bookName,
|
||||
chapter: firstVerse.chapter,
|
||||
verses: matchedVerses.map(v => ({
|
||||
verse: v.verseNumber,
|
||||
text: v.text
|
||||
}))
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Error fetching Bible verses:', err);
|
||||
return error(500, 'Failed to fetch Bible verses');
|
||||
}
|
||||
};
|
||||
@@ -4,8 +4,8 @@ import type { RequestHandler } from './$types';
|
||||
interface BibleVerse {
|
||||
bookName: string;
|
||||
abbreviation: string;
|
||||
bookNumber: number;
|
||||
chapter: number;
|
||||
verse: number;
|
||||
verseNumber: number;
|
||||
text: string;
|
||||
}
|
||||
@@ -27,12 +27,12 @@ async function loadVerses(fetch: typeof globalThis.fetch): Promise<BibleVerse[]>
|
||||
const lines = content.trim().split('\n');
|
||||
|
||||
cachedVerses = lines.map(line => {
|
||||
const [bookName, abbreviation, chapter, verse, verseNumber, text] = line.split('\t');
|
||||
const [bookName, abbreviation, bookNumber, chapter, verseNumber, text] = line.split('\t');
|
||||
return {
|
||||
bookName,
|
||||
abbreviation,
|
||||
bookNumber: parseInt(bookNumber),
|
||||
chapter: parseInt(chapter),
|
||||
verse: parseInt(verse),
|
||||
verseNumber: parseInt(verseNumber),
|
||||
text
|
||||
};
|
||||
@@ -81,6 +81,8 @@
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
max-width: 100%;
|
||||
overflow-x: hidden;
|
||||
transition: margin-right 0.3s ease-out;
|
||||
}
|
||||
|
||||
|
||||
@@ -275,6 +275,8 @@
|
||||
.cospend-main {
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
max-width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@@ -676,6 +678,10 @@
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.recent-activity {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.actions {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
import "$lib/css/christ.css";
|
||||
import "$lib/css/nordtheme.css";
|
||||
import Gebet from "./Gebet.svelte";
|
||||
import Kreuzzeichen from "$lib/components/prayers/Kreuzzeichen.svelte";
|
||||
import GloriaPatri from "$lib/components/prayers/GloriaPatri.svelte";
|
||||
import Paternoster from "$lib/components/prayers/Paternoster.svelte";
|
||||
import Credo from "$lib/components/prayers/Credo.svelte";
|
||||
import AveMaria from "$lib/components/prayers/AveMaria.svelte";
|
||||
import SalveRegina from "$lib/components/prayers/SalveRegina.svelte";
|
||||
import FatimaGebet from "$lib/components/prayers/FatimaGebet.svelte";
|
||||
import Gloria from "$lib/components/prayers/Gloria.svelte";
|
||||
import MichaelGebet from "$lib/components/prayers/MichaelGebet.svelte";
|
||||
import BruderKlausGebet from "$lib/components/prayers/BruderKlausGebet.svelte";
|
||||
import JosephGebet from "$lib/components/prayers/JosephGebet.svelte";
|
||||
</script>
|
||||
<style>
|
||||
.ccontainer{
|
||||
@@ -34,305 +45,50 @@ h1{
|
||||
<div class="ccontainer">
|
||||
<div class=container>
|
||||
|
||||
<Gebet name={"Das heilige Kreuzzeichen"} is_bilingue={true} >
|
||||
<p>
|
||||
<v lang=la>In nómine <i>♱</i> Patris, et Fílii, et Spíritus Sancti. Amen.</v>
|
||||
<v lang=de>Im Namen des <i>♱</i> Vaters und des Sohnes und des Heiligen Geistes. Amen.</v>
|
||||
</p>
|
||||
<Gebet name={"Das heilige Kreuzzeichen"} is_bilingue={true}>
|
||||
<Kreuzzeichen />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Glória Patri"} is_bilingue={true}>
|
||||
<p>
|
||||
<v lang=la>Glória Patri, et Fílio, et Spirítui Sancto.</v>
|
||||
<v lang=de>Ehre sei dem Vater und dem Sohne und dem Hl. Geiste.</v>
|
||||
<v lang=la>Sicute erat in princípio, et nunc, et semper:</v>
|
||||
<v lang=de>Wie es war am Anfang, so auch jetzt und allezeit</v>
|
||||
<v lang=la>et in sǽcula sæculórum. Amen.</v>
|
||||
<v lang=de>und in Ewigkeit. Amen.</v>
|
||||
</p>
|
||||
<GloriaPatri />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Paternoster"} is_bilingue={true} >
|
||||
<p>
|
||||
<v lang=la>Pater noster, qui es in cælis</v>
|
||||
<v lang=de>Vater unser, der Du bist im Himmel,</v>
|
||||
<v lang=la>Sanctificétur nomen tuum</v>
|
||||
<v lang=de>geheiligt werde Dein Name;</v>
|
||||
<v lang=la>Advéniat regnum tuum</v>
|
||||
<v lang=de>zu uns komme Dein Reich;</v>
|
||||
<v lang=la>Fiat volúntas tua, sicut in cælo, et in terra.</v>
|
||||
<v lang=de>Dein Wille geschehe, wie im Himmel, also auch auf Erden!</v>
|
||||
<v lang=la>Panem nostrum quotidiánum da nobis hódie.</v>
|
||||
<v lang=de>Unser tägliches Brot gib uns heute;</v>
|
||||
<v lang=la>Et dimítte nobis debíta nostra,</v>
|
||||
<v lang=de>und vergib uns unsere Schulden,</v>
|
||||
<v lang=la>sicut et nos dimíttimus debitóribus nostris.</v>
|
||||
<v lang=de>wie auch wir vergeben unsern Schuldigern;</v>
|
||||
<v lang=la>Et ne nos indúcas in tentatiónem.</v>
|
||||
<v lang=de>und führe uns nicht in Versuchung.</v>
|
||||
<v lang=la>Sed líbera nos a malo. Amen.</v>
|
||||
<v lang=de>Sondern erlöse uns von dem Übel. Amen.</v>
|
||||
</p>
|
||||
<Gebet name={"Paternoster"} is_bilingue={true}>
|
||||
<Paternoster />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Credo"} is_bilingue={true}>
|
||||
<p>
|
||||
<v lang=la>Credo in unum <i><sup>⚬</sup></i> Deum, Patrem omnipoténtem,</v>
|
||||
<v lang=de>Ich glaub an den einen <i><sup>⚬</sup></i> Gott. Den allmächtigen Vater,</v>
|
||||
<v lang=la>factórem cæli et terræ,</v>
|
||||
<v lang=de>Schöpfer des Himmels und der Erde,</v>
|
||||
<v lang=la>visibílium ómnium et invisibílium.</v>
|
||||
<v lang=de>aller sichtbaren und unsichtbaren Dinge.</v>
|
||||
<v lang=la>Et in unum Dóminum <i><sup>⚬</sup></i> Jesum Christum,</v>
|
||||
<v lang=de>Und an den einen Herrn <i><sup>⚬</sup></i> Jesus Christus,</v>
|
||||
<v lang=la>Fílium Dei unigénitum.</v>
|
||||
<v lang=de>Gottes eingeborenen Sohn.</v>
|
||||
<v lang=la>Et ex Patre natum ante ómnia sǽcula.</v>
|
||||
<v lang=de>Er ist aus dem Vater geboren vor aller Zeit.</v>
|
||||
<v lang=la>Deum de Deo,</v>
|
||||
<v lang=de>Gott von Gott,</v>
|
||||
<v lang=la>lumen de lúmine,</v>
|
||||
<v lang=de>Licht vom Lichte,</v>
|
||||
<v lang=la>Deum verum de Deo vero.</v>
|
||||
<v lang=de>wahrer Gott vom wahren Gott;</v>
|
||||
<v lang=la>Génitum, non factum,</v>
|
||||
<v lang=de>Gezeugt, nicht geschaffen,</v>
|
||||
<v lang=la>consubstantiálem Patri:</v>
|
||||
<v lang=de>eines Wesens mit dem Vater;</v>
|
||||
<v lang=la>per quem ómnia facta sunt.</v>
|
||||
<v lang=de>durch Ihn ist alles geschaffen.</v>
|
||||
<v lang=la>Qui propter nos hómines</v>
|
||||
<v lang=de>Für uns Menschen</v>
|
||||
<v lang=la>et propter nostram salútem</v>
|
||||
<v lang=de>und um unsres Heiles willen</v>
|
||||
<v lang=la>descéndit de cælis.</v>
|
||||
<v lang=de>ist Er vom Himmel herabgestiegen.</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang=la>Et incarnátus est de Spíritu Sancto</v>
|
||||
<v lang=de>Er hat Fleisch angenommen durch den Hl. Geist</v>
|
||||
<v lang=la>ex <i><sup>⚬</sup></i> María Vírgine:</v>
|
||||
<v lang=de>aus <i><sup>⚬</sup></i> Maria, der Jungfrau</v>
|
||||
<v lang=la>Et homo factus est.</v>
|
||||
<v lang=de>und ist Mensch geworden.</v>
|
||||
<v lang=la>Crucifíxus étiam pro nobis:</v>
|
||||
<v lang=de>Gekreuzigt wurde Er sogar für uns;</v>
|
||||
<v lang=la>sub Póntio Piláto passus, et sepúltus est.</v>
|
||||
<v lang=de>unter Pontius Pilatus hat Er den Tod erlitten</v>
|
||||
<v lang=de>und ist begraben worden</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang=la>Et resurréxit tértia die,</v>
|
||||
<v lang=de>Er ist auferstanden am dritten Tage,</v>
|
||||
<v lang=la>secúndum Scriptúras.</v>
|
||||
<v lang=de>gemäß der Schrift;</v>
|
||||
<v lang=la>Et ascéndit in cáelum:</v>
|
||||
<v lang=de>Er ist aufgefahren in den Himmel</v>
|
||||
<v lang=la>sedet ad déxteram Patris.</v>
|
||||
<v lang=de>und sitzet zur Rechten des Vaters.</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang=la>Et íterum ventúrus est cum glória</v>
|
||||
<v lang=de>Er wird wiederkommen in Herrlichkeit,</v>
|
||||
<v lang=la>judicáre vivos et mórtuos:</v>
|
||||
<v lang=de>Gericht zu halten über Lebende und Tote:</v>
|
||||
<v lang=la>cujus regni non erit finis.</v>
|
||||
<v lang=de>und Seines Reiches wird kein Endes sein.</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang=la>Et in Spíritum Sanctum,</v>
|
||||
<v lang=de>Ich glaube an den Heiligen Geist,</v>
|
||||
<v lang=la>Dóminum et vivificántem:</v>
|
||||
<v lang=de>den Herrn und Lebensspender,</v>
|
||||
<v lang=la>qui ex Patre Filióque procédit.</v>
|
||||
<v lang=de>der vom Vater und vom Sohne ausgeht.</v>
|
||||
<v lang=la>Qui cum Patre et Fílio simul <i><sup></sup></i> adorátur et conglorificátur:</v>
|
||||
<v lang=de>zugleich <i><sup></sup></i> angebetet und verherrlicht;</v>
|
||||
<v lang=la>qui locútus est per Prophétas.</v>
|
||||
<v lang=de>Er hat gesprochen durch die Propheten.</v>
|
||||
<v lang=la>Et unam sanctam cathólicam et apostólicam Ecclésiam.</v>
|
||||
<v lang=de>Ich glaube an die eine, heilige, katholische und apostolische Kirche.</v>
|
||||
<v lang=la>Confíteor unum baptísma</v>
|
||||
<v lang=de>Ich bekenne die eine Taufe</v>
|
||||
<v lang=la>in remissiónem peccatórum.</v>
|
||||
<v lang=de>zur Vergebung der Sünden.</v>
|
||||
<v lang=la>Et exspécto resurrectiónem mortuórum.</v>
|
||||
<v lang=de>Ich erwarte die Auferstehung der Toten.</v>
|
||||
<v lang=la><i>♱</i> Et vitam ventúri sǽculi. Amen.</v>
|
||||
<v lang=de><i>♱</i> Und das Leben der zukünftigen Welt. Amen.</v>
|
||||
</p>
|
||||
<Credo />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Ave Maria"} is_bilingue={true}>
|
||||
<p>
|
||||
<v lang=la>Ave María, grátia plena. Dóminus tecum,</v>
|
||||
<v lang=de>Gegrüsset seist du Maria, voll der Gnade; der Herr ist mit dir;</v>
|
||||
<v lang=la>benedícta tu in muliéribus,</v>
|
||||
<v lang=de>du bist gebenedeit unter den Weibern,</v>
|
||||
<v lang=la>et benedíctus fructus ventris tui, Jesus.</v>
|
||||
<v lang=de>und gebenedeit ist die Frucht deines Leibes, Jesus.</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang=la>Sancta María, mater Dei, ora pro nobis peccatóribus,</v>
|
||||
<v lang=de>Heilige Maria, Mutter Gottes, bitte für uns Sünder</v>
|
||||
<v lang=la>nunc, et in hora mortis nostræ. Amen.</v>
|
||||
<v lang=de>jetzt und in der Stunde unseres Todes! Amen.</v>
|
||||
</p>
|
||||
<AveMaria />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Salve Regina"} is_bilingue={true}>
|
||||
<p>
|
||||
<v lang=la>Salve, Regína,</v>
|
||||
<v lang=de>Sei gegrüßt, o Königin,</v>
|
||||
<v lang=la>máter misericórdiae;</v>
|
||||
<v lang=de>Mutter der Barmherzigkeit,</v>
|
||||
<v lang=la>Víta, dulcédo et spes nóstra, sálve.</v>
|
||||
<v lang=de>unser Leben, unsre Wonne</v>
|
||||
<v lang=de>und unsere Hoffnung, sei gegrüßt!</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang=la>Ad te clamámus, éxsules fílii Hévae.</v>
|
||||
<v lang=de>Zu dir rufen wir verbannte Kinder Evas;</v>
|
||||
<v lang=la>Ad te suspirámus,</v>
|
||||
<v lang=de>zu dir seufzen wir</v>
|
||||
<v lang=la>geméntes et fléntes in hac lacrimárum válle.</v>
|
||||
<v lang=de>trauernd und weinend in diesem Tal der Tränen.</v>
|
||||
<v lang=la>Eia ergo, Advocáta nóstra,</v>
|
||||
<v lang=de>Wohlan denn, unsre Fürsprecherin,</v>
|
||||
<v lang=la>íllos túos misericórdes óculos ad nos convérte.</v>
|
||||
<v lang=de>deine barmherzigen Augen wende zu uns</v>
|
||||
<v lang=la>Et Jésum, benedíctum frúctum véntris túi,</v>
|
||||
<v lang=de>und nach diesem Elend zeige uns Jesus,</v>
|
||||
<v lang=la>nóbis post hoc exsílíum osténde.</v>
|
||||
<v lang=de>die gebenedeite Frucht deines Leibes.</v>
|
||||
<v lang=la>O clémens, o pía, o dúlcis Vírgo María.</v>
|
||||
<v lang=de>O gütige, o milde, o süße Jungfrau Maria.</v>
|
||||
</p>
|
||||
<SalveRegina />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Das Fatimagebet"} is_bilingue={true}>
|
||||
<v lang=la>Ó mí Jésú, dímitte nóbís débita nostra,</v>
|
||||
<v lang=de>O mein Jesus, verzeih' uns unsere Sünden,</v>
|
||||
<v lang=la>líberá nós ab igne ínferní,</v>
|
||||
<v lang=de>bewahre uns vor den Feuern der Hölle</v>
|
||||
<v lang=la>condúc in cælum omnés animás, </v>
|
||||
<v lang=de>und führe alle Seelen in den Himmel,</v>
|
||||
<v lang=la>præsertim illás,</v>
|
||||
<v lang=de>besonders jene,</v>
|
||||
<v lang=la>quæ maximé indigent misericordiá tuá. Amen.</v>
|
||||
<v lang=de>die Deiner Barmherzigkeit am meisten bedürfen. Amen.</v>
|
||||
<FatimaGebet />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Glória"} is_bilingue={true}>
|
||||
<p slot="intro">Der uralte Gesang beginnt mit den Worten, mit denen die Engelscharen den neugeborenen Welterlöser feierten. Er preist zunächst Gott Vater, dann Gott Sohn; er schließt mit einer Huldigung an die Heiligste Dreifaltigkeit, wobei man sich mit dem großen Kreuze bezeichnet.</p>
|
||||
<p>
|
||||
<v lang=la>Glória in excélsis <i><sup>⚬</sup></i> Deo.</v>
|
||||
<v lang=de>Ehre sei <i><sup>⚬</sup></i> Gott in der Höhe.</v>
|
||||
<v lang=la>Et in terra pax homínibus</v>
|
||||
<v lang=de>Und auf Erden Friede den Mesnchen,</v>
|
||||
<v lang=la>bonæ voluntátis.</v>
|
||||
<v lang=de>die guten Willens sind.</v>
|
||||
<v lang=la>Laudámus te.</v>
|
||||
<v lang=de>Wir loben Dich.</v>
|
||||
<v lang=la>Benedícimus te.</v>
|
||||
<v lang=de>Wir preisen Dich.</v>
|
||||
<v lang=la><i><sup>⚬</sup></i> Adorámus te.</v>
|
||||
<v lang=de><i><sup>⚬</sup></i> Wir beten Dich an.</v>
|
||||
<v lang=la>Glorificámus te.</v>
|
||||
<v lang=de>Wir verherrlichen Dich.</v>
|
||||
<v lang=la><i><sup>⚬</sup></i> Grátias ágimus tibi</v>
|
||||
<v lang=de><i><sup>⚬</sup></i> Wir sagen Dir Dank</v>
|
||||
<v lang=la>propter magnam glóriam tuam.</v>
|
||||
<v lang=de>ob Deiner großen Herrlichkeit.</v>
|
||||
<v lang=la>Dómine Deus, Rex cæléstis,</v>
|
||||
<v lang=de>Herr und Gott, König des Himmels,</v>
|
||||
<v lang=la>Deus Pater omnípotens.</v>
|
||||
<v lang=de>Gott allmächtiger Vater!</v>
|
||||
<v lang=la>Dómine Fili unigénite, <i><sup>⚬</sup></i> Jesu Christe.</v>
|
||||
<v lang=de>Herr <i><sup>⚬</sup></i> Jesus Christus, eingeborener Sohn!</v>
|
||||
<v lang=la>Dómine Deus, Agnus Dei,</v>
|
||||
<v lang=de>Herr und Gott, Lamm Gottes,</v>
|
||||
<v lang=la>Fílius Patris.</v>
|
||||
<v lang=de>Sohn des Vaters!</v>
|
||||
<v lang=la>Qui tollis peccáta mundi,</v>
|
||||
<v lang=de>Du nimmst hinweg die Sünden der Welt:</v>
|
||||
<v lang=la>miserére nobis.</v>
|
||||
<v lang=de>erbarme Dich unser.</v>
|
||||
<v lang=la>Qui tollis peccáta mundi,</v>
|
||||
<v lang=de>Du nimmst hinwerg die Sünden der Welt.</v>
|
||||
<v lang=la><i><sup>⚬</sup></i> súscipe depreciatiónem nostram.</v>
|
||||
<v lang=de><i><sup>⚬</sup></i> nimm unser Flehen gnädig auf.</v>
|
||||
<v lang=la>Qui sedes ad déxteram Patris,</v>
|
||||
<v lang=de>Du sitzt zur Rechten des Vaters:</v>
|
||||
<v lang=la>miserére nobis.</v>
|
||||
<v lang=de>erbarme Dich unser.</v>
|
||||
<v lang=la>Quóniam tu solus Sanctus.</v>
|
||||
<v lang=de>Denn Du allein bist der Heilige.</v>
|
||||
<v lang=la>Tu solus Altíssimus,</v>
|
||||
<v lang=de>Du allein der Höchste,</v>
|
||||
<v lang=la><i><sup>⚬</sup></i> Jesu Christe.</v>
|
||||
<v lang=de><i><sup>⚬</sup></i> Jesus Christus,</v>
|
||||
<v lang=la>Cum Sancto Spíritu</v>
|
||||
<v lang=de>Mit dem Hl. Geiste,</v>
|
||||
<v lang=la><i>♱</i> in glória Dei Patris. Amen.</v>
|
||||
<v lang=de><i>♱</i> in der Herrlichkeit Gottes des Vaters. Amen.</v>
|
||||
</p>
|
||||
<p slot="intro">Der uralte Gesang beginnt mit den Worten, mit denen die Engelscharen den neugeborenen Welterlöser feierten. Er preist zunächst Gott Vater, dann Gott Sohn; er schliesst mit einer Huldigung an die Heiligste Dreifaltigkeit, wobei man sich mit dem grossen Kreuze bezeichnet.</p>
|
||||
<Gloria />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Gebet zum hl. Erzengel Michael"} is_bilingue={true}>
|
||||
<p>
|
||||
<v lang=la>Sáncte Míchael Archángele,</v>
|
||||
<v lang=de>Heiliger Erzengel Michael,</v>
|
||||
<v lang=la>defénde nos in proélio,</v>
|
||||
<v lang=de>verteidige uns im Kampfe!</v>
|
||||
<v lang=la>cóntra nequítam et insídias</v>
|
||||
<v lang=de>Gegen die Bosheit und Nachstellungen</v>
|
||||
<v lang=la>diáboli ésto præsídium.</v>
|
||||
<v lang=de>des Teufels sei unser Schutz. </v>
|
||||
<v lang=la>Ímperet ílli Déus, súpplices deprecámur:</v>
|
||||
<v lang=de>»Gott gebiete ihm!«, so bitten wir flehentlich.</v>
|
||||
<v lang=la>tuque, Prínceps milítæ cæléstis,</v>
|
||||
<v lang=de>Du aber, Fürst der himmlischen Heerscharen,</v>
|
||||
<v lang=la>Sátanam aliósque spíritus malígnos,</v>
|
||||
<v lang=de>stoße den Satan und die anderen bösen Geister,</v>
|
||||
<v lang=la>qui ad perditiónem animárum</v>
|
||||
<v lang=la>pervagántur in múndo,</v>
|
||||
<v lang=de>die in der Welt umhergehen,</v>
|
||||
<v lang=de>um die Seelen zu verderben,</v>
|
||||
<v lang=la>divína virtúte, in inférnum detrúde. Amen.</v>
|
||||
<v lang=de>durch die Kraft Gottes in die Hölle. Amen.</v>
|
||||
</p>
|
||||
<MichaelGebet />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Bruder Klaus Gebet"} is_bilingue={false}>
|
||||
<p>
|
||||
<v lang=de>Mein Herr und mein Gott,</v>
|
||||
<v lang=de>nimm alles von mir,</v>
|
||||
<v lang=de>was mich hindert zu Dir.</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang=de>Mein Herr und mein Gott,</v>
|
||||
<v lang=de>gib alles mir,</v>
|
||||
<v lang=de>was mich führet zu Dir.</v>
|
||||
</p>
|
||||
<p>
|
||||
<v lang=de>Mein Herr und mein Gott,</v>
|
||||
<v lang=de>nimm mich mir</v>
|
||||
<v lang=de>und gib mich ganz zu eigen Dir.</v>
|
||||
</p>
|
||||
<BruderKlausGebet />
|
||||
</Gebet>
|
||||
|
||||
<Gebet name={"Josephgebet des hl. Papst Pius X"} is_bilingue={false}>
|
||||
<p slot="intro">Wenn man mehr zum hl. Joseph als <q>Patrone Morientium</q> wissen möchte kann man <a href="predigten/20220319-hl._joseph">hier</a> die Predigt zum Festtag des hl. Joseph nachlesen.</p>
|
||||
|
||||
<p>
|
||||
<v>Jungfräulicher Vater Jesu,</v>
|
||||
<v>Reinster Bräutigam Mariä,</v>
|
||||
<v>Sankt Joseph, bitte Tag für Tag bei Jesus, dem Sohn Gottes.</v>
|
||||
<v>Seine Kraft und Gnade soll uns stärken,</v>
|
||||
<v>dass wir siegreich streiten im Leben</v>
|
||||
<v>und die Krone von Ihm erhalten im Sterben.</v>
|
||||
</p>
|
||||
<p slot="intro">Wenn man mehr zum hl. Joseph als <q>Patrone Morientium</q> wissen möchte kann man <a href="predigten/20220319-hl._joseph">hier</a> die Predigt zum Festtag des hl. Joseph nachlesen.</p>
|
||||
<JosephGebet />
|
||||
</Gebet>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -74,16 +74,16 @@ h4{
|
||||
<h2>Der Osterfestkreis</h2>
|
||||
<div class=schott>
|
||||
<p>
|
||||
Der Weihnachtsfestkreis schließt mit der Woche vor Septuagesima.
|
||||
Der Weihnachtsfestkreis schliesst mit der Woche vor Septuagesima.
|
||||
Der ersehnte Erlöser ist gekommen und hat in seiner ersten Ankunft zugleich seine zweite, die am Gerichtstage erfolgen wird, begründet und begonnen.
|
||||
</p>
|
||||
<p>
|
||||
Jetzt ist die Zeit des anstrengten Kampfes gegen Sünde, Welt und Fleisch gekommen, die Zeit der mühevollen Aussaat, des sturmumtobten Wachsens.
|
||||
Durch Kampf zum Sieg, durch Sterben zum Leben, zur Auferstehung, zur Vollherrschaft Christi und schließlich zur Verklärung im Osterlichte!
|
||||
Christus soll in uns den Thron seiner Herrschaft errichten, einer Herrschaft, die uns nicht erdrückt, sondern erhöht; nicht beraubt, sondern bereichert; nicht einschränkt, sondern innerlich weitet und uns einmal mitherrschen läßt im ewigen Ostern des Himmels.
|
||||
Durch Kampf zum Sieg, durch Sterben zum Leben, zur Auferstehung, zur Vollherrschaft Christi und schliesslich zur Verklärung im Osterlichte!
|
||||
Christus soll in uns den Thron seiner Herrschaft errichten, einer Herrschaft, die uns nicht erdrückt, sondern erhöht; nicht beraubt, sondern bereichert; nicht einschränkt, sondern innerlich weitet und uns einmal mitherrschen lässt im ewigen Ostern des Himmels.
|
||||
</p>
|
||||
<p>
|
||||
Der Osterfestkreis umfaßt drei Abschnitte:
|
||||
Der Osterfestkreis umfasst drei Abschnitte:
|
||||
die Zeit der Vorbereitung: Vorfasten- und Fastenzeit;
|
||||
die eigentliche Festzeit: Oster- und Pfingstfest;
|
||||
endlich die Zeit nach Pfingsten
|
||||
@@ -94,15 +94,15 @@ endlich die Zeit nach Pfingsten
|
||||
<h3> 1. Die Vorfastenzeit</h3>
|
||||
<div class=schott >
|
||||
<p>
|
||||
Sie umfaßt die Sonntage Septuagesima, Sexagesima und Quinquagesima.
|
||||
Sie umfasst die Sonntage Septuagesima, Sexagesima und Quinquagesima.
|
||||
Diese Namen bezeichnen nicht die genauen Abstände bis zum Osterfest, sonder deuten auf die rund berechnete 70tägige, 60tägige, 50tägige Vorbereitungzeit auf Ostern.
|
||||
</p>
|
||||
<p>
|
||||
Der Name Septuagesima weckt die Erinnerung an die 70 Jahre der Gefangenschaft, welche die Juden zur Strafe für ihre Untreue fern von Jerusalem, zu Babylon, verbringen mußten, bevor sie wieder ins Gelobte Land zurückkerhen durften.
|
||||
Der Name Septuagesima weckt die Erinnerung an die 70 Jahre der Gefangenschaft, welche die Juden zur Strafe für ihre Untreue fern von Jerusalem, zu Babylon, verbringen mussten, bevor sie wieder ins Gelobte Land zurückkerhen durften.
|
||||
So mahnt uns diese Zeit an unsre eigene Pilgerschaft aus der Fremde, aus der gottfernen Welt (Babylon), zum wahren Vaterland (Jerusalem).
|
||||
Diese Pilgerschaft ist für uns eine beständiger Kampf gegen die Feinde unsres Heiles.
|
||||
Für den göttlichen Heiland bedeutet das öffentliche Wirken Mühsal und Leiden und schließlich den Tod;
|
||||
so muß sich auch unser Leben, soll es dem seinen nachgebildet werden, auf Kämpfe, selbst auf ein geistiges Sterben gefaßt machen;
|
||||
Für den göttlichen Heiland bedeutet das öffentliche Wirken Mühsal und Leiden und schliesslich den Tod;
|
||||
so muss sich auch unser Leben, soll es dem seinen nachgebildet werden, auf Kämpfe, selbst auf ein geistiges Sterben gefasst machen;
|
||||
erst dann wird es mit dem Heiland zum endlichen Triumph gelangen.
|
||||
</p>
|
||||
</div>
|
||||
@@ -123,14 +123,14 @@ endlich die Zeit nach Pfingsten
|
||||
<h3> Epistel </h3>
|
||||
<div class="epistel bibel">
|
||||
<ol><i>1 Cor. 9</i>
|
||||
<li value=24>Wisset ihr nicht, daß die, welche in der Rennbahn laufen, zwar alle laufen, aber nur einer erlangt den Preis? Laufet fo, daß ihr ihn erlanget!</li>
|
||||
<li value=24>Wisset ihr nicht, dass die, welche in der Rennbahn laufen, zwar alle laufen, aber nur einer erlangt den Preis? Laufet fo, dass ihr ihn erlanget!</li>
|
||||
<li>Jeder aber, der im Kampfspiele ringt, enthält sich von allem, und zwar jene, um eine vergängliche Krone zu empfangen, wir aber eine unvergängliche.</li>
|
||||
<li>Ich laufe demnach, nicht wie in's Ungewisse; ich kämpfe, nicht indem ich Luftstreiche thue,</li>
|
||||
<li>sondern ich züchtige meinen Leib, und bringe ihn in die Botmäßigkeit, damit ich nicht etwa, nachdem ich anderen gepredigt habe, selbst verworfen werde.</li>
|
||||
<li>sondern ich züchtige meinen Leib, und bringe ihn in die Botmässigkeit, damit ich nicht etwa, nachdem ich anderen gepredigt habe, selbst verworfen werde.</li>
|
||||
<i>1 Cor. 10</i>
|
||||
<li value=1>Denn ich will euch nicht in Unwissenheit lassen, Brüder! Daß unsere Väter alle unter der Wolke waren, und alle durch das Meer hindurch gingen,</li>
|
||||
<li value=1>Denn ich will euch nicht in Unwissenheit lassen, Brüder! Dass unsere Väter alle unter der Wolke waren, und alle durch das Meer hindurch gingen,</li>
|
||||
<li>und alle auf Moses getauft wurden, in der Wolke und in dem Meere,</li>
|
||||
<li>und alle dieselbe geistige Speise aßen,</li>
|
||||
<li>und alle dieselbe geistige Speise assen,</li>
|
||||
<li>und alle dieselbe geistigen Trank tranken (sie tranken nämlich aus einem geistigen, sie begleitenden Felsen, der Felsen aber war Christus);</li>
|
||||
<li>aber an der Mehrzahl von ihnen hatte Gott kein Wohlgefallen; denn sie wurden niedergestreckt in der Wüste.</li>
|
||||
</ol>
|
||||
@@ -141,14 +141,14 @@ endlich die Zeit nach Pfingsten
|
||||
<ol><i>Matth. 20</i>
|
||||
<li>Das Himmelreich ist gleich einem Hausvater, der am frühen Morgen ausging, um Arbeiter in seinen Weinberg zu dingen.</li>
|
||||
<li>Nachdem er nun mit den Arbeitern um einen Denar für den Tag übereingekommen war, sandte er sie in seinen Weinberg.</li>
|
||||
<li>Und als er um die dritte Stunde ausging, sah er andere au dem Markte müßig stehen,</li>
|
||||
<li>Und als er um die dritte Stunde ausging, sah er andere au dem Markte müssig stehen,</li>
|
||||
<li>und sprach zu ihnen: Gehet auch ihr in meinen Weinberg, und was recht ist, werde ich euch geben.</li>
|
||||
<li>Sie aber gingen hin. Abermals ging er um die sechste und neunte Stunde aus, und that ebenso.</li>
|
||||
<li>Um die elfte Stunde aber ging er aus, und fand andere andere stehen, und sprach zu ihnen: Was stehet ihr hier den ganzen Tag müßig?</li>
|
||||
<li>Um die elfte Stunde aber ging er aus, und fand andere andere stehen, und sprach zu ihnen: Was stehet ihr hier den ganzen Tag müssig?</li>
|
||||
<li>Sie antworteten ihm: Weil uns niemand gedungen hat. Da sprach er zu ihnen: Gehet auch ihr in meinen Weinberg,</li>
|
||||
<li>Als es nun Abend geworden, sagte der Herr des Weinberges zu seinem Verwalter: Rufe die Arbeiter, und gib ihnen den Lohn, von den letzten anfangend, bis zu den ersten.</li>
|
||||
<li>Da nun die kamen, welche um die elfte Stunde eingetreten waren, empfingen sie jeder einen Denar.</li>
|
||||
<li>Wie aber auch die ersten kamen, meinten sie, daß sie mehr empfangen würden, aber auch sie erhielten jeder einen Denar.</li>
|
||||
<li>Wie aber auch die ersten kamen, meinten sie, dass sie mehr empfangen würden, aber auch sie erhielten jeder einen Denar.</li>
|
||||
<li>Und da sie ihn empfingen, murrten sie wider den Hausvater.</li>
|
||||
<li>und sprachen: Siese letzten haben eine einzige Stunde gearbeitet, und du hast sie uns gleich gehalten, die wir die Last und Hitze des Tages getragen haben.</li>
|
||||
<li>Er aber antowrtete einem aus ihnen, und sprach: Freund! ich thue dir nicht Unrecht; bist du nicht auf einen Denar mit mir eins geworden?</li>
|
||||
@@ -168,7 +168,7 @@ endlich die Zeit nach Pfingsten
|
||||
Wir sollen gleich den Sportlern verzichten für das Heil der Seelen, dem Heil der eigenen Seele.
|
||||
</p>
|
||||
<p>
|
||||
Diese Bildnis der Spiele im Stadion waren vermutlich ein gutes Bildnis für die Korinter. So hatten sie alle zwei Jahre Sportspiele von April bis Anfang Mai, welche wie auch Fußball heute noch, vieles der Gesellschaft lahmlegte.
|
||||
Diese Bildnis der Spiele im Stadion waren vermutlich ein gutes Bildnis für die Korinter. So hatten sie alle zwei Jahre Sportspiele von April bis Anfang Mai, welche wie auch Fussball heute noch, vieles der Gesellschaft lahmlegte.
|
||||
Auch die Gläubigen gehörten damals wie heute zu den Begeisterten solcher Spiele.
|
||||
</p>
|
||||
|
||||
@@ -194,7 +194,7 @@ endlich die Zeit nach Pfingsten
|
||||
So beging er zwei Todsünden durch einen Blick auf eine Frau: Ehebruch und Mord am Manne dieser Frau.
|
||||
</p>
|
||||
<p>
|
||||
Als Kind hat er Löwen und Bären mit bloßen Händen besiegt, aber nun wird dieser einst mutige und starke Mann bezwungen wegen seinem <em>Müßiggang</em>.
|
||||
Als Kind hat er Löwen und Bären mit blossen Händen besiegt, aber nun wird dieser einst mutige und starke Mann bezwungen wegen seinem <em>Müssiggang</em>.
|
||||
Wie man zu sagen pflegt: Wer man kein Beschäftigugn welche Platz einnimmt so wird der Teufel selbst den ganzen Platz einnehmen, den wir freigelassen haben.
|
||||
Es wäre besser gewesen für David, noch in der Ängstlichkeit der Flucht vor Saulus zu sein, als in seinem Palast in Jerusalem.
|
||||
</p>
|
||||
@@ -208,10 +208,10 @@ endlich die Zeit nach Pfingsten
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Müßiggang hat ihn besiegt und der Gedanke, dass er nichts mehr zu erobern hatte.
|
||||
Müssiggang hat ihn besiegt und der Gedanke, dass er nichts mehr zu erobern hatte.
|
||||
Es gibt immer etwas weiteres zu erobern. Es gibt immer eine Ecke in unserer Seele die uns, und damit Gott, nicht gehört.
|
||||
Es gibt immer etwas, was man besser tun kann, es gibt immer schlechte Gewohnheiten die man ablegen muss.
|
||||
In dieser Vorfastenzeit geht es darum sich diesem deutlicher bewusst zu werden und seinen Kampf gegen diese Müßigkeit für die kommende Fastenzeit zu planen.
|
||||
In dieser Vorfastenzeit geht es darum sich diesem deutlicher bewusst zu werden und seinen Kampf gegen diese Müssigkeit für die kommende Fastenzeit zu planen.
|
||||
</p>
|
||||
<p>
|
||||
Als Beispiel hilft hier das Königreich Spanien. Jahrhunderte von Kampf um die Anwesenheit der Muslime zu bekämpfen. Als sie endlich die letzte Stadt, welche unter der Vollmacht der Muslime war, erobert hatten, hat die Vorsehung ihnen noch etwas zu erobern gegeben:
|
||||
@@ -226,7 +226,7 @@ endlich die Zeit nach Pfingsten
|
||||
<p>
|
||||
Von den Ägyptern durch die Wunder Gottes befreit, sind sie nun auf dem weiten Weg zum versprochenen Land.
|
||||
Sie schicken Kundschafter in dieses Land. Diese Kundschafter gehen und verbringen 40 Tage dort.
|
||||
Diese Kundschafter finden ein wunderbares Land. Es fließt Honig und Milch. Aber es ist nicht unbevölkert. Es gibt viele, starke Stämme.
|
||||
Diese Kundschafter finden ein wunderbares Land. Es fliesst Honig und Milch. Aber es ist nicht unbevölkert. Es gibt viele, starke Stämme.
|
||||
Die Kundschafter haben Angst, sie verbreiteten Lügen über dieses Land da sie Angst haben zu fallen im Versuch es einzunehmen.
|
||||
Das Volk will murren, beklagen. Sie wollen nicht kämpfen.
|
||||
</p>
|
||||
@@ -251,7 +251,7 @@ endlich die Zeit nach Pfingsten
|
||||
Diese Knechtschaft soll abgelegt werden um so zu einem kämpferischen Geist zu kommen. Das wird auch bestätigt im Johannesevangelium wo steht:
|
||||
<div class=bibel>
|
||||
<ol><i> Johannes 15</i>
|
||||
<li value=15>Ich nenne euch nun nicht mehr Knechte, denn der Knecht weiß nicht, was sein Herr tut; euch aber habe ich Freunde genannt; denn alles, was ich von meinem Vater gehört, habe ich euch kundgetan.
|
||||
<li value=15>Ich nenne euch nun nicht mehr Knechte, denn der Knecht weiss nicht, was sein Herr tut; euch aber habe ich Freunde genannt; denn alles, was ich von meinem Vater gehört, habe ich euch kundgetan.
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
@@ -280,7 +280,7 @@ endlich die Zeit nach Pfingsten
|
||||
<li value=10>Simon Petrus also, der sein Schwert hatte, zog es und schlug den Knecht des Hohenpriesters, und hieb ihm sein rechtes Ohr ab. Der Name des Knechtes aber war Malchus.</li>
|
||||
<i>Matthäus 26</i>
|
||||
<li value=35>Da sprach Petrus zu ihm: Wenn ich auch mit dir sterben müsste, werde ich dich doch nicht verleugnen. In gleicher Weise sprachen auch alle Jünger.</li>
|
||||
<li value=69>Petrus aber saß draußen in dem Hofe; und eine Magd trat zu ihm hin, und sprach: Du warest auch bei Jesus, dem Galiläer!</li>
|
||||
<li value=69>Petrus aber sass draussen in dem Hofe; und eine Magd trat zu ihm hin, und sprach: Du warest auch bei Jesus, dem Galiläer!</li>
|
||||
<li>Doch er leugnete vor allen, und sprach: Ich weiss nicht, was du sagst.</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
64
src/routes/glaube/rosenkranz/+page.server.ts
Normal file
64
src/routes/glaube/rosenkranz/+page.server.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { mysteryReferences, type MysteryDescription, type VerseData } from '$lib/data/mysteryDescriptions';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const prerender = true;
|
||||
|
||||
async function fetchBibleData(reference: string, fetch: typeof globalThis.fetch): Promise<{ text: string; verseData: VerseData | null }> {
|
||||
try {
|
||||
const response = await fetch(`/api/glaube/bibel/${encodeURIComponent(reference)}`);
|
||||
if (!response.ok) {
|
||||
console.error(`Failed to fetch reference ${reference}:`, response.status);
|
||||
return { text: '', verseData: null };
|
||||
}
|
||||
const data = await response.json();
|
||||
|
||||
// Format the verses into a single text with guillemets
|
||||
let text = '';
|
||||
if (data.verses && data.verses.length > 0) {
|
||||
text = `«${data.verses.map((v: { verse: number; text: string }) => v.text).join(' ')}»`;
|
||||
}
|
||||
|
||||
// Store the full verse data for the modal
|
||||
const verseData: VerseData = {
|
||||
book: data.book,
|
||||
chapter: data.chapter,
|
||||
verses: data.verses
|
||||
};
|
||||
|
||||
return { text, verseData };
|
||||
} catch (err) {
|
||||
console.error(`Error fetching reference ${reference}:`, err);
|
||||
return { text: '', verseData: null };
|
||||
}
|
||||
}
|
||||
|
||||
export const load: PageServerLoad = async ({ fetch }) => {
|
||||
// Fetch Bible texts for all mysteries at build time
|
||||
const mysteryDescriptions: Record<string, MysteryDescription[]> = {
|
||||
lichtreichen: [],
|
||||
freudenreich: [],
|
||||
schmerzhaften: [],
|
||||
glorreichen: []
|
||||
};
|
||||
|
||||
// Process each mystery type
|
||||
for (const [mysteryType, references] of Object.entries(mysteryReferences)) {
|
||||
const descriptions: MysteryDescription[] = [];
|
||||
|
||||
for (const ref of references) {
|
||||
const { text, verseData } = await fetchBibleData(ref.reference, fetch);
|
||||
descriptions.push({
|
||||
title: ref.title,
|
||||
reference: ref.reference,
|
||||
text,
|
||||
verseData
|
||||
});
|
||||
}
|
||||
|
||||
mysteryDescriptions[mysteryType] = descriptions;
|
||||
}
|
||||
|
||||
return {
|
||||
mysteryDescriptions
|
||||
};
|
||||
};
|
||||
@@ -9,8 +9,12 @@ import AveMaria from "$lib/components/prayers/AveMaria.svelte";
|
||||
import GloriaPatri from "$lib/components/prayers/GloriaPatri.svelte";
|
||||
import FatimaGebet from "$lib/components/prayers/FatimaGebet.svelte";
|
||||
import SalveRegina from "$lib/components/prayers/SalveRegina.svelte";
|
||||
import RosaryFinalPrayer from "$lib/components/prayers/RosaryFinalPrayer.svelte";
|
||||
import BenedictusMedal from "$lib/components/BenedictusMedal.svelte";
|
||||
import CounterButton from "$lib/components/CounterButton.svelte";
|
||||
import BibleModal from "$lib/components/BibleModal.svelte";
|
||||
|
||||
export let data;
|
||||
|
||||
// Mystery variations for each type of rosary
|
||||
const mysteries = {
|
||||
@@ -23,7 +27,7 @@ const mysteries = {
|
||||
],
|
||||
schmerzhaften: [
|
||||
"Jesus, der für uns Blut geschwitzt hat.",
|
||||
"Jesus, der für uns gegeißelt worden ist.",
|
||||
"Jesus, der für uns gegeisselt worden ist.",
|
||||
"Jesus, der für uns mit Dornen gekrönt worden ist.",
|
||||
"Jesus, der für uns das schwere Kreuz getragen hat.",
|
||||
"Jesus, der für uns gekreuzigt worden ist."
|
||||
@@ -46,32 +50,64 @@ const mysteries = {
|
||||
|
||||
const mysteriesLatin = {
|
||||
freudenreich: [
|
||||
"Jesus, quem tu, Virgo, de Spiritu Sancto concepisti.",
|
||||
"Jesus, quem tu, Virgo, ad Elisabeth portasti.",
|
||||
"Jesus, quem tu, Virgo, Bethlehemi peperisti.",
|
||||
"Jesus, quem tu, Virgo, in templo praesentasti.",
|
||||
"Jesus, quem tu, Virgo, in templo invenisti."
|
||||
"Jesus, quem, virgo, concepísti.",
|
||||
"Jesus, quem visitándo Elísabeth portásti.",
|
||||
"Jesus, quem, virgo, genuísti.",
|
||||
"Jesus, quem in templo præsentásti.",
|
||||
"Jesus, quem in templo invenisti."
|
||||
],
|
||||
schmerzhaften: [
|
||||
"Jesus, qui pro nobis sanguinem sudavit.",
|
||||
"Jesus, qui pro nobis flagellatus est.",
|
||||
"Jesus, qui pro nobis spinis coronatus est.",
|
||||
"Jesus, qui pro nobis crucem baiulavit.",
|
||||
"Jesus, qui pro nobis sánguinem sudavit.",
|
||||
"Jesus, qui pro nobis flagellátus est.",
|
||||
"Jesus, qui pro nobis spinis coronátus est.",
|
||||
"Jesus, qui pro nobis crucem baiulávit.",
|
||||
"Jesus, qui pro nobis crucifixus est."
|
||||
],
|
||||
glorreichen: [
|
||||
"Jesus, qui resurrexit a mortuis.",
|
||||
"Jesus, qui in caelum ascendit.",
|
||||
"Jesus, qui Spiritum Sanctum misit.",
|
||||
"Jesus, qui te, Virgo, in caelum assumpsit.",
|
||||
"Jesus, qui te, Virgo, in caelis coronavit."
|
||||
"Jesus, qui resurréxit a mórtuis.",
|
||||
"Jesus, qui ascendit in cælum.",
|
||||
"Jesus, qui misit Spíritum Sanctum.",
|
||||
"Jesus, qui te, virgo, in cælum assúmpsit.",
|
||||
"Jesus, qui te, virgo, in cælo coronávit."
|
||||
],
|
||||
lichtreichen: [
|
||||
"Jesus, qui a Ioanne baptizatus est.",
|
||||
"Jesus, qui in Cana se manifestavit.",
|
||||
"Jesus, qui regnum Dei proclamavit.",
|
||||
"Jesus, qui in monte transfiguratus est.",
|
||||
"Jesus, qui Eucharistiam donavit."
|
||||
"Jesus, qui a Ioánne baptizátus est.",
|
||||
"Jesus, qui se in Cana revelávit.",
|
||||
"Jesus, qui regnum Dei prædicávit.",
|
||||
"Jesus, qui in monte transfigurátus est.",
|
||||
"Jesus, Sacraméntum Altáris instítuit."
|
||||
]
|
||||
};
|
||||
|
||||
// Short titles for mysteries (for display in headings)
|
||||
const mysteryTitles = {
|
||||
freudenreich: [
|
||||
"Verkündigung",
|
||||
"Heimsuchung",
|
||||
"Geburt",
|
||||
"Darstellung",
|
||||
"Wiederfindung"
|
||||
],
|
||||
schmerzhaften: [
|
||||
"Todesangst",
|
||||
"Geisselung",
|
||||
"Dornenkrönung",
|
||||
"Kreuzweg",
|
||||
"Kreuzigung"
|
||||
],
|
||||
glorreichen: [
|
||||
"Auferstehung",
|
||||
"Himmelfahrt",
|
||||
"Geistsendung",
|
||||
"Aufnahme Mariens",
|
||||
"Krönung Mariens"
|
||||
],
|
||||
lichtreichen: [
|
||||
"Taufe",
|
||||
"Hochzeit zu Kana",
|
||||
"Verkündigung des Reiches",
|
||||
"Verklärung",
|
||||
"Einsetzung der Eucharistie"
|
||||
]
|
||||
};
|
||||
|
||||
@@ -111,20 +147,27 @@ function getMysteryForWeekday(date, includeLuminous) {
|
||||
|
||||
// Determine which mystery to use based on current weekday
|
||||
let selectedMystery = getMysteryForWeekday(new Date(), includeLuminous);
|
||||
let todaysMystery = selectedMystery; // Track today's auto-selected mystery
|
||||
let currentMysteries = mysteries[selectedMystery];
|
||||
let currentMysteriesLatin = mysteriesLatin[selectedMystery];
|
||||
let currentMysteryTitles = mysteryTitles[selectedMystery];
|
||||
let currentMysteryDescriptions = data.mysteryDescriptions[selectedMystery] || [];
|
||||
|
||||
// Reactive statement to update mystery descriptions when selectedMystery changes
|
||||
$: currentMysteryDescriptions = data.mysteryDescriptions[selectedMystery] || [];
|
||||
|
||||
// Function to switch mysteries
|
||||
function selectMystery(mysteryType) {
|
||||
selectedMystery = mysteryType;
|
||||
currentMysteries = mysteries[mysteryType];
|
||||
currentMysteriesLatin = mysteriesLatin[mysteryType];
|
||||
currentMysteryTitles = mysteryTitles[mysteryType];
|
||||
}
|
||||
|
||||
// Function to handle toggle change
|
||||
function handleToggleChange() {
|
||||
// Recalculate the default mystery for today
|
||||
const todaysMystery = getMysteryForWeekday(new Date(), includeLuminous);
|
||||
todaysMystery = getMysteryForWeekday(new Date(), includeLuminous);
|
||||
// Update to today's mystery
|
||||
selectMystery(todaysMystery);
|
||||
}
|
||||
@@ -143,6 +186,12 @@ let decadeCounters = {
|
||||
secret5: 0
|
||||
};
|
||||
|
||||
// Modal state for displaying Bible citations
|
||||
let showModal = false;
|
||||
let selectedReference = '';
|
||||
let selectedTitle = '';
|
||||
let selectedVerseData = null;
|
||||
|
||||
// Function to advance the counter for a specific decade
|
||||
function advanceDecade(decadeNum) {
|
||||
const key = `secret${decadeNum}`;
|
||||
@@ -176,6 +225,14 @@ function advanceDecade(decadeNum) {
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle citation click
|
||||
function handleCitationClick(reference, title = '', verseData = null) {
|
||||
selectedReference = reference;
|
||||
selectedTitle = title;
|
||||
selectedVerseData = verseData;
|
||||
showModal = true;
|
||||
}
|
||||
|
||||
// Map sections to their vertical positions in the SVG
|
||||
const sectionPositions = {
|
||||
cross: 35,
|
||||
@@ -545,9 +602,9 @@ onMount(() => {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Make SVG beads larger on mobile by scaling up */
|
||||
/* Make SVG beads larger on mobile by scaling up and center it */
|
||||
.rosary-visualization svg {
|
||||
transform: scale(3.5) translateX(-5px);
|
||||
transform: scale(3.5);
|
||||
transform-origin: center top;
|
||||
}
|
||||
|
||||
@@ -561,6 +618,11 @@ onMount(() => {
|
||||
max-width: 100%;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
/* Reduce padding in prayer cards for mobile */
|
||||
.prayer-section {
|
||||
padding: 10rem;
|
||||
}
|
||||
}
|
||||
|
||||
.rosary-visualization {
|
||||
@@ -604,7 +666,6 @@ onMount(() => {
|
||||
}
|
||||
|
||||
.prayer-section {
|
||||
min-height: 50vh;
|
||||
scroll-snap-align: start;
|
||||
padding: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
@@ -622,6 +683,17 @@ onMount(() => {
|
||||
|
||||
.prayer-section.decade {
|
||||
scroll-snap-align: start;
|
||||
min-height: 50vh; /* Only decades need minimum height for scroll-snap */
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
.prayer-section.decade {
|
||||
padding-bottom: 1.5rem;
|
||||
}
|
||||
.prayer-section {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.prayer-section h2 {
|
||||
@@ -719,6 +791,7 @@ onMount(() => {
|
||||
.rosary-visualization :global(.cross-symbol) {
|
||||
fill: var(--nord4);
|
||||
transition: all 0.3s ease;
|
||||
font-family: crosses;
|
||||
}
|
||||
|
||||
/* Active states */
|
||||
@@ -745,35 +818,26 @@ h1 {
|
||||
|
||||
/* Luminous mysteries toggle */
|
||||
.luminous-toggle {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 2rem;
|
||||
padding: 1rem;
|
||||
background: var(--nord1);
|
||||
border-radius: 8px;
|
||||
max-width: 600px;
|
||||
max-width: 1200px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.luminous-toggle {
|
||||
background: var(--nord5);
|
||||
}
|
||||
}
|
||||
|
||||
.luminous-toggle label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
gap: 0.75rem;
|
||||
cursor: pointer;
|
||||
font-size: 1.1rem;
|
||||
font-size: 0.95rem;
|
||||
color: var(--nord4);
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.luminous-toggle label {
|
||||
color: var(--nord0);
|
||||
color: var(--nord2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,6 +858,7 @@ h1 {
|
||||
transition: background 0.3s ease;
|
||||
outline: none;
|
||||
border: none;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
@@ -823,34 +888,43 @@ h1 {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.luminous-toggle .toggle-description {
|
||||
margin-top: 1rem;
|
||||
font-size: 0.95rem;
|
||||
color: var(--nord8);
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
max-width: 500px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.luminous-toggle .toggle-description {
|
||||
color: var(--nord3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Mystery selector grid */
|
||||
.mystery-selector {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
max-width: 1000px;
|
||||
max-width: 750px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.mystery-selector.four-mysteries {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.mystery-selector.four-mysteries {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
max-width: 900px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.mystery-selector:not(.four-mysteries) {
|
||||
grid-template-columns: 1fr;
|
||||
max-width: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
.mystery-selector.four-mysteries {
|
||||
grid-template-columns: 1fr;
|
||||
max-width: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.mystery-button {
|
||||
background: var(--nord1);
|
||||
border: 2px solid transparent;
|
||||
@@ -863,6 +937,7 @@ h1 {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
@@ -878,20 +953,18 @@ h1 {
|
||||
|
||||
.mystery-button.selected {
|
||||
border-color: var(--nord10);
|
||||
background: var(--nord2);
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.mystery-button.selected {
|
||||
border-color: var(--nord10);
|
||||
background: var(--nord5);
|
||||
}
|
||||
}
|
||||
|
||||
.mystery-button:nth-child(1):hover { background: var(--nord15); }
|
||||
.mystery-button:nth-child(2):hover { background: var(--nord13); }
|
||||
.mystery-button:nth-child(3):hover { background: var(--nord14); }
|
||||
.mystery-button:nth-child(4):hover { background: var(--nord12); }
|
||||
.mystery-button:nth-child(1):hover,
|
||||
.mystery-button:nth-child(1).selected { background: var(--nord15); }
|
||||
.mystery-button:nth-child(2):hover,
|
||||
.mystery-button:nth-child(2).selected { background: var(--nord13); }
|
||||
.mystery-button:nth-child(3):hover,
|
||||
.mystery-button:nth-child(3).selected { background: var(--nord14); }
|
||||
.mystery-button:nth-child(4):hover,
|
||||
.mystery-button:nth-child(4).selected { background: var(--nord12); }
|
||||
|
||||
.mystery-button svg {
|
||||
width: 80px;
|
||||
@@ -927,49 +1000,135 @@ h1 {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Today's mystery badge */
|
||||
.today-badge {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
background: var(--nord11);
|
||||
color: white;
|
||||
padding: 0.4rem 0.8rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* Highlighted bead (orange for counting) */
|
||||
.rosary-visualization :global(.counted-bead) {
|
||||
fill: var(--nord13) !important;
|
||||
filter: drop-shadow(0 0 8px var(--nord13));
|
||||
}
|
||||
|
||||
/* Mystery description styling */
|
||||
.mystery-description {
|
||||
margin: 1.5rem 0 1.5rem 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mystery-title {
|
||||
font-weight: 700;
|
||||
color: var(--nord10);
|
||||
font-size: 1.1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.decade-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1rem;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.bible-reference-text {
|
||||
color: var(--nord8);
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.bible-reference-text {
|
||||
color: var(--nord10);
|
||||
}
|
||||
}
|
||||
|
||||
.bible-reference-button {
|
||||
background: var(--nord3);
|
||||
border: 2px solid var(--nord2);
|
||||
color: var(--nord6);
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
border-radius: 50%;
|
||||
transition: all 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.bible-reference-button:hover {
|
||||
background: var(--nord8);
|
||||
border-color: var(--nord9);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.bible-reference-button:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: light) {
|
||||
.bible-reference-button {
|
||||
background: var(--nord5);
|
||||
border-color: var(--nord4);
|
||||
color: var(--nord0);
|
||||
}
|
||||
|
||||
.bible-reference-button:hover {
|
||||
background: var(--nord4);
|
||||
border-color: var(--nord3);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<svelte:head>
|
||||
<title>Rosenkranz - Interaktiv</title>
|
||||
<title>Interaktiver Rosenkranz</title>
|
||||
<meta name="description" content="Interaktive digitale Version des Rosenkranzes zum Mitbeten. Scrolle durch die Gebete und folge der Visualisierung.">
|
||||
</svelte:head>
|
||||
|
||||
<div class="page-container">
|
||||
<h1>Interaktiver Rosenkranz</h1>
|
||||
|
||||
<!-- Luminous Mysteries Toggle -->
|
||||
<div class="luminous-toggle">
|
||||
<label>
|
||||
<input type="checkbox" bind:checked={includeLuminous} on:change={handleToggleChange} />
|
||||
<span>Lichtreiche Geheimnisse einbeziehen</span>
|
||||
</label>
|
||||
<p class="toggle-description">
|
||||
Die Geheimnisse werden automatisch nach dem Wochenplan ausgewählt.
|
||||
{#if includeLuminous}
|
||||
Mit lichtreichen Geheimnissen: Do=Lichtreich, andere Tage folgen dem traditionellen Plan.
|
||||
{:else}
|
||||
Traditioneller Plan ohne lichtreiche Geheimnisse.
|
||||
{/if}
|
||||
Sie können jederzeit manuell ein anderes Geheimnis wählen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2 style="text-align:center;">Geheimnisse</h2>
|
||||
<!-- Mystery Selector -->
|
||||
<div class="mystery-selector">
|
||||
<div class="mystery-selector" class:four-mysteries={includeLuminous}>
|
||||
<button
|
||||
class="mystery-button"
|
||||
class:selected={selectedMystery === 'freudenreich'}
|
||||
on:click={() => selectMystery('freudenreich')}
|
||||
>
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Placeholder: Star for joyful mysteries -->
|
||||
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
||||
{#if todaysMystery === 'freudenreich'}
|
||||
<span class="today-badge">Heutige</span>
|
||||
{/if}
|
||||
<svg viewBox="-10 0 2058 2048">
|
||||
<path d="M1935 90q0 32 -38 91q-21 29 -56 90q-20 55 -63 164q-35 86 -95 143q-22 -21 -43 -45q51 -49 85 -139q49 -130 61 -152q-126 48 -152 63q-76 46 -95 128q-27 -18 -58 -25q28 -104 97 -149q31 -20 138 -52q90 -28 137 -74l29 -39q22 -30 32 -30q21 0 21 26zM1714 653 q-90 30 -113 43q-65 36 -65 90q0 19 20 119q23 116 23 247q0 169 -103 299q-111 141 -275 141q-254 0 -283 87q-16 104 -31 207q-27 162 -76 162q-21 0 -41 -20q-16 -19 -32 -37q-10 3 -33 22q-18 15 -39 15q-28 0 -50 -44.5t-30 -44.5q-10 0 -35.5 11.5t-41.5 11.5 q-47 0 -58.5 -45.5t-21.5 -45.5t-29.5 2.5t-29.5 2.5q-46 0 -46 -30q0 -16 14 -44.5t14 -44.5q0 -8 -46.5 -25.5t-46.5 -48.5q0 -34 35.5 -52t99.5 -31q91 -19 103 -22q113 -32 171 -93q37 -39 105 -165q34 -64 43 -82q26 -53 31 -85q-129 -67 -224 -76q-33 0 -96 -11 q-36 -13 -36 -41q0 -7 2 -19.5t2 -19.5q0 -20 -67.5 -42t-67.5 -64q0 -11 8.5 -30t8.5 -30q0 -15 -79 -39t-79 -63q0 -16 9 -45t9 -45q0 -20 -29 -43q-23 -17 -46 -33q-49 -44 -49 -215q0 -8 1 -15q91 53 194 68l282 16q202 12 304 59q143 65 143 210q0 15 -2 44t-2 44 q0 122 78 122q73 0 108 -133q16 -70 32 -139q21 -81 57 -119q46 -51 130 -51q71 0 122 61q90 107 154 149zM1597 636q-25 -22 -77 -91q-30 -40 -75 -40q-91 0 -131 115q-30 106 -59 213q-44 115 -144 115q-146 0 -146 -180q0 -16 2.5 -46.5t2.5 -46.5q0 -62 -19 -87 q-70 -92 -303 -115q-173 -9 -347 -18q-55 -6 -116 -30v34q0 27 57.5 73.5t57.5 91.5q0 16 -10.5 45t-10.5 44q1 1 7 1q3 0 7 1q146 36 146 105q0 13 -8.5 32.5t-8.5 27.5h10q5 0 9 1q61 15 86 36q32 28 28 85q173 15 372 107q-7 77 -80 215q-67 128 -127 195 q-67 74 -169 104q-96 24 -193 47q-10 3 -29 13q86 18 86 70q0 19 -19 62q15 -5 33 -5q42 0 59 26q8 11 22 61l-1 3q10 0 34.5 -11.5t42.5 -11.5q55 0 88 84q38 -32 64 -32q37 0 66 41q25 -53 33 -151q10 -112 23 -154q43 -136 337 -136q116 0 215 -108q105 -114 105 -277 q0 -23 -12 -112l-28 -207q-4 -30 -4 -42q0 -97 124 -147zM1506 605q0 38 -38 38q-39 0 -39 -38t39 -38q38 0 38 38z" />
|
||||
<path d="m 1724.44,1054.6641 c -31.1769,-18 -37.7653,-42.5884 -19.7653,-73.76528 5.3333,-9.2376 12.354,-16.7312 21.0621,-22.4808 6.2201,-4.1068 44.7886,-7.2427 115.7055,-9.4077 70.9168,-2.1649 110.128,-1.0807 117.6336,3.2526 30.0222,17.3334 35.5333,42.45448 16.5333,75.36348 -7.3333,12.7017 -16.1754,20.6833 -26.5263,23.9448 -24.5645,1.2137 -56.7805,3.0135 -96.648,5.3994 -72.6282,5.7957 -115.2931,5.0269 -127.9949,-2.3065 z" />
|
||||
<path d="m 386.57764,1262.0569 c 53.44793,-14.3214 85.17574,-2.8075 95.18337,34.5417 9.83517,36.7052 -12.29319,62.3047 -66.38503,76.7986 l -82.1037,21.9996 c -54.09184,14.4939 -86.05533,3.3882 -95.89047,-33.317 -10.00766,-37.3491 12.67841,-63.4432 68.05807,-78.2821 z"/>
|
||||
<path d="m 1115.7599,372.22724 c 14.3213,53.44793 2.8073,85.17581 -34.5418,95.18323 -36.705,9.83527 -62.3047,-12.29323 -76.7986,-66.38485 l -21.99962,-82.10394 c -14.4939,-54.09162 -3.3882,-86.05531 33.31712,-95.89019 37.349,-10.00765 63.4431,12.67818 78.2821,68.05802 z" />
|
||||
<path d="m 1184.6228,1956.284 c -4.807,-8.0003 -6.8298,-42.7561 -6.0684,-104.2674 0.7614,-61.5113 2.7093,-100.0139 5.8437,-115.508 3.1343,-15.4941 11.8445,-27.5329 26.1306,-36.117 30.2866,-18.198 54.7006,-11.868 73.242,18.99 5.4937,9.1432 8.145,43.3269 7.9537,102.5512 -0.081,52.9359 -1.4296,89.5231 -4.0464,109.7617 -2.276,16.9226 -11.1284,30.0192 -26.5575,39.29 -33.1439,19.9148 -58.643,15.0146 -76.4977,-14.7005 z" />
|
||||
<path d="m 1773.3127,1737.6952 c -9.0153,-2.4157 -34.6139,-26.0118 -76.7955,-70.7882 -42.1816,-44.7764 -67.5266,-73.826 -76.035,-87.1489 -8.5084,-13.3228 -10.6057,-28.0334 -6.2922,-44.1323 9.145,-34.1293 31.1041,-46.5353 65.8774,-37.2179 10.3033,2.7609 35.9565,25.5088 76.9595,68.2441 36.7142,38.1352 61.1596,65.3907 73.3362,81.7668 10.1182,13.7541 12.8479,29.3245 8.1892,46.7113 -10.0077,37.3492 -31.7542,51.5375 -65.2396,42.5651 z" />
|
||||
</svg>
|
||||
<h3>Freudenreich</h3>
|
||||
<h3>Freudenreiche</h3>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@@ -977,9 +1136,11 @@ h1 {
|
||||
class:selected={selectedMystery === 'schmerzhaften'}
|
||||
on:click={() => selectMystery('schmerzhaften')}
|
||||
>
|
||||
{#if todaysMystery === 'schmerzhaften'}
|
||||
<span class="today-badge">Heutige</span>
|
||||
{/if}
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Placeholder: Cross for sorrowful mysteries -->
|
||||
<path d="M10 2h4v7h7v4h-7v9h-4v-9H3v-4h7V2z"/>
|
||||
<svg viewBox="0 0 512 512" ><path d="M255.094 24.875c-16.73 9.388-34.47 42.043-41.688 59.47-14.608-2.407-28.87-3.664-42.562-3.75-11.446-.074-22.49.68-33.03 2.218-16.34-8.284-34.766-29.065-42.626-50-9.324 15.704-9.558 42.313-5.782 64.593-19.443 9.72-35.107 23.633-45.53 41.688-7.262 12.577-11.5 26.34-12.97 40.875 13.294-25.904 35-46.957 65.656-54.345-34.99 31.783-59.85 87.186-51.5 129.406-1.2 22.87-9.48 37.647-24.75 44.595 16.335 4.59 35.497 3.343 49.438-1.28 24.94 34.82 60.818 67.882 105.063 94.342-6.952 17.613-16.677 49.21-16.47 66.032 10.846-13.178 37.433-40.585 61.72-42.783 23.656 10.27 47.35 17.698 70.312 22.313 12.423 17.25 12.895 38.867 7.375 53.594 16.402-9.2 33.82-33.187 39.938-48 47.1 1.423 88.046-10.534 114.718-35.563 17.536 5.52 30.744 15.707 39.813 30.5.243-19.578-8.05-44.353-18-60.31 13.42-28.268 12.786-61.81.5-96.158l.405.47c9.976-11.804 18.304-33.19 18.063-52.907-8.535 10.373-20.727 15.14-36.75 14.188-13.56-22.597-31.81-44.812-54.032-65.375 10.56-19.27 30.402-36.43 44.156-47.97-18.985-5.337-67.794 5.2-80.78 17.782l5.906 8.5c5.637 11.99 9.503 24.423 11.093 37.063-26.323-37.275-70.72-74.72-114.905-95.625-15.894-25.424-19.322-56.118-12.78-73.563zm-82.875 97.063c1.13-.015 2.258-.008 3.405 0 31.56.2 68.888 8.842 107 25.656-8.8 20.095-14.74 44.482-10 61.344 13.33-18.637 37.313-34.22 55.406-37.5 55.904 34.315 96.215 78.718 111.658 118.718l.093.22c16.088 37.88 13.36 85.186-26.56 117.312 4.79-11.41 7.986-23.828 9.5-36.438-14.078 10.012-33.524 15.304-56.314 15.97-1.954-17.242-9.117-52.874-22.28-65.72 1.565 16.122-8.11 46.272-26.22 61.063-31.916-6.495-66.794-19.67-101.03-39.438-9.538-5.506-18.65-11.307-27.314-17.344-3.444-23.614 7.842-53.562 20.563-64.03-18.967-.234-46.71 22.156-59.313 32.75-40.974-38.47-64.14-81.11-61.25-115 16.275-1.708 36.144.927 51.72 8-3.92-15.382-18.553-31.733-34.407-44.344 14.757-13.826 37.7-20.852 65.344-21.22z"/></svg>
|
||||
</svg>
|
||||
<h3>Schmerzhaften</h3>
|
||||
</button>
|
||||
@@ -989,10 +1150,20 @@ h1 {
|
||||
class:selected={selectedMystery === 'glorreichen'}
|
||||
on:click={() => selectMystery('glorreichen')}
|
||||
>
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Placeholder: Crown for glorious mysteries -->
|
||||
<path d="M5 16l3-6.5 4 4 4-4 3 6.5v4H5v-4zm0-13l2 2-2 2V5zm14 0l-2 2 2 2V5zM12 3l-2 2 2 2 2-2-2-2z"/>
|
||||
</svg>
|
||||
{#if todaysMystery === 'glorreichen'}
|
||||
<span class="today-badge">Heutige</span>
|
||||
{/if}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="-10 0 2060 2048">
|
||||
<path
|
||||
d="M1968 505l-119 632q101 61 101 163q0 149 -228 212q-171 47 -356 47h-682q-47 0 -111 -8q-210 -26 -293 -55q-180 -62 -180 -196q0 -124 101 -163l-119 -632h37q87 0 170 43q-18 85 -18 103q0 116 75 130q31 -47 77 -129l40 147q49 -37 95 -37t100 37q9 -38 31 -113
|
||||
q34 29 68 57q47 38 75 38q34 0 60 -27.5t26 -61.5q0 -26 -31 -74l-46 -72q46 -13 91 -26q55 -15 93 -15t93 15q45 13 91 26l-46 72q-31 51 -31 74q0 34 26 61.5t60 27.5q26 0 75 -38q34 -28 68 -57l31 113q66 -37 97 -37q56 0 95 37q14 -48 43 -145q39 66 77 127
|
||||
q75 -14 75 -130q0 17 -18 -103q89 -43 207 -43zM1889 557h-29q-10 0 -17 7q0 94 -9 130q-14 63 -67 110q-33 29 -63 29q-28 0 -59 -41q-31 115 -31 169q57 -36 77 -36q75 0 75 119q0 78 -32 126h-183q-54 -79 -54 -198v-5q64 -28 64 -80q0 -30 -20 -52.5t-50 -22.5
|
||||
q-33 0 -55 22.5t-22 55.5q0 53 46 74q-10 44 -21 86.5t-45.5 81t-39.5 38.5h-271q-21 -52 -21 -81q0 -65 47 -114.5t112 -49.5q29 0 106 36q7 -33 7 -82q0 -26 -7 -89q-42 43 -106 43q-65 0 -112 -49.5t-47 -114.5q0 -40 33 -105q-26 -7 -70 -7q-48 0 -70 7q33 63 33 105
|
||||
q0 65 -47 114.5t-112 49.5q-60 0 -106 -43q-7 63 -7 87q0 53 7 84q70 -36 106 -36q65 0 112 49.5t47 114.5q0 32 -21 81h-271q-16 0 -57 -58q-21 -30 -32 -72q-8 -38 -17 -76q46 -14 46 -74q0 -78 -77 -78q-30 0 -50 22t-20 53q0 48 64 80v4q0 125 -54 199h-183
|
||||
q-32 -54 -32 -124q0 -121 75 -121q19 0 77 36v-20q0 -27 -31 -151q-27 43 -59 43q-19 0 -51 -19q-40 -24 -67 -87q-24 -57 -24 -109q0 -10 1 -29t1 -28q-18 -1 -23 -1q-13 0 -22 1l46 241q64 17 64 101q0 51 -30 51q-3 0 -6 -1q19 83 39 212l-2 4q-102 20 -102 110
|
||||
q0 141 342 175q132 13 150 13h726q-9 0 55 -5q437 -34 437 -183q0 -88 -105 -111l40 -215q-2 0 -5 1q-31 0 -31 -51q0 -32 16 -62q19 -34 48 -39zM1518 888q0 34 -30 34q-34 0 -34 -34t32 -34t32 34zM1099 880q0 30 -22 51t-52 21q-29 0 -51.5 -21.5t-22.5 -50.5
|
||||
q0 -31 22 -54.5t52 -23.5q31 0 52.5 23.5t21.5 54.5zM596 888q0 34 -34 34q-30 0 -30 -34t32 -34t32 34z" />
|
||||
</svg>
|
||||
<h3>Glorreichen</h3>
|
||||
</button>
|
||||
|
||||
@@ -1002,92 +1173,107 @@ h1 {
|
||||
class:selected={selectedMystery === 'lichtreichen'}
|
||||
on:click={() => selectMystery('lichtreichen')}
|
||||
>
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Placeholder: Candle/Light for luminous mysteries -->
|
||||
<path d="M9 2h6v2H9V2zm3 3c-2.76 0-5 2.24-5 5 0 2.04 1.23 3.79 3 4.58V21h4v-6.42c1.77-.79 3-2.54 3-4.58 0-2.76-2.24-5-5-5zm0 2c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3z"/>
|
||||
</svg>
|
||||
{#if todaysMystery === 'lichtreichen'}
|
||||
<span class="today-badge">Heutige</span>
|
||||
{/if}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="-10 0 2156 2048">
|
||||
<path
|
||||
d="M1668 383q0 14 -48.5 92.5t-64.5 96t-41 17.5q-53 0 -53 -54q0 -16 46 -92q41 -68 60 -92q16 -20 43 -20q58 0 58 52zM688 535q0 54 -54 54q-16 0 -30 -7q-10 -5 -66 -95.5t-56 -103.5q0 -52 57 -52q22 0 34 11q20 31 53 81q62 90 62 112zM2064 842q0 59 -56 100
|
||||
q-231 162 -468 342l190 586q1 4 -5 28q-22 84 -110 84q-23 0 -45 -11q-18 -9 -203 -146l-291 -213q-125 89 -328 238q-51 39 -156 114q-28 18 -63 18q-46 0 -78.5 -32t-34.5 -78l194 -589q-76 -58 -197 -144q-81 -57 -163 -114q-126 -91 -147 -118t-21 -65q0 -36 29.5 -75.5
|
||||
t64.5 -39.5h604q33 -94 126 -375q19 -62 61 -184q29 -73 108 -73t110 83q4 11 58 177l123 372h607q34 0 64 41q27 38 27 74zM1129 1958q0 83 -58 83q-57 0 -57 -84v-85q0 -84 57 -84q58 0 58 86v84zM1943 849h-659l-211 -636l-207 629h-663l541 397l-206 621l537 -386
|
||||
l536 389l-209 -629zM1671 934l-370 267l150 436l-378 -271l-371 271q8 -34 15 -68q10 -41 28 -62q46 -53 144 -120q80 -53 159 -106l296 210l-112 -344l299 -213h140z" />
|
||||
</svg>
|
||||
|
||||
<h3>Lichtreichen</h3>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Luminous Mysteries Toggle -->
|
||||
<div class="luminous-toggle">
|
||||
<label>
|
||||
<input type="checkbox" bind:checked={includeLuminous} on:change={handleToggleChange} />
|
||||
<span>Lichtreiche Geheimnisse einbeziehen</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="rosary-layout">
|
||||
<!-- Sidebar: Rosary Visualization -->
|
||||
<div class="rosary-sidebar">
|
||||
<div class="rosary-visualization" bind:this={svgContainer}>
|
||||
<svg class="linear-rosary" viewBox="-100 -100 250 2200" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMin meet">
|
||||
<!-- Vertical chain -->
|
||||
<line x1="50" y1="35" x2="50" y2="1655" class="chain" />
|
||||
<line x1="25" y1="35" x2="25" y2="1655" class="chain" />
|
||||
|
||||
<!-- Cross (at top) -->
|
||||
<g id="cross-section" data-section="cross">
|
||||
<text x="50" y="35" text-anchor="middle" font-size="80"
|
||||
<text x="25" y="35" text-anchor="middle" font-size="80"
|
||||
class="cross-symbol" class:active-cross={activeSection === 'cross'}>♱</text>
|
||||
</g>
|
||||
|
||||
<!-- First large bead (Paternoster) -->
|
||||
<circle cx="50" cy="80" r="15" class="large-bead" class:active-large-bead={activeSection === 'lbead1'} data-section="lbead1" />
|
||||
<circle cx="25" cy="80" r="15" class="large-bead" class:active-large-bead={activeSection === 'lbead1'} data-section="lbead1" />
|
||||
|
||||
<!-- Three small beads -->
|
||||
<circle cx="50" cy="110" r="10" class="bead" class:active-bead={activeSection === 'start1'} data-section="start1" />
|
||||
<circle cx="50" cy="135" r="10" class="bead" class:active-bead={activeSection === 'start2'} data-section="start2" />
|
||||
<circle cx="50" cy="160" r="10" class="bead" class:active-bead={activeSection === 'start3'} data-section="start3" />
|
||||
<circle cx="25" cy="110" r="10" class="bead" class:active-bead={activeSection === 'start1'} data-section="start1" />
|
||||
<circle cx="25" cy="135" r="10" class="bead" class:active-bead={activeSection === 'start2'} data-section="start2" />
|
||||
<circle cx="25" cy="160" r="10" class="bead" class:active-bead={activeSection === 'start3'} data-section="start3" />
|
||||
|
||||
<!-- Large bead before decades -->
|
||||
<circle cx="50" cy="200" r="15" class="large-bead" class:active-large-bead={activeSection === 'lbead2'} data-section="lbead2" />
|
||||
<circle cx="25" cy="200" r="15" class="large-bead" class:active-large-bead={activeSection === 'lbead2'} data-section="lbead2" />
|
||||
|
||||
<!-- Benedictus Medal -->
|
||||
<BenedictusMedal x={30} y={220} size={40} />
|
||||
<BenedictusMedal x={5} y={220} size={40} />
|
||||
|
||||
<!-- Decade 1: Ave Maria (10 beads) -->
|
||||
{#each Array(10) as _, i}
|
||||
<circle cx="50" cy={280 + i * 22} r="10" class="bead"
|
||||
<circle cx="25" cy={280 + i * 22} r="10" class="bead"
|
||||
class:active-bead={activeSection === 'secret1'}
|
||||
class:counted-bead={i < decadeCounters.secret1}
|
||||
data-section="secret1" />
|
||||
{/each}
|
||||
<!-- Transition 1: Gloria + Fatima + Paternoster (large bead) -->
|
||||
<circle cx="50" cy="520" r="15" class="large-bead" class:active-large-bead={activeSection === 'secret1_transition'} data-section="secret1_transition" />
|
||||
<circle cx="25" cy="520" r="15" class="large-bead" class:active-large-bead={activeSection === 'secret1_transition'} data-section="secret1_transition" />
|
||||
|
||||
<!-- Decade 2: Ave Maria (10 beads) -->
|
||||
{#each Array(10) as _, i}
|
||||
<circle cx="50" cy={560 + i * 22} r="10" class="bead"
|
||||
<circle cx="25" cy={560 + i * 22} r="10" class="bead"
|
||||
class:active-bead={activeSection === 'secret2'}
|
||||
class:counted-bead={i < decadeCounters.secret2}
|
||||
data-section="secret2" />
|
||||
{/each}
|
||||
<!-- Transition 2: Gloria + Fatima + Paternoster (large bead) -->
|
||||
<circle cx="50" cy="800" r="15" class="large-bead" class:active-large-bead={activeSection === 'secret2_transition'} data-section="secret2_transition" />
|
||||
<circle cx="25" cy="800" r="15" class="large-bead" class:active-large-bead={activeSection === 'secret2_transition'} data-section="secret2_transition" />
|
||||
|
||||
<!-- Decade 3: Ave Maria (10 beads) -->
|
||||
{#each Array(10) as _, i}
|
||||
<circle cx="50" cy={840 + i * 22} r="10" class="bead"
|
||||
<circle cx="25" cy={840 + i * 22} r="10" class="bead"
|
||||
class:active-bead={activeSection === 'secret3'}
|
||||
class:counted-bead={i < decadeCounters.secret3}
|
||||
data-section="secret3" />
|
||||
{/each}
|
||||
<!-- Transition 3: Gloria + Fatima + Paternoster (large bead) -->
|
||||
<circle cx="50" cy="1080" r="15" class="large-bead" class:active-large-bead={activeSection === 'secret3_transition'} data-section="secret3_transition" />
|
||||
<circle cx="25" cy="1080" r="15" class="large-bead" class:active-large-bead={activeSection === 'secret3_transition'} data-section="secret3_transition" />
|
||||
|
||||
<!-- Decade 4: Ave Maria (10 beads) -->
|
||||
{#each Array(10) as _, i}
|
||||
<circle cx="50" cy={1120 + i * 22} r="10" class="bead"
|
||||
<circle cx="25" cy={1120 + i * 22} r="10" class="bead"
|
||||
class:active-bead={activeSection === 'secret4'}
|
||||
class:counted-bead={i < decadeCounters.secret4}
|
||||
data-section="secret4" />
|
||||
{/each}
|
||||
<!-- Transition 4: Gloria + Fatima + Paternoster (large bead) -->
|
||||
<circle cx="50" cy="1360" r="15" class="large-bead" class:active-large-bead={activeSection === 'secret4_transition'} data-section="secret4_transition" />
|
||||
<circle cx="25" cy="1360" r="15" class="large-bead" class:active-large-bead={activeSection === 'secret4_transition'} data-section="secret4_transition" />
|
||||
|
||||
<!-- Decade 5: Ave Maria (10 beads) -->
|
||||
{#each Array(10) as _, i}
|
||||
<circle cx="50" cy={1400 + i * 22} r="10" class="bead"
|
||||
<circle cx="25" cy={1400 + i * 22} r="10" class="bead"
|
||||
class:active-bead={activeSection === 'secret5'}
|
||||
class:counted-bead={i < decadeCounters.secret5}
|
||||
data-section="secret5" />
|
||||
{/each}
|
||||
<!-- Final transition: Gloria + Fatima -->
|
||||
<circle cx="50" cy="1640" r="15" class="large-bead" class:active-large-bead={activeSection === 'final_transition'} data-section="final_transition" />
|
||||
<circle cx="25" cy="1640" r="15" class="large-bead" class:active-large-bead={activeSection === 'final_transition'} data-section="final_transition" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1123,9 +1309,9 @@ h1 {
|
||||
bind:this={sectionElements.start1}
|
||||
data-section="start1"
|
||||
>
|
||||
<h3>Ave Maria</h3>
|
||||
<h3>Ave Maria: Glaube</h3>
|
||||
<AveMaria
|
||||
mysteryLatin="Jesus, qui fidem in nobis augeat"
|
||||
mysteryLatin="Jesus, qui adáugeat nobis fidem"
|
||||
mystery="Jesus, der in uns den Glauben vermehre"
|
||||
/>
|
||||
</div>
|
||||
@@ -1136,9 +1322,9 @@ h1 {
|
||||
bind:this={sectionElements.start2}
|
||||
data-section="start2"
|
||||
>
|
||||
<h3>Ave Maria</h3>
|
||||
<h3>Ave Maria: Hoffnung</h3>
|
||||
<AveMaria
|
||||
mysteryLatin="Jesus, qui spem in nobis firmet"
|
||||
mysteryLatin="Jesus, qui corróboret nobis spem"
|
||||
mystery="Jesus, der in uns die Hoffnung stärke"
|
||||
/>
|
||||
</div>
|
||||
@@ -1149,9 +1335,9 @@ h1 {
|
||||
bind:this={sectionElements.start3}
|
||||
data-section="start3"
|
||||
>
|
||||
<h3>Ave Maria</h3>
|
||||
<h3>Ave Maria: Liebe</h3>
|
||||
<AveMaria
|
||||
mysteryLatin="Jesus, qui caritatem in nobis accendat"
|
||||
mysteryLatin="Jesus, qui perficiat in nobis caritátem"
|
||||
mystery="Jesus, der in uns die Liebe entzünde"
|
||||
/>
|
||||
</div>
|
||||
@@ -1176,15 +1362,30 @@ h1 {
|
||||
bind:this={sectionElements[`secret${decadeNum}`]}
|
||||
data-section="secret{decadeNum}"
|
||||
>
|
||||
<h2>{decadeNum}. Gesätz</h2>
|
||||
<h2>{decadeNum}. Gesätz: {currentMysteryTitles[decadeNum - 1]}</h2>
|
||||
|
||||
<!-- Mystery description with Bible reference button -->
|
||||
<h3>Ave Maria <span class="repeat-count">(10×)</span></h3>
|
||||
<AveMaria
|
||||
mysteryLatin={currentMysteriesLatin[decadeNum - 1]}
|
||||
mystery={currentMysteries[decadeNum - 1]}
|
||||
/>
|
||||
|
||||
<!-- Counter button -->
|
||||
<CounterButton onClick={() => advanceDecade(decadeNum)} />
|
||||
<!-- Bible reference and counter buttons -->
|
||||
<div class="decade-buttons">
|
||||
{#if currentMysteryDescriptions[decadeNum - 1]}
|
||||
{@const description = currentMysteryDescriptions[decadeNum - 1]}
|
||||
<span class="bible-reference-text">{description.reference}</span>
|
||||
<button
|
||||
class="bible-reference-button"
|
||||
on:click={() => handleCitationClick(description.reference, description.title, description.verseData)}
|
||||
aria-label="Bibelstelle anzeigen"
|
||||
>
|
||||
📖
|
||||
</button>
|
||||
{/if}
|
||||
<CounterButton onClick={() => advanceDecade(decadeNum)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transition prayers (Gloria, Fatima, Paternoster) -->
|
||||
@@ -1222,6 +1423,11 @@ h1 {
|
||||
|
||||
<h3>Salve Regina</h3>
|
||||
<SalveRegina />
|
||||
|
||||
<h3>Schlussgebet</h3>
|
||||
<RosaryFinalPrayer />
|
||||
|
||||
<h3 style="text-align: center; font-size: 2.5rem; margin-top: 2rem;">♱</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1318,7 +1524,7 @@ Der Plan ohne lichtreiche Geheimnisse ist wie folgt:
|
||||
<h3>Die schmerzhaften Geheimnisse <i>(über das Leiden und Sterben Jesu)</i></h3>
|
||||
<ol><!-- dolorosa -->
|
||||
<li>... Jesus, der für uns Blut geschwitzt hat.</li>
|
||||
<li>... Jesus, der für uns gegeißelt worden ist.</li>
|
||||
<li>... Jesus, der für uns gegeisselt worden ist.</li>
|
||||
<li>... Jesus, der für uns mit Dornen gekrönt worden ist.</li>
|
||||
<li>... Jesus, der für uns das schwere Kreuz getragen hat.</li>
|
||||
<li>... Jesus, der für uns gekreuzigt worden ist.</li>
|
||||
@@ -1367,3 +1573,8 @@ Anders als die Geheimnisse in Deutsch ist es üblich beim beten des Rosenkranzes
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bible citation modal -->
|
||||
{#if showModal}
|
||||
<BibleModal reference={selectedReference} title={selectedTitle} verseData={selectedVerseData} onClose={() => showModal = false} />
|
||||
{/if}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { dbConnect } from '$utils/db';
|
||||
import { MarioKartTournament } from '$models/MarioKartTournament';
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
try {
|
||||
await dbConnect();
|
||||
|
||||
const tournaments = await MarioKartTournament.find()
|
||||
.sort({ createdAt: -1 })
|
||||
.lean({ flattenMaps: true });
|
||||
|
||||
// Convert MongoDB documents to plain objects for serialization
|
||||
const serializedTournaments = JSON.parse(JSON.stringify(tournaments));
|
||||
|
||||
return {
|
||||
tournaments: serializedTournaments
|
||||
};
|
||||
} catch (err) {
|
||||
console.error('Error loading tournaments:', err);
|
||||
throw error(500, 'Failed to load tournaments');
|
||||
}
|
||||
};
|
||||
@@ -1,569 +0,0 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
import { invalidateAll } from '$app/navigation';
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
let tournaments = $state(data.tournaments);
|
||||
let showCreateModal = $state(false);
|
||||
let newTournamentName = $state('');
|
||||
let roundsPerMatch = $state(3);
|
||||
let matchSize = $state(2);
|
||||
let loading = $state(false);
|
||||
|
||||
async function createTournament() {
|
||||
if (!newTournamentName.trim()) {
|
||||
alert('Please enter a tournament name');
|
||||
return;
|
||||
}
|
||||
|
||||
loading = true;
|
||||
try {
|
||||
const response = await fetch('/api/mario-kart/tournaments', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
name: newTournamentName,
|
||||
roundsPerMatch,
|
||||
matchSize
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
showCreateModal = false;
|
||||
newTournamentName = '';
|
||||
goto(`/mario-kart/${data.tournament._id}`);
|
||||
} else {
|
||||
const error = await response.json();
|
||||
alert(error.error || 'Failed to create tournament');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to create tournament:', error);
|
||||
alert('Failed to create tournament');
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteTournament(id, name) {
|
||||
if (!confirm(`Are you sure you want to delete "${name}"?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/mario-kart/tournaments/${id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
await invalidateAll();
|
||||
} else {
|
||||
const error = await response.json();
|
||||
alert(error.error || 'Failed to delete tournament');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to delete tournament:', error);
|
||||
alert('Failed to delete tournament');
|
||||
}
|
||||
}
|
||||
|
||||
function getStatusBadge(status) {
|
||||
const badges = {
|
||||
setup: { text: 'Setup', class: 'badge-blue' },
|
||||
group_stage: { text: 'Group Stage', class: 'badge-yellow' },
|
||||
bracket: { text: 'Bracket', class: 'badge-purple' },
|
||||
completed: { text: 'Completed', class: 'badge-green' }
|
||||
};
|
||||
return badges[status] || badges.setup;
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
return new Date(dateString).toLocaleDateString();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="header-content">
|
||||
<h1>Mario Kart Tournament Tracker</h1>
|
||||
<p>Manage your company Mario Kart tournaments</p>
|
||||
</div>
|
||||
<button class="btn-primary" onclick={() => showCreateModal = true}>
|
||||
Create Tournament
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if tournaments.length === 0}
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">🏁</div>
|
||||
<h2>No tournaments yet</h2>
|
||||
<p>Create your first Mario Kart tournament to get started!</p>
|
||||
<button class="btn-primary" onclick={() => showCreateModal = true}>
|
||||
Create Your First Tournament
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="tournaments-grid">
|
||||
{#each tournaments as tournament}
|
||||
<div class="tournament-card">
|
||||
<div class="card-header">
|
||||
<h3>{tournament.name}</h3>
|
||||
<span class="badge {getStatusBadge(tournament.status).class}">
|
||||
{getStatusBadge(tournament.status).text}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="card-stats">
|
||||
<div class="stat">
|
||||
<span class="stat-icon">👥</span>
|
||||
<span>{tournament.contestants.length} contestants</span>
|
||||
</div>
|
||||
{#if tournament.groups.length > 0}
|
||||
<div class="stat">
|
||||
<span class="stat-icon">🎮</span>
|
||||
<span>{tournament.groups.length} groups</span>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="stat">
|
||||
<span class="stat-icon">🔄</span>
|
||||
<span>{tournament.roundsPerMatch} rounds/match</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<span class="date">Created {formatDate(tournament.createdAt)}</span>
|
||||
<div class="actions">
|
||||
<a href="/mario-kart/{tournament._id}" class="btn-view">View</a>
|
||||
<button
|
||||
class="btn-delete"
|
||||
onclick={() => deleteTournament(tournament._id, tournament.name)}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if showCreateModal}
|
||||
<div class="modal-overlay" onclick={() => showCreateModal = false}>
|
||||
<div class="modal" onclick={(e) => e.stopPropagation()}>
|
||||
<div class="modal-header">
|
||||
<h2>Create New Tournament</h2>
|
||||
<button class="close-btn" onclick={() => showCreateModal = false}>×</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="tournament-name">Tournament Name</label>
|
||||
<input
|
||||
id="tournament-name"
|
||||
type="text"
|
||||
bind:value={newTournamentName}
|
||||
placeholder="e.g., Company Championship 2024"
|
||||
class="input"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="rounds-per-match">Rounds per Match</label>
|
||||
<input
|
||||
id="rounds-per-match"
|
||||
type="number"
|
||||
bind:value={roundsPerMatch}
|
||||
min="1"
|
||||
max="10"
|
||||
class="input"
|
||||
/>
|
||||
<small>How many races should each match have?</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="match-size">Match Size (Contestants per Match)</label>
|
||||
<input
|
||||
id="match-size"
|
||||
type="number"
|
||||
bind:value={matchSize}
|
||||
min="2"
|
||||
max="12"
|
||||
class="input"
|
||||
/>
|
||||
<small>How many contestants compete simultaneously? (2 for 1v1, 4 for 4-player matches)</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn-secondary" onclick={() => showCreateModal = false}>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="btn-primary"
|
||||
onclick={createTournament}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? 'Creating...' : 'Create Tournament'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.header-content h1 {
|
||||
font-size: 2rem;
|
||||
font-weight: 800;
|
||||
color: #1f2937;
|
||||
margin: 0 0 0.5rem 0;
|
||||
}
|
||||
|
||||
.header-content p {
|
||||
color: #6b7280;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 4rem 2rem;
|
||||
background: white;
|
||||
border-radius: 1rem;
|
||||
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 4rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.empty-state h2 {
|
||||
font-size: 1.5rem;
|
||||
color: #1f2937;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
color: #6b7280;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.tournaments-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.tournament-card {
|
||||
background: white;
|
||||
border-radius: 1rem;
|
||||
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
|
||||
padding: 1.5rem;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.tournament-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: start;
|
||||
margin-bottom: 1rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.card-header h3 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.badge {
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 9999px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.badge-blue {
|
||||
background: #dbeafe;
|
||||
color: #1e40af;
|
||||
}
|
||||
|
||||
.badge-yellow {
|
||||
background: #fef3c7;
|
||||
color: #92400e;
|
||||
}
|
||||
|
||||
.badge-purple {
|
||||
background: #e9d5ff;
|
||||
color: #6b21a8;
|
||||
}
|
||||
|
||||
.badge-green {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
}
|
||||
|
||||
.card-stats {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
padding: 1rem;
|
||||
background: #f9fafb;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.stat {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 0.875rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #3b82f6;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.625rem 1.25rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background: #2563eb;
|
||||
}
|
||||
|
||||
.btn-primary:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: white;
|
||||
color: #374151;
|
||||
border: 1px solid #d1d5db;
|
||||
padding: 0.625rem 1.25rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.btn-view {
|
||||
background: #10b981;
|
||||
color: white;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 0.375rem;
|
||||
text-decoration: none;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.btn-view:hover {
|
||||
background: #059669;
|
||||
}
|
||||
|
||||
.btn-delete {
|
||||
background: #ef4444;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 0.375rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.btn-delete:hover {
|
||||
background: #dc2626;
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 50;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.modal {
|
||||
background: white;
|
||||
border-radius: 1rem;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1);
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1.5rem;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.modal-header h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 2rem;
|
||||
color: #9ca3af;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.close-btn:hover {
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.form-group:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
color: #374151;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
padding: 0.625rem;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
outline: none;
|
||||
border-color: #3b82f6;
|
||||
ring: 2px;
|
||||
ring-color: rgba(59, 130, 246, 0.5);
|
||||
}
|
||||
|
||||
.form-group small {
|
||||
display: block;
|
||||
color: #6b7280;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.75rem;
|
||||
padding: 1.5rem;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.tournaments-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.actions {
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
.btn-view,
|
||||
.btn-delete {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,43 +0,0 @@
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { dbConnect } from '$utils/db';
|
||||
import { MarioKartTournament } from '$models/MarioKartTournament';
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
try {
|
||||
await dbConnect();
|
||||
|
||||
// Use lean with flattenMaps option to convert Map objects to plain objects
|
||||
const tournament = await MarioKartTournament.findById(params.id).lean({ flattenMaps: true });
|
||||
|
||||
if (!tournament) {
|
||||
throw error(404, 'Tournament not found');
|
||||
}
|
||||
|
||||
console.log('=== SERVER LOAD DEBUG ===');
|
||||
console.log('Raw tournament bracket:', tournament.bracket);
|
||||
if (tournament.bracket?.rounds) {
|
||||
console.log('First bracket round matches:', tournament.bracket.rounds[0]?.matches);
|
||||
}
|
||||
console.log('=== END SERVER LOAD DEBUG ===');
|
||||
|
||||
// Convert _id and other MongoDB ObjectIds to strings for serialization
|
||||
const serializedTournament = JSON.parse(JSON.stringify(tournament));
|
||||
|
||||
console.log('=== SERIALIZED DEBUG ===');
|
||||
if (serializedTournament.bracket?.rounds) {
|
||||
console.log('Serialized first bracket round matches:', serializedTournament.bracket.rounds[0]?.matches);
|
||||
}
|
||||
console.log('=== END SERIALIZED DEBUG ===');
|
||||
|
||||
return {
|
||||
tournament: serializedTournament
|
||||
};
|
||||
} catch (err: any) {
|
||||
if (err.status === 404) {
|
||||
throw err;
|
||||
}
|
||||
console.error('Error loading tournament:', err);
|
||||
throw error(500, 'Failed to load tournament');
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,7 +52,7 @@ h1{
|
||||
|
||||
<p>
|
||||
Die Fensterprobe ist eine Methode um den optimalen Knetzustand eines Teiges zu bestimmen.
|
||||
Dazu wird ein kleines, ca. Walnussgrosses Stück Teig zwischen den Fingern auseinandergezogen. Ist der Teig elastisch und reißt nicht bis der Teig so dünn ist, dass man leicht licht durchsehen kann, so ist der Teig optimal verknetet.
|
||||
Dazu wird ein kleines, ca. Walnussgrosses Stück Teig zwischen den Fingern auseinandergezogen. Ist der Teig elastisch und reisst nicht bis der Teig so dünn ist, dass man leicht licht durchsehen kann, so ist der Teig optimal verknetet.
|
||||
</p>
|
||||
<p>
|
||||
Teig lässt sich leichter verkneten wenn er noch trockener ist. Daher lohnt es sich zunächst etwa 10% der Flüssigkeit zurückzuhalten und erst nach und nach zuzugeben nachdem der Teig bereits für einige Minuten geknetet wurde.
|
||||
|
||||
BIN
static/fonts/LinLibertine_Rah.ttf
Normal file
BIN
static/fonts/LinLibertine_Rah.ttf
Normal file
Binary file not shown.
BIN
static/fonts/LinLibertine_minimal.ttf
Normal file
BIN
static/fonts/LinLibertine_minimal.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UnifrakturMaguntia18.ttf
Normal file
BIN
static/fonts/UnifrakturMaguntia18.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UnifrakturMaguntia19.ttf
Normal file
BIN
static/fonts/UnifrakturMaguntia19.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UnifrakturMaguntia20.ttf
Normal file
BIN
static/fonts/UnifrakturMaguntia20.ttf
Normal file
Binary file not shown.
BIN
static/fonts/UnifrakturMaguntia21.ttf
Normal file
BIN
static/fonts/UnifrakturMaguntia21.ttf
Normal file
Binary file not shown.
BIN
static/fonts/crosses.ttf
Normal file
BIN
static/fonts/crosses.ttf
Normal file
Binary file not shown.
BIN
static/fonts/crosses.woff2
Normal file
BIN
static/fonts/crosses.woff2
Normal file
Binary file not shown.
BIN
static/fonts/devjavu_serif_minimal.ttf
Normal file
BIN
static/fonts/devjavu_serif_minimal.ttf
Normal file
Binary file not shown.
Reference in New Issue
Block a user