@@ -358,21 +286,7 @@ const Contact = () => {
ogDescription={t('contact.description')}
ogImage="/placeholder.svg"
/>
-
-
-
-
-
- {t('navigation.home')}
-
-
-
-
- {t('navigation.contact')}
-
-
-
-
+
{/* Hero Section */}
diff --git a/src/pages/Dashboard.tsx b/src/pages/Dashboard.tsx
index d9618bd..311b47c 100644
--- a/src/pages/Dashboard.tsx
+++ b/src/pages/Dashboard.tsx
@@ -26,7 +26,7 @@ import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import Loading from '@/components/Loading';
import { AlertTriangle, Loader2, LogOut, RefreshCcw } from 'lucide-react';
import { useTranslation } from 'react-i18next';
-import { getNormalizedLocale } from '@/lib/i18n';
+import { createDateFormatter, formatDate } from '@/lib/i18n';
type Profile = Database['public']['Tables']['profiles']['Row'];
type Lead = Database['public']['Tables']['leads']['Row'];
@@ -149,44 +149,17 @@ const Dashboard = () => {
void loadDashboard();
}, [loadDashboard]);
- const normalizedLocale = useMemo(
- () => getNormalizedLocale(i18n.language),
+ const dateTimeFormatter = useMemo(
+ () => createDateFormatter(i18n.language, {
+ dateStyle: 'short',
+ timeStyle: 'short',
+ }),
[i18n.language]
);
- const fallbackDateFormatter = useMemo(
- () =>
- new Intl.DateTimeFormat('en-US', {
- dateStyle: 'short',
- timeStyle: 'short',
- }),
- []
- );
-
- const dateTimeFormatter = useMemo(() => {
- try {
- return new Intl.DateTimeFormat(normalizedLocale, {
- dateStyle: 'short',
- timeStyle: 'short',
- });
- } catch (error) {
- console.error('Unsupported locale for dashboard date formatting', error);
- return fallbackDateFormatter;
- }
- }, [fallbackDateFormatter, normalizedLocale]);
-
- const formatDate = useCallback(
- (value: string | null | undefined) => {
- if (!value) return '—';
-
- try {
- return dateTimeFormatter.format(new Date(value));
- } catch (error) {
- console.error('Error formatting dashboard date', error);
- return fallbackDateFormatter.format(new Date(value));
- }
- },
- [dateTimeFormatter, fallbackDateFormatter]
+ const formatDashboardDate = useCallback(
+ (value: string | null | undefined) => formatDate(value, dateTimeFormatter),
+ [dateTimeFormatter]
);
const handleRefresh = () => {
@@ -350,7 +323,7 @@ const Dashboard = () => {
{t('dashboard.profile.updatedAt')}
- {formatDate(profile?.updated_at)}
+ {formatDashboardDate(profile?.updated_at)}
@@ -401,7 +374,7 @@ const Dashboard = () => {
{lead.project ?? '—'}
{lead.message}
- {formatDate(lead.created_at)}
+ {formatDashboardDate(lead.created_at)}
))}
@@ -451,7 +424,7 @@ const Dashboard = () => {
- {formatDate(subscriber.subscribed_at)}
+ {formatDashboardDate(subscriber.subscribed_at)}
))}
diff --git a/src/pages/Projects.tsx b/src/pages/Projects.tsx
index c75d31f..c4516ae 100644
--- a/src/pages/Projects.tsx
+++ b/src/pages/Projects.tsx
@@ -3,17 +3,10 @@ import { useQuery } from '@tanstack/react-query';
import { Github, ExternalLink, Calendar, ArrowRight } from 'lucide-react';
import Layout from '../components/Layout';
import Meta from '@/components/Meta';
+import { PageBreadcrumb } from '@/components/PageBreadcrumb';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
-import {
- Breadcrumb,
- BreadcrumbList,
- BreadcrumbItem,
- BreadcrumbLink,
- BreadcrumbPage,
- BreadcrumbSeparator,
-} from '@/components/ui/breadcrumb';
import { supabase } from '@/integrations/supabase';
import { useTranslation, Trans } from 'react-i18next';
import { Link } from 'react-router-dom';
@@ -25,7 +18,7 @@ import {
} from '@/lib/solutions';
import type { GitHubRepository } from '@/lib/solutions';
import type { SolutionContent } from '@/types/solutions';
-import { getNormalizedLocale } from '@/lib/i18n';
+import { createDateFormatter, formatDate } from '@/lib/i18n';
import {
SolutionCard,
sectionContainer,
@@ -52,44 +45,18 @@ const Projects = () => {
const memoizedFallbackSolutions = useMemo(() => getFallbackSolutions(), []);
- const normalizedLocale = useMemo(
- () => getNormalizedLocale(i18n.language),
+ const dateFormatter = useMemo(
+ () => createDateFormatter(i18n.language, {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ }),
[i18n.language]
);
- const fallbackDateFormatter = useMemo(
- () =>
- new Intl.DateTimeFormat('en-US', {
- year: 'numeric',
- month: 'short',
- day: 'numeric',
- }),
- []
- );
-
- const dateFormatter = useMemo(() => {
- try {
- return new Intl.DateTimeFormat(normalizedLocale, {
- year: 'numeric',
- month: 'short',
- day: 'numeric',
- });
- } catch (error) {
- console.error('Unsupported locale for project date formatting', error);
- return fallbackDateFormatter;
- }
- }, [fallbackDateFormatter, normalizedLocale]);
-
- const formatDate = useCallback(
- (dateString: string) => {
- try {
- return dateFormatter.format(new Date(dateString));
- } catch (error) {
- console.error('Error formatting project date', error);
- return fallbackDateFormatter.format(new Date(dateString));
- }
- },
- [dateFormatter, fallbackDateFormatter]
+ const formatProjectDate = useCallback(
+ (dateString: string) => formatDate(dateString, dateFormatter),
+ [dateFormatter]
);
const {
@@ -254,21 +221,7 @@ const Projects = () => {
ogDescription={t('projects.description')}
ogImage="/placeholder.svg"
/>
-
-
-
-
-
- {t('navigation.home')}
-
-
-
-
- {t('navigation.projects')}
-
-
-
-
+
@@ -457,7 +410,7 @@ const Projects = () => {
- {formatDate(repo.created_at)}
+ {formatProjectDate(repo.created_at)}
diff --git a/src/pages/Solutions.tsx b/src/pages/Solutions.tsx
index 596f39f..8972bf6 100644
--- a/src/pages/Solutions.tsx
+++ b/src/pages/Solutions.tsx
@@ -3,15 +3,8 @@ import { useQuery } from '@tanstack/react-query';
import { Button } from '@/components/ui/button';
import Layout from '@/components/Layout';
import Meta from '@/components/Meta';
+import { PageBreadcrumb } from '@/components/PageBreadcrumb';
import { Link } from 'react-router-dom';
-import {
- Breadcrumb,
- BreadcrumbList,
- BreadcrumbItem,
- BreadcrumbLink,
- BreadcrumbPage,
- BreadcrumbSeparator,
-} from '@/components/ui/breadcrumb';
import { ArrowRight } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { supabase } from '@/integrations/supabase';
@@ -109,21 +102,7 @@ const Solutions = () => {
ogDescription={t('solutionsPage.description')}
ogImage="/placeholder.svg"
/>
-
-
-
-
-
- {t('navigation.home')}
-
-
-
-
- {t('navigation.solutions')}
-
-
-
-
+
{/* Hero Section */}
diff --git a/src/pages/blog/[slug].tsx b/src/pages/blog/[slug].tsx
index b1e024f..b9600fb 100644
--- a/src/pages/blog/[slug].tsx
+++ b/src/pages/blog/[slug].tsx
@@ -7,17 +7,10 @@ import Layout from '@/components/Layout';
import Meta from '@/components/Meta';
import NewsletterSection from '@/components/NewsletterSection';
import CommentsSection from '@/components/blog/CommentsSection';
+import { PageBreadcrumb } from '@/components/PageBreadcrumb';
import { supabase } from '@/integrations/supabase';
-import { getNormalizedLocale } from '@/lib/i18n';
+import { createDateFormatter } from '@/lib/i18n';
import type { Database } from '@/integrations/supabase/types';
-import {
- Breadcrumb,
- BreadcrumbList,
- BreadcrumbItem,
- BreadcrumbLink,
- BreadcrumbPage,
- BreadcrumbSeparator,
-} from '@/components/ui/breadcrumb';
type BlogPost = Database['public']['Tables']['blog_posts']['Row'];
@@ -213,22 +206,11 @@ const BlogPostPage = () => {
const { slug } = useParams<{ slug: string }>();
const { t, i18n } = useTranslation();
- const normalizedLocale = useMemo(
- () => getNormalizedLocale(i18n.language),
+ const dateFormatter = useMemo(
+ () => createDateFormatter(i18n.language, { dateStyle: 'long' }),
[i18n.language]
);
- const dateFormatter = useMemo(() => {
- try {
- return new Intl.DateTimeFormat(normalizedLocale, {
- dateStyle: 'long',
- });
- } catch (error) {
- console.error('Unsupported locale for blog post date formatting', error);
- return new Intl.DateTimeFormat('en-US', { dateStyle: 'long' });
- }
- }, [normalizedLocale]);
-
const {
data: post,
isLoading,
@@ -336,27 +318,10 @@ const BlogPostPage = () => {
ogDescription={metaDescription}
ogImage={metaImage}
/>
-
-
-
-
-
- {t('navigation.home')}
-
-
-
-
-
- {t('navigation.blog')}
-
-
-
-
- {post.title}
-
-
-
-
+
{
ogDescription={displaySolution.description}
ogImage={displaySolution.imageUrl ?? '/placeholder.svg'}
/>
-
-
-
-
-
- {t('navigation.home')}
-
-
-
-
-
- {t('navigation.solutions')}
-
-
-
-
- {displaySolution.title}
-
-
-
-
+