Explorar el Código

feat: footerbar

BaiLuoYan hace 3 meses
padre
commit
9c1cb02202

+ 110 - 0
src/components/Footerbar/index.tsx

@@ -0,0 +1,110 @@
+import { memo } from 'react';
+
+import { Icon } from '@iconify/react';
+import { useTranslation } from 'react-i18next';
+import { useNavigate } from 'react-router-dom';
+
+import logoIcon from '@/assets/iconify/multi-color/logo.svg';
+import { useResponsive } from '@/hooks/useResponsive';
+
+const Footerbar = memo(() => {
+    const { t } = useTranslation();
+    const { isMobile } = useResponsive();
+    const navigate = useNavigate();
+
+    const handleLinkClick = (path: string) => {
+        navigate(path);
+    };
+
+    return (
+        <footer className={`bg-black border-t border-white/10 ${isMobile ? 'min-h-[168px]' : 'min-h-[189px]'}`}>
+            <div className={`px-[30px] sm:px-6 lg:px-8 max-w-[1440px] mx-auto ${isMobile ? 'pt-12 pb-12' : 'pt-[49px] pb-[48px]'}`}>
+                {isMobile ? (
+                    /* Mobile Layout */
+                    <div className="flex flex-col items-start gap-5">
+                        {/* Logo */}
+                        <div className="flex items-center gap-2">
+                            <Icon icon={logoIcon} className="w-8 h-8" />
+                            <h2 className="text-base font-normal text-white leading-6">
+                                {t('components.footerbar.logo')}
+                            </h2>
+                        </div>
+                        {/* Copyright */}
+                        <p className="text-sm font-normal leading-[1.43em] text-white/40 text-center">
+                            {t('components.footerbar.copyright')}
+                        </p>
+                    </div>
+                ) : (
+                    /* Desktop Layout */
+                    <div className="flex flex-col gap-8 h-[92px]">
+                        {/* Top Section */}
+                        <div className="flex items-center justify-between">
+                            {/* Logo */}
+                            <div className="flex items-center gap-2">
+                                <Icon icon={logoIcon} className="w-8 h-8" />
+                                <h2 className="text-base font-normal text-white leading-6">
+                                    {t('components.footerbar.logo')}
+                                </h2>
+                            </div>
+
+                            {/* Navigation Links */}
+                            <nav className="flex items-center gap-8">
+                                <button
+                                    onClick={() => handleLinkClick('/privacy-policy')}
+                                    className="text-sm font-normal leading-[1.43em] text-white/60 hover:text-white transition-colors border-none bg-transparent whitespace-nowrap"
+                                >
+                                    {t('components.footerbar.privacyPolicy')}
+                                </button>
+                                <button
+                                    onClick={() => handleLinkClick('/terms-of-service')}
+                                    className="text-sm font-normal leading-[1.43em] text-white/60 hover:text-white transition-colors border-none bg-transparent whitespace-nowrap"
+                                >
+                                    {t('components.footerbar.termsOfService')}
+                                </button>
+                                <button
+                                    onClick={() => handleLinkClick('/contact')}
+                                    className="text-sm font-normal leading-[1.43em] text-white/60 hover:text-white transition-colors border-none bg-transparent whitespace-nowrap"
+                                >
+                                    {t('components.footerbar.contact')}
+                                </button>
+                            </nav>
+
+                            {/* Social Media Icons */}
+                            <div className="flex items-center gap-4">
+                                <a
+                                    href="https://twitter.com"
+                                    target="_blank"
+                                    rel="noopener noreferrer"
+                                    className="w-10 h-10 flex items-center justify-center bg-white/5 rounded-full hover:bg-white/10 transition-colors"
+                                    aria-label="Twitter"
+                                >
+                                    <Icon icon="ri:twitter-x-fill" className="w-5 h-5 text-white" />
+                                </a>
+                                <a
+                                    href="https://facebook.com"
+                                    target="_blank"
+                                    rel="noopener noreferrer"
+                                    className="w-10 h-10 flex items-center justify-center bg-white/5 rounded-full hover:bg-white/10 transition-colors"
+                                    aria-label="Facebook"
+                                >
+                                    <Icon icon="ri:facebook-fill" className="w-5 h-5 text-white" />
+                                </a>
+                            </div>
+                        </div>
+
+                        {/* Copyright */}
+                        <div className="flex justify-center">
+                            <p className="text-sm font-normal leading-[1.43em] text-white/40 text-center">
+                                {t('components.footerbar.copyright')}
+                            </p>
+                        </div>
+                    </div>
+                )}
+            </div>
+        </footer>
+    );
+});
+
+Footerbar.displayName = 'Footerbar';
+
+export default Footerbar;

+ 4 - 13
src/components/Topbar/index.tsx

@@ -9,12 +9,10 @@ import menuIcon from '@/assets/iconify/single-color/menu.svg';
 import closeIcon from '@/assets/iconify/single-color/close.svg';
 import chevronDownIcon from '@/assets/iconify/single-color/chevron-down.svg';
 import type { NavMenuItem } from '@/utils/navUtils';
+import { useResponsive } from '@/hooks/useResponsive';
 import { useAction } from './useAction';
-import { useResponsive } from './useResponsive';
 import { useService } from './useService';
 
-const MAX_CONTAINER_WIDTH = 1440;
-
 const Topbar = memo(() => {
     const { t } = useTranslation();
     const { isMobile } = useResponsive();
@@ -46,10 +44,7 @@ const Topbar = memo(() => {
     return (
         <Fragment>
             <header className="fixed top-0 start-0 end-0 z-50 bg-black/90 border-b border-white/10 backdrop-blur-sm">
-                <div
-                    className="h-[81px] px-5 sm:px-6 lg:px-8 flex items-center justify-between"
-                    style={{ maxWidth: MAX_CONTAINER_WIDTH, margin: '0 auto' }}
-                >
+                <div className="h-[81px] px-[30px] sm:px-6 lg:px-8 flex items-center justify-between max-w-[1440px] mx-auto">
                     {/* Logo */}
                     <div className="flex-shrink-0 flex items-center gap-2">
                         <Icon icon={logoIcon} className="w-8 h-8" />
@@ -132,15 +127,11 @@ const Topbar = memo(() => {
                 <>
                     {/* 遮罩层 */}
                     <div
-                        className="fixed inset-0 bg-black/50 z-40"
-                        style={{ top: '81px' }}
+                        className="fixed inset-0 bg-black/50 z-40 top-[81px]"
                         onClick={closeMobileMenu}
                     />
                     {/* 侧边栏菜单 */}
-                    <nav
-                        className="fixed end-0 w-[250px] bg-black/80 backdrop-blur-[4px] z-50"
-                        style={{ top: '81px', bottom: 0 }}
-                    >
+                    <nav className="fixed end-0 top-[81px] bottom-0 w-[250px] bg-black/80 backdrop-blur-[4px] z-50">
                         <div className="h-full px-[30px] pt-[30px] flex flex-col gap-[14px]">
                             {menuItems.map((item: NavMenuItem) => {
                                 const active = isActive(item.path);

+ 1 - 1
src/components/Topbar/useResponsive.ts → src/hooks/useResponsive.ts

@@ -3,7 +3,7 @@ import { useEffect, useState } from 'react';
 const MOBILE_BREAKPOINT = 768;
 
 /**
- * Topbar 响应式检测 Hook
+ * 响应式检测 Hook
  * 检测当前是否为移动端
  */
 export function useResponsive() {

+ 4 - 2
src/layouts/BasicLayout.tsx

@@ -1,14 +1,16 @@
 import { Outlet } from 'react-router-dom';
 
+import Footerbar from '@/components/Footerbar';
 import Topbar from '@/components/Topbar';
 
 const BasicLayout = () => {
     return (
-        <div className="min-h-screen bg-black">
+        <div className="min-h-screen bg-black flex flex-col">
             <Topbar />
-            <main className="pt-[81px]">
+            <main className="pt-[81px] flex-1">
                 <Outlet />
             </main>
+            <Footerbar />
         </div>
     );
 };

+ 7 - 0
src/locales/en-US/components.ts

@@ -2,4 +2,11 @@ export default {
     topbar: {
         logo: 'NOMO',
     },
+    footerbar: {
+        logo: 'NOMO VPN',
+        privacyPolicy: 'Privacy Policy',
+        termsOfService: 'Terms of Service',
+        contact: 'Contact',
+        copyright: '© 2025 NOMO VPN Inc., All rights reserved',
+    },
 };

+ 7 - 0
src/locales/fa-IR/components.ts

@@ -2,4 +2,11 @@ export default {
     topbar: {
         logo: 'NOMO',
     },
+    footerbar: {
+        logo: 'NOMO VPN',
+        privacyPolicy: 'سیاست حریم خصوصی',
+        termsOfService: 'شرایط استفاده',
+        contact: 'تماس با ما',
+        copyright: '© 2025 NOMO VPN Inc., تمامی حقوق محفوظ است',
+    },
 };