refactor: consolidate configuration and utility files

- Move menu, footer, and social links to `config.tsx`
- Create `constants.ts` for shared constants like `POSTS_PER_PAGE`
- Extract translation utility to `translator.ts`
- Move table of contents generation to `lib/blog/toc.ts`
- Update import paths across multiple components
- Simplify email configuration using `siteConfig`
This commit is contained in:
javayhu 2025-03-09 23:40:29 +08:00
parent 4f5f216296
commit c7ab08f01d
19 changed files with 38 additions and 47 deletions

View File

@ -1,7 +1,7 @@
import BlogGrid from '@/components/blog/blog-grid';
import EmptyGrid from '@/components/shared/empty-grid';
import CustomPagination from '@/components/shared/pagination';
import { POSTS_PER_PAGE } from '@/lib/constants';
import { POSTS_PER_PAGE } from '@/constants';
import { allPosts, allCategories } from 'content-collections';
import { siteConfig } from '@/config/site';
import { constructMetadata } from '@/lib/metadata';

View File

@ -3,7 +3,7 @@ import { Metadata } from 'next';
import BlogGrid from '@/components/blog/blog-grid';
import EmptyGrid from '@/components/shared/empty-grid';
import CustomPagination from '@/components/shared/pagination';
import { POSTS_PER_PAGE } from '@/lib/constants';
import { POSTS_PER_PAGE } from '@/constants';
import { NextPageProps } from '@/types/next-page-props';
export async function generateMetadata(): Promise<Metadata> {

View File

@ -2,7 +2,7 @@ import AllPostsButton from '@/components/blog/all-posts-button';
import { BlogToc } from '@/components/blog/blog-toc';
import { Mdx } from '@/components/shared/mdx-component';
import { LocaleLink } from '@/i18n/navigation';
import { getTableOfContents } from '@/lib/toc';
import { getTableOfContents } from '@/lib/blog/toc';
import { getBaseUrl } from '@/lib/urls/get-base-url';
import { estimateReadingTime, getLocaleDate } from '@/lib/utils';
import type { NextPageProps } from '@/types/next-page-props';

View File

@ -5,7 +5,7 @@ import { Routes } from '@/routes';
export const metadata = constructMetadata({
title: 'Auth Error',
description: 'Auth Error',
description: 'Auth Error',
canonicalUrl: `${getBaseUrl()}${Routes.AuthError}`,
});

View File

@ -1,5 +1,5 @@
import BlogCard, { BlogCardSkeleton } from '@/components/blog/blog-card';
import { POSTS_PER_PAGE } from '@/lib/constants';
import { POSTS_PER_PAGE } from '@/constants';
import { Post } from 'content-collections';
interface BlogGridProps {

View File

@ -1,7 +1,7 @@
'use client';
import { useMounted } from '@/hooks/use-mounted';
import type { TableOfContents } from '@/lib/toc';
import type { TableOfContents } from '@/lib/blog/toc';
import { cn } from '@/lib/utils';
import * as React from 'react';

View File

@ -20,7 +20,7 @@ export default function Error({ reset }: { reset: () => void }) {
const router = useRouter();
const [isPending, startTransition] = useTransition();
const t = useTranslations('ErrorPage');
return (
<div className="flex min-h-screen flex-col items-center justify-center gap-8">
<Logo className="size-12" />

View File

@ -4,11 +4,7 @@ import Container from '@/components/container';
import { ThemeSwitcherHorizontal } from '@/components/layout/theme-switcher-horizontal';
import { Logo } from '@/components/logo';
import BuiltWithButton from '@/components/shared/built-with-button';
import {
createTranslator,
getFooterLinks,
getSocialLinks,
} from '@/config/config';
import { createTranslator, getFooterLinks, getSocialLinks } from '@/config';
import { siteConfig } from '@/config/site';
import { LocaleLink } from '@/i18n/navigation';
import { cn } from '@/lib/utils';

View File

@ -9,7 +9,8 @@ import {
CollapsibleContent,
CollapsibleTrigger,
} from '@/components/ui/collapsible';
import { createTranslator, getMenuLinks } from '@/config/config';
import { getMenuLinks } from '@/config';
import { createTranslator } from '@/i18n/translator';
import { siteConfig } from '@/config/site';
import { LocaleLink, useLocalePathname } from '@/i18n/navigation';
import { authClient } from '@/lib/auth-client';

View File

@ -17,7 +17,8 @@ import {
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from '@/components/ui/navigation-menu';
import { createTranslator, getMenuLinks } from '@/config/config';
import { getMenuLinks } from '@/config';
import { createTranslator } from '@/i18n/translator';
import { siteConfig } from '@/config/site';
import { useScroll } from '@/hooks/use-scroll';
import { LocaleLink, useLocalePathname } from '@/i18n/navigation';

View File

@ -17,7 +17,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { createTranslator, getAvatarLinks } from '@/config/config';
import { createTranslator, getAvatarLinks } from '@/config';
import { useMediaQuery } from '@/hooks/use-media-query';
import { LocaleLink, useLocaleRouter } from '@/i18n/navigation';
import { authClient } from '@/lib/auth-client';

View File

@ -32,25 +32,7 @@ import {
ThumbsUpIcon,
WandSparklesIcon,
} from 'lucide-react';
type TranslationFunction = (key: string, ...args: any[]) => string;
/**
* Creates a translation function that works with our menu functions
* @param t - The next-intl translation function
* @returns A translation function that accepts string keys
*/
export function createTranslator(t: any): TranslationFunction {
return (key: string) => {
try {
// @ts-ignore - We know this is a valid key because we've defined it in our messages
return t(key);
} catch (error) {
console.error(`Translation key not found: ${key}`);
return key.split('.').pop() || key;
}
};
}
import { TranslationFunction } from './i18n/translator';
/**
* Get menu links with translations

1
src/constants.ts Normal file
View File

@ -0,0 +1 @@
export const POSTS_PER_PAGE = 6;

18
src/i18n/translator.ts Normal file
View File

@ -0,0 +1,18 @@
export type TranslationFunction = (key: string, ...args: any[]) => string;
/**
* Creates a translation function that works with our menu functions
* @param t - The next-intl translation function
* @returns A translation function that accepts string keys
*/
export function createTranslator(t: any): TranslationFunction {
return (key: string) => {
try {
// @ts-ignore - We know this is a valid key because we've defined it in our messages
return t(key);
} catch (error) {
console.error(`Translation key not found: ${key}`);
return key.split('.').pop() || key;
}
};
}

View File

@ -1,3 +0,0 @@
export const POSTS_PER_PAGE = 6;
export const EMAIL_FROM = process.env.EMAIL_FROM;

View File

@ -20,7 +20,7 @@ export function constructMetadata({
} = {}): Metadata {
const fullTitle = title ? `${title} - ${siteConfig.title}` : siteConfig.title;
const ogImageUrl = new URL(`${getBaseUrl()}/${image}`);
return {
title: fullTitle,
description,

View File

@ -11,12 +11,7 @@ type VerifyEmailProps = {
name: string;
} & BaseMailProps;
export function VerifyEmail({
url,
name,
locale,
messages,
}: VerifyEmailProps) {
export function VerifyEmail({ url, name, locale, messages }: VerifyEmailProps) {
const t = createTranslator({
locale,
messages,

View File

@ -1,6 +1,6 @@
import { EMAIL_FROM } from '@/lib/constants';
import { Resend } from 'resend';
import { siteConfig } from '@/config/site';
import { SendEmailHandler } from '@/mail/types';
import { Resend } from 'resend';
export const resend = new Resend(process.env.RESEND_API_KEY);
@ -12,7 +12,7 @@ export const sendEmail: SendEmailHandler = async ({ to, subject, html }) => {
Authorization: `Bearer ${process.env.RESEND_API_KEY}`,
},
body: JSON.stringify({
from: EMAIL_FROM,
from: siteConfig.mail,
to,
subject,
html,