/opt/canhelp/apps/web/src/app
Edit: /opt/canhelp/apps/web/src/app/page.tsx (24337B)
import Link from 'next/link'
import { cookies } from 'next/headers'
import { getCategories, getLocations } from '@/lib/api'
import { getTranslations, type Locale } from '@/lib/translations'
import type { Category } from '@canhelp/shared'
import { HomeCityCloud } from '@/components/HomeCityCloud'
import { ShareButton } from '@/components/ShareButton'
import { CommunityArt } from '@/components/HomeSectionArt'
import { Section } from '@/components/Section'
import { HeroSearch } from '@/components/HeroSearch'
import { HeroFloatingIcons } from '@/components/HeroFloatingIcons'
import { FaqAccordion } from '@/components/FaqAccordion'
import { BecomeSpecialistButton } from '@/components/BecomeSpecialistButton'
import { PromoCountdown } from '@/components/PromoCountdown'
import { HomeCategoryGrid } from '@/components/HomeCategoryGrid'
export default async function HomePage() {
const cookieStore = await cookies()
const rawLocale = cookieStore.get('canhelp_locale')?.value as Locale | undefined
const locale: Locale = ['el', 'en', 'uk', 'ru'].includes(rawLocale ?? '') ? rawLocale! : 'el'
const t = getTranslations(locale)
// Determine user role server-side
const INTERNAL = process.env.INTERNAL_API_URL || 'http://localhost:4000'
const cookieHeader = cookieStore.getAll().map((c) => `${c.name}=${c.value}`).join('; ')
let userRole: string | null = null
try {
const sessRes = await fetch(`${INTERNAL}/api/auth/get-session`, {
headers: { Cookie: cookieHeader },
})
if (sessRes.ok) {
const sess = await sessRes.json()
userRole = sess?.user?.role ?? null
}
} catch {}
// Admin can override the role for preview purposes via cookie
const previewRole = cookieStore.get('canhelp_preview_role')?.value
const effectiveRole = (userRole === 'admin' && previewRole) ? previewRole : userRole
const isSpecialist = effectiveRole === 'specialist'
let categories: Category[] = []
let locationTree: any[] = []
let platformStats = { specialistCount: 0, taskCount: 0, categoryCount: 0 }
try {
;[categories, locationTree] = await Promise.all([getCategories(), getLocations()])
} catch {}
try {
const statsRes = await fetch(`${INTERNAL}/api/stats`, { next: { revalidate: 600 } })
if (statsRes.ok) platformStats = await statsRes.json()
} catch {}
return (
{/* Hero */}
{isSpecialist ? t('hero.specialist.title') : t('hero.title')}
{isSpecialist ? t('hero.specialist.subtitle') : t('hero.subtitle')}
{isSpecialist ? (
<>
{t('hero.specialist.cta')}
{t('nav.dashboard')}
>
) : (
<>
{t('hero.cta.post')}
{t('hero.cta.specialists')}
>
)}
{/* Stats strip */}
{platformStats.specialistCount > 0 ? platformStats.specialistCount : '—'}
{t('stats.specialists')}
{platformStats.taskCount > 0 ? platformStats.taskCount : '—'}
{t('stats.tasks')}
{platformStats.categoryCount > 0 ? platformStats.categoryCount : '—'}
{t('stats.categories')}
{/* Promo countdown — only for guests */}
{!userRole && (
)}
{/* Categories */}
{isSpecialist ? t('section.categories.specialist') : t('section.categories')}
{/* How it works */}
{t('section.how')}
{([1, 2, 3] as const).map((n) => (
{n}
{isSpecialist ? t(`how.specialist.step${n}.title`) : t(`how.step${n}.title`)}
{isSpecialist ? t(`how.specialist.step${n}.desc`) : t(`how.step${n}.desc`)}
))}
{/* Specialist promo — only shown to customers / guests */}
{!isSpecialist && (
{t('become_specialist.free_badge')}
{t('become_specialist.hero.title')}
{t('become_specialist.hero.subtitle')}
{([1, 2, 3] as const).map((n) => (
{n}
{t(`become_specialist.step${n}.title`)}
{t(`become_specialist.step${n}.desc`)}
))}
{([1, 2, 3, 4] as const).map((n) => (
✓ {t(`become_specialist.benefit${n}`)}
))}
{t('become_specialist.cta')}
)}
{/* Community / Share section */}
{t('section.community')}
{t('community.subtitle')}
🛠️
{t('community.point1.title')}
{t('community.point1.desc')}
🙋
{t('community.point2.title')}
{t('community.point2.desc')}
🌱
{t('community.point3.title')}
{t('community.point3.desc')}
{/* Referral / Partner Program */}
{t('referral.home.badge')}
{t('section.referral')}
{t('referral.home.subtitle')}
{([1, 2, 3] as const).map((n) => (
{n}
{t(`referral.home.step${n}.title`)}
{t(`referral.home.step${n}.desc`)}
))}
{t('referral.home.cta')}
{/* FAQ */}
{t('section.faq')}
({
q: t(`faq.q${n}`),
a: t(`faq.a${n}`),
}))}
/>
{/* Mobile App Download section */}
{/* Two mobile app previews */}
CanHelp
Найдите помощь рядом
Новая заявка
{['Электрик', 'Сантехник', 'Уборка'].map((service) => (
))}
{/* Text + QR codes */}
CanHelp Mobile
{t('app.download_title', 'Скачайте мобильное приложение CanHelp')}
{t('app.download_desc', 'Всегда под рукой. Доступно для Android и iOS.')}
{/* Store buttons */}
{/* QR codes */}
{/* eslint-disable-next-line @next/next/no-img-element */}
App Store · QR
{/* eslint-disable-next-line @next/next/no-img-element */}
Google Play · QR
{/* Cities & Districts cloud */}
{locationTree.length > 0 && (
{isSpecialist ? t('section.cities.specialist') : t('section.cities')}
)}
)
}