Compare commits

...

3 Commits

9 changed files with 159 additions and 99 deletions

View File

@@ -14,7 +14,10 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
const pathname = usePathname();
const getPageTitle = (path: string) => {
if (path === "/") return "Overview";
const pathSegments = path.split("/").filter(Boolean);
if (pathSegments.length <= 1) return "Overview";
const purePath = `/${pathSegments.slice(1).join("/")}`;
const titles: Record<string, string> = {
"/users": "Users",
@@ -24,7 +27,8 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
"/events": "Worship & Events",
};
return titles[path] || "Dashboard";
return titles[purePath] || "Dashboard";
};
return (

View File

@@ -13,11 +13,11 @@ export interface BibleVerse {
export const bibleVerses: BibleVerse[] = [
{
reference: "Epheser 2:19",
reference: "Epheser 2:19-22",
content: {
en: "So then you are no longer strangers and aliens...",
de: "So seid ihr nun nicht mehr Gäste und Fremdlinge...",
ru: "Итак вы уже не чужие и не пришельцы..."
en: "So then you are no longer strangers and aliens, but you are fellow citizens with the saints and members of the household of God, built on the foundation of the apostles and prophets, Christ Jesus himself being the cornerstone, in whom the whole structure, being joined together, grows into a holy temple in the Lord. In him you also are being built together into a dwelling place for God by the Spirit.",
de: "So seid ihr nun nicht mehr Gäste und Fremdlinge, sondern Mitbürger der Heiligen und Gottes Hausgenossen, erbaut auf den Grund der Apostel und Propheten, da Jesus Christus der Eckstein ist, auf welchem der ganze Bau ineinandergefügt wächst zu einem heiligen Tempel in dem Herrn. Durch ihn werdet auch ihr mit erbaut zu einer Wohnung Gottes im Geist.",
ru: "Итак, вы уже не чужие и не пришельцы, но сограждане святым и свои Богу, быв утверждены на основании Апостолов и пророков, имея Самого Иисуса Христа краеугольным камнем, на котором всё здание, слагаясь стройно, возрастает в святой храм в Господе, на котором и вы устрояетесь в жилище Божие Духом."
}
},
{

View File

@@ -26,6 +26,8 @@ import { useParams } from "next/navigation";
import Link from "next/link";
import React from "react";
import { bibleVerses, localizedContent } from "./lib/dailyVerseData";
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import Image from "next/image";
const Dashboard: React.FC = () => {
// 1. Get a unique number for the current day
@@ -39,7 +41,6 @@ const Dashboard: React.FC = () => {
const todayVerse = bibleVerses[verseIndex];
const params = useParams();
const lng = params.locale as keyof localizedContent || "en"; // Default to English if no locale is provided
const t = useTranslations("dashboard");
const categories: ModuleCategory[] = [
@@ -184,22 +185,21 @@ const Dashboard: React.FC = () => {
return (
<div className="mx-auto max-w-7xl space-y-8">
{/* Welcome Section */}
<div className="flex flex-col justify-between gap-4 md:flex-row md:items-center">
<div>
<h1 className="text-foreground text-3xl font-bold tracking-tight">
{t("title")}
</h1>
<p className="text-muted-foreground mt-1">{t("greeting", { user: "David", church: "Rastatt" })}</p>
<p className="text-muted-foreground mt-1">{t("verse_intro")}</p>
<p className="text-muted-foreground mt-1">
{todayVerse.content[lng]}"
</p>
<span className="text-sm text-muted-foreground">({todayVerse.reference})</span>
<div data-cmp="ModuleCard" className="group bg-card border border-border rounded-xl p-6 h-full overflow-hidden">
<div className="animate-in items-baseline fade-in slide-in-from-bottom-4 duration-700 flex flex-col sm:flex-row grow pr-6 gap-2">
<span className="text-2xl md:text-3xl text-nowrap font-semibold leading-none">{t("greeting_name", { user: "Alexander" })}</span>
<span className="text-xl font-semibold text-nowrap leading-none"> {t("greeting")}</span>
</div>
<div className="flex space-x-3">
<Badge variant="secondary" className="px-2.5 py-0.5 text-sm">
v2.4.0 Live
</Badge>
<div className="flex-col mt-4">
<p>
<span className="font-semibold">{t("verse_intro")}</span> <br />
<i className="italic text-foreground">"{todayVerse.content[lng]}"</i>
</p>
<div className="flex justify-end mt-3">
<Badge variant="outline" className="rounded-sm self-start">
{todayVerse.reference}
</Badge>
</div>
</div>
</div>

View File

@@ -44,72 +44,114 @@
}
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.129 0.042 264.695);
--card: oklch(1 0 0);
--card-foreground: oklch(0.129 0.042 264.695);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.129 0.042 264.695);
--primary: oklch(0.208 0.042 265.755);
--primary-foreground: oklch(0.984 0.003 247.858);
--secondary: oklch(0.968 0.007 247.896);
--secondary-foreground: oklch(0.208 0.042 265.755);
--muted: oklch(0.968 0.007 247.896);
--muted-foreground: oklch(0.554 0.046 257.417);
--accent: oklch(0.968 0.007 247.896);
--accent-foreground: oklch(0.208 0.042 265.755);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.929 0.013 255.508);
--input: oklch(0.929 0.013 255.508);
--ring: oklch(0.704 0.04 256.788);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.984 0.003 247.858);
--sidebar-foreground: oklch(0.129 0.042 264.695);
--sidebar-primary: oklch(0.208 0.042 265.755);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.968 0.007 247.896);
--sidebar-accent-foreground: oklch(0.208 0.042 265.755);
--sidebar-border: oklch(0.929 0.013 255.508);
--sidebar-ring: oklch(0.704 0.04 256.788);
--radius: 0.125rem;
/* ---------- Base background (warm light) ---------- */
--background: oklch(0.97 0.01 95);
--foreground: oklch(0.22 0.02 30);
/* ---------- Surfaces ---------- */
--card: oklch(0.99 0.005 95);
--card-foreground: oklch(0.22 0.02 30);
--popover: oklch(1 0.004 95);
--popover-foreground: oklch(0.22 0.02 30);
/* ---------- Ubuntu orange primary ---------- */
--primary: oklch(0.62 0.2 45);
--primary-foreground: oklch(0.99 0.005 95);
/* ---------- Secondary / muted warm grays ---------- */
--secondary: oklch(0.92 0.01 90);
--secondary-foreground: oklch(0.3 0.02 35);
--muted: oklch(0.94 0.008 90);
--muted-foreground: oklch(0.45 0.015 35);
--accent: oklch(0.9 0.015 85);
--accent-foreground: oklch(0.3 0.02 35);
/* ---------- Destructive ---------- */
--destructive: oklch(0.58 0.23 25);
/* ---------- Borders / inputs ---------- */
--border: oklch(0.85 0.01 90);
--input: oklch(0.88 0.01 90);
--ring: oklch(0.62 0.2 45 / 0.5);
/* ---------- Charts ---------- */
--chart-1: oklch(0.62 0.2 45); /* orange */
--chart-2: oklch(0.55 0.16 150); /* green */
--chart-3: oklch(0.7 0.17 85); /* yellow */
--chart-4: oklch(0.6 0.18 300); /* purple */
--chart-5: oklch(0.6 0.2 20); /* red */
/* ---------- Sidebar ---------- */
--sidebar: oklch(0.95 0.01 90);
--sidebar-foreground: oklch(0.28 0.02 30);
--sidebar-primary: oklch(0.62 0.2 45);
--sidebar-primary-foreground: oklch(0.99 0.005 95);
--sidebar-accent: oklch(0.9 0.015 85);
--sidebar-accent-foreground: oklch(0.3 0.02 35);
--sidebar-border: oklch(0.85 0.01 90);
--sidebar-ring: oklch(0.62 0.2 45 / 0.5);
}
.dark {
--background: oklch(0.129 0.042 264.695);
--foreground: oklch(0.984 0.003 247.858);
--card: oklch(0.208 0.042 265.755);
--card-foreground: oklch(0.984 0.003 247.858);
--popover: oklch(0.208 0.042 265.755);
--popover-foreground: oklch(0.984 0.003 247.858);
--primary: oklch(0.929 0.013 255.508);
--primary-foreground: oklch(0.208 0.042 265.755);
--secondary: oklch(0.279 0.041 260.031);
--secondary-foreground: oklch(0.984 0.003 247.858);
--muted: oklch(0.279 0.041 260.031);
--muted-foreground: oklch(0.704 0.04 256.788);
--accent: oklch(0.279 0.041 260.031);
--accent-foreground: oklch(0.984 0.003 247.858);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.551 0.027 264.364);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.208 0.042 265.755);
--sidebar-foreground: oklch(0.984 0.003 247.858);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.279 0.041 260.031);
--sidebar-accent-foreground: oklch(0.984 0.003 247.858);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.551 0.027 264.364);
/* ---------- Base background (warm charcoal) ---------- */
--background: oklch(0.11 0.015 30);
--foreground: oklch(0.97 0.01 95);
/* ---------- Surfaces ---------- */
--card: oklch(0.16 0.018 32);
--card-foreground: oklch(0.97 0.01 95);
--popover: oklch(0.18 0.02 32);
--popover-foreground: oklch(0.97 0.01 95);
/* ---------- Ubuntu orange primary ---------- */
--primary: oklch(0.68 0.19 45);
--primary-foreground: oklch(0.98 0.01 95);
/* ---------- Secondary / muted warm grays ---------- */
--secondary: oklch(0.22 0.02 30);
--secondary-foreground: oklch(0.92 0.015 95);
--muted: oklch(0.22 0.02 30);
--muted-foreground: oklch(0.68 0.02 90);
--accent: oklch(0.26 0.025 35);
--accent-foreground: oklch(0.95 0.01 95);
/* ---------- Destructive (Ubuntu red tone) ---------- */
--destructive: oklch(0.62 0.22 25);
/* ---------- Borders / inputs ---------- */
--border: oklch(0.3 0.015 35 / 0.6);
--input: oklch(0.3 0.015 35 / 0.8);
--ring: oklch(0.68 0.19 45 / 0.6);
/* ---------- Charts ---------- */
--chart-1: oklch(0.68 0.19 45); /* orange */
--chart-2: oklch(0.7 0.15 150); /* green */
--chart-3: oklch(0.78 0.16 85); /* yellow */
--chart-4: oklch(0.66 0.18 300); /* purple */
--chart-5: oklch(0.7 0.18 20); /* red */
/* ---------- Sidebar (slightly darker & warmer) ---------- */
--sidebar: oklch(0.14 0.018 30);
--sidebar-foreground: oklch(0.95 0.01 95);
--sidebar-primary: oklch(0.68 0.19 45);
--sidebar-primary-foreground: oklch(0.98 0.01 95);
--sidebar-accent: oklch(0.24 0.02 32);
--sidebar-accent-foreground: oklch(0.95 0.01 95);
--sidebar-border: oklch(0.3 0.015 35 / 0.5);
--sidebar-ring: oklch(0.68 0.19 45 / 0.6);
}
/* === CUSTOM COLOR THEME === */

View File

@@ -7,6 +7,7 @@ interface HeaderProps {
}
const Header: React.FC<HeaderProps> = ({ onMenuClick, pageTitle }) => {
const [hasError, setHasError] = React.useState(false);
return (
<header
data-cmp="Header"
@@ -55,9 +56,19 @@ const Header: React.FC<HeaderProps> = ({ onMenuClick, pageTitle }) => {
<p className="text-foreground text-sm font-medium">Community Admin</p>
<p className="text-muted-foreground text-xs">Super Administrator</p>
</div>
<div className="bg-primary/10 border-primary/20 flex h-9 w-9 shrink-0 items-center justify-center rounded-full border">
<User className="text-primary h-5 w-5" />
</div>
{hasError ? (
<div className="w-10 h-10 rounded-full border border-border bg-muted flex items-center justify-center">
<User className="w-6 h-6 text-muted-foreground" />
</div>
) : (
<img
src="/images/IMG_84271.jpg"
alt="Profile"
className="w-10 h-10 rounded-full object-cover border border-border"
/* If image fails to load, set hasError to true */
onError={() => setHasError(true)}
/>
)}
</div>
</div>
</header>

View File

@@ -11,8 +11,9 @@
"dashboard": {
"title": "Community-Dashboard",
"welcome": "Willkommen im Admin-Bereich. Verwalten Sie Ihre Community-Ressourcen sicher.",
"greeting": "Lieber {user}, deine örtliche Gemeinde {church} begrüßt dich!",
"verse_intro": "Lass dich durch den folgenden Vers ermutigen:"
"greeting_name": "Lieber Bruder {user},",
"greeting": "Friede sei mit Dir!",
"verse_intro": "Zur Ermutigung:"
},
"users": {
"title": "Benutzer",

View File

@@ -11,8 +11,9 @@
"dashboard": {
"title": "Community Dashboard",
"welcome": "Welcome to the admin area. Manage your community resources safely.",
"greeting": "Dear {user}, your local community {church} welcomes you!",
"verse_intro": "Let the following verse encourage you:"
"greeting_name": "Dear brother {user},",
"greeting": "peace be with you!",
"verse_intro": "For encouragement:"
},
"users": {
"title": "Users",

View File

@@ -11,8 +11,9 @@
"dashboard": {
"title": "Community Dashboard",
"welcome": "Добро пожаловать в административный раздел. Безопасно управляйте ресурсами вашего сообщества.",
"greeting": "Дорогой {user}, твоя местная община {church} приветствует тебя!",
"verse_intro": "Пусть этот стих подбодрит тебя:"
"greeting_name": "Дорогой брат {user},",
"greeting": "мир Тебе!",
"verse_intro": "Для ободрения:"
},
"users": {
"title": "Пользователи",

BIN
public/images/IMG_84271.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB