bugfix: site renamed. Name component created.
This commit is contained in:
@@ -10,6 +10,7 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import * as z from 'zod';
|
||||
import { Lock, Mail, User } from 'lucide-react';
|
||||
import { AuthPageShell } from '@/components/ui/auth/AuthPageShell';
|
||||
import { BrandWordmark } from '@/components/ui/shared/BrandWordmark';
|
||||
import { Button } from '@/components/ui/shared/Button';
|
||||
import { Input } from '@/components/ui/shared/Input';
|
||||
import { OrganizationDetailsFields } from '@/components/ui/auth/OrganizationDetailsFields';
|
||||
@@ -179,9 +180,7 @@ function AcceptOrganizationInviteContent() {
|
||||
header={
|
||||
<>
|
||||
<Link href="/" className="flex justify-center">
|
||||
<span className="text-2xl sm:text-3xl font-semibold text-text-primary">
|
||||
{tCommon('appName')}
|
||||
</span>
|
||||
<BrandWordmark className="text-2xl sm:text-3xl font-semibold text-text-primary" />
|
||||
</Link>
|
||||
<h2 className="mt-4 sm:mt-6 text-center text-2xl sm:text-3xl font-semibold text-text-primary">
|
||||
{t('acceptOrganizationTitle')}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { authApi } from '@/lib/api/auth';
|
||||
import { getUserFacingError } from '@/components/shared/formatApiError';
|
||||
import { useAuth } from '@/lib/hooks/useAuth';
|
||||
import { AuthPageShell } from '@/components/ui/auth/AuthPageShell';
|
||||
import { BrandWordmark } from '@/components/ui/shared/BrandWordmark';
|
||||
import { Button } from '@/components/ui/shared/Button';
|
||||
import { Input } from '@/components/ui/shared/Input';
|
||||
|
||||
@@ -28,7 +29,6 @@ function normalizeIranMobile(input: string): string {
|
||||
|
||||
export default function ForgotPasswordPage() {
|
||||
const t = useTranslations('auth');
|
||||
const tCommon = useTranslations('common');
|
||||
const tValidation = useTranslations('validation');
|
||||
const tErrors = useTranslations('errors');
|
||||
const router = useRouter();
|
||||
@@ -128,9 +128,7 @@ export default function ForgotPasswordPage() {
|
||||
header={
|
||||
<>
|
||||
<Link href="/" className="flex justify-center">
|
||||
<span className="text-2xl sm:text-3xl font-semibold text-text-primary">
|
||||
{tCommon('appName')}
|
||||
</span>
|
||||
<BrandWordmark className="text-2xl sm:text-3xl font-semibold text-text-primary" />
|
||||
</Link>
|
||||
<h2 className="mt-4 sm:mt-6 text-center text-2xl sm:text-3xl font-semibold text-text-primary">
|
||||
{t('forgotPasswordTitle')}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { getUserFacingError } from '@/components/shared/formatApiError';
|
||||
import { useAuth } from '@/lib/hooks/useAuth';
|
||||
import { getRememberedEmail } from '@/lib/auth/rememberMe';
|
||||
import { AuthPageShell } from '@/components/ui/auth/AuthPageShell';
|
||||
import { BrandWordmark } from '@/components/ui/shared/BrandWordmark';
|
||||
import { Button } from '@/components/ui/shared/Button';
|
||||
import { Checkbox } from '@/components/ui/shared/Checkbox';
|
||||
import { Input } from '@/components/ui/shared/Input';
|
||||
@@ -91,9 +92,7 @@ function LoginPageContent() {
|
||||
header={
|
||||
<>
|
||||
<Link href="/" className="flex justify-center">
|
||||
<span className="text-2xl sm:text-3xl font-semibold text-text-primary">
|
||||
{tCommon('appName')}
|
||||
</span>
|
||||
<BrandWordmark className="text-2xl sm:text-3xl font-semibold text-text-primary" />
|
||||
</Link>
|
||||
<h2 className="mt-4 sm:mt-6 text-center text-2xl sm:text-3xl font-semibold text-text-primary">
|
||||
{t('signInTitle')}
|
||||
|
||||
@@ -5,20 +5,20 @@ import { Link } from '@/i18n/navigation';
|
||||
import { useAuth } from '@/lib/hooks/useAuth';
|
||||
import { Button } from '@/components/ui/shared/Button';
|
||||
import { TopBarControls } from '@/components/ui/shared/TopBarControls';
|
||||
import { BrandWordmark } from '@/components/ui/shared/BrandWordmark';
|
||||
import { Building2, Beaker, Calendar, Shield, Clock, Users } from 'lucide-react';
|
||||
|
||||
export default function HomePage() {
|
||||
const t = useTranslations('landing');
|
||||
const tAuth = useTranslations('auth');
|
||||
const tCommon = useTranslations('common');
|
||||
const { user, isAuthReady } = useAuth();
|
||||
|
||||
return (
|
||||
<div className="min-h-[100dvh] flex flex-col app-web-bg text-text-primary">
|
||||
<header className="border-b border-border/70 bg-background-secondary/65 backdrop-blur-sm fixed top-0 w-full z-10">
|
||||
<div className="container mx-auto px-4 py-3 sm:py-4 flex flex-wrap items-center justify-between gap-x-4 gap-y-3">
|
||||
<Link href="/" className="text-xl sm:text-2xl font-semibold text-text-primary shrink-0">
|
||||
{tCommon('appName')}
|
||||
<Link href="/" className="shrink-0">
|
||||
<BrandWordmark className="text-xl sm:text-2xl font-semibold text-text-primary" />
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-1.5 sm:gap-3 ml-auto shrink-0">
|
||||
|
||||
@@ -11,6 +11,7 @@ import { getUserFacingError } from '@/components/shared/formatApiError';
|
||||
import { useAuth } from '@/lib/hooks/useAuth';
|
||||
import { useEnterAppWhenAuthenticated } from '@/lib/hooks/useEnterAppWhenAuthenticated';
|
||||
import { AuthPageShell } from '@/components/ui/auth/AuthPageShell';
|
||||
import { BrandWordmark } from '@/components/ui/shared/BrandWordmark';
|
||||
import { OrganizationDetailsFields } from '@/components/ui/auth/OrganizationDetailsFields';
|
||||
import { RegistrationProgressSteps } from '@/components/ui/auth/RegistrationProgressSteps';
|
||||
import { Button } from '@/components/ui/shared/Button';
|
||||
@@ -136,9 +137,7 @@ export default function RegisterPage() {
|
||||
header={
|
||||
<>
|
||||
<Link href="/" className="flex justify-center">
|
||||
<span className="text-2xl sm:text-3xl font-semibold text-text-primary">
|
||||
{tCommon('appName')}
|
||||
</span>
|
||||
<BrandWordmark className="text-2xl sm:text-3xl font-semibold text-text-primary" />
|
||||
</Link>
|
||||
<h2 className="mt-4 sm:mt-6 text-center text-2xl sm:text-3xl font-semibold text-text-primary">
|
||||
{t('registerTitle')}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { routing, isRtlLocale, localeHtmlLang } from '@/i18n/routing';
|
||||
import { LocaleSync } from '@/components/i18n/LocaleSync';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'DyoLink - Dental Clinic & Lab Communication Hub',
|
||||
title: 'Nudentic - Dental Clinic & Lab Communication Hub',
|
||||
description: 'Connect dental clinics and laboratories seamlessly',
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { formatToothList } from '@/components/treatment/prosthesisTypeDisplay';
|
||||
import type { LabCaseDetail } from '@/types/cases';
|
||||
import type { ProsthesisCatalogEntry } from '@/types/treatment-catalog';
|
||||
import type { FdiToothId } from '@/types/treatment';
|
||||
import { BrandWordmark, BRAND_PRIMARY_HEX } from '@/components/ui/shared/BrandWordmark';
|
||||
|
||||
export type CaseSheetLabels = {
|
||||
title: string;
|
||||
@@ -89,7 +90,9 @@ export function CaseSheetPrintLayout({
|
||||
}}
|
||||
>
|
||||
<div style={{ minWidth: 0, flex: 1 }}>
|
||||
<p style={{ ...muted, margin: 0 }}>Dyolink</p>
|
||||
<p style={{ ...muted, margin: 0, textTransform: 'none', letterSpacing: '0.02em' }}>
|
||||
<BrandWordmark dotColor={BRAND_PRIMARY_HEX} />
|
||||
</p>
|
||||
<h1 style={{ margin: '4px 0 0', fontSize: 24, fontWeight: 600 }}>{labels.title}</h1>
|
||||
</div>
|
||||
{labCase.shareUrl ? (
|
||||
|
||||
44
frontend/src/components/ui/shared/BrandWordmark.tsx
Normal file
44
frontend/src/components/ui/shared/BrandWordmark.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import type { CSSProperties } from 'react';
|
||||
|
||||
export const BRAND_NAME = 'Nudentic';
|
||||
|
||||
/** Light-theme primary — use in print/PDF where theme tokens are unsafe. */
|
||||
export const BRAND_PRIMARY_HEX = '#009cae';
|
||||
|
||||
type BrandWordmarkProps = {
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
/**
|
||||
* i-dot color. Omit to use the theme primary token.
|
||||
* Pass a hex (e.g. `BRAND_PRIMARY_HEX`) for print/PDF capture.
|
||||
*/
|
||||
dotColor?: string;
|
||||
};
|
||||
|
||||
function BrandI({ fill }: { fill: string }) {
|
||||
return (
|
||||
<svg
|
||||
aria-hidden
|
||||
viewBox="0 0 24 80"
|
||||
className="inline-block h-[0.78em] w-[0.26em] overflow-visible align-baseline ms-[0.05em] me-[0.04em]"
|
||||
>
|
||||
<circle cx="12" cy="10" r="8" fill={fill} />
|
||||
<rect x="6" y="28" width="12" height="52" rx="1.2" fill="currentColor" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function BrandWordmark({ className, style, dotColor }: BrandWordmarkProps) {
|
||||
const tittleFill = dotColor ?? 'var(--color-primary)';
|
||||
|
||||
return (
|
||||
<span dir="ltr" className={className} style={style}>
|
||||
<span className="sr-only">{BRAND_NAME}</span>
|
||||
<span aria-hidden>
|
||||
Nudent
|
||||
<BrandI fill={tittleFill} />
|
||||
c
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import { usePendingConnectionsCount } from '@/lib/hooks/usePendingConnectionsCou
|
||||
import { useTabBadgeCounts } from '@/lib/hooks/useTabBadgeCounts';
|
||||
import { badgeCountForPath } from '@/lib/tabBadgeUtils';
|
||||
import { NavBadgePill } from '@/components/ui/shared/NavBadgePill';
|
||||
import { BrandWordmark } from '@/components/ui/shared/BrandWordmark';
|
||||
import {
|
||||
canViewAppointmentsTab,
|
||||
canViewCases,
|
||||
@@ -110,7 +111,9 @@ function Sidebar({ mobileOpen = false, onClose }: SidebarProps) {
|
||||
}`}
|
||||
>
|
||||
<div className="h-[71px] px-4 flex items-center justify-between gap-2">
|
||||
<h1 className="text-lg font-medium tracking-tight truncate">{tCommon('appName')}</h1>
|
||||
<h1 className="min-w-0 truncate">
|
||||
<BrandWordmark className="text-lg font-medium tracking-tight" />
|
||||
</h1>
|
||||
{onClose ? (
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user