♻️ refactor(core): Restructure project for better module separation
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { GlobalMapIcon } from '@repo/ui/lotties';
|
||||
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
|
||||
import GlobalMapLottie from '@workspace/ui/lotties/global-map.json';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
@@ -40,7 +41,7 @@ export function GlobalMap() {
|
||||
delay: 0.4,
|
||||
}}
|
||||
>
|
||||
<GlobalMapIcon className='-mt-[25%] w-full' />
|
||||
<DotLottieReact className='w-full scale-150' data={GlobalMapLottie} autoplay loop />
|
||||
</motion.div>
|
||||
</motion.section>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import useGlobalStore from '@/config/use-global';
|
||||
import { NetworkSecurityIcon } from '@repo/ui/lotties';
|
||||
import { HoverBorderGradient } from '@shadcn/ui/hover-border-gradient';
|
||||
import { TextGenerateEffect } from '@shadcn/ui/text-generate-effect';
|
||||
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
|
||||
import { HoverBorderGradient } from '@workspace/ui/components/hover-border-gradient';
|
||||
import { TextGenerateEffect } from '@workspace/ui/components/text-generate-effect';
|
||||
import NetworkSecurityLottie from '@workspace/ui/lotties/network-security.json';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
@@ -54,7 +55,7 @@ export function Hero() {
|
||||
viewport={{ once: true, amount: 0.3 }}
|
||||
className='flex w-full'
|
||||
>
|
||||
<NetworkSecurityIcon />
|
||||
<DotLottieReact data={NetworkSecurityLottie} autoplay loop />
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
);
|
||||
|
||||
@@ -4,14 +4,15 @@ import { SubscribeDetail } from '@/app/(main)/(user)/subscribe/detail';
|
||||
import { Display } from '@/components/display';
|
||||
import { getSubscription } from '@/services/common/common';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { Button } from '@shadcn/ui/button';
|
||||
import { Card, CardContent, CardFooter, CardHeader } from '@shadcn/ui/card';
|
||||
import { cn } from '@shadcn/ui/lib/utils';
|
||||
import { Separator } from '@shadcn/ui/separator';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Card, CardContent, CardFooter, CardHeader } from '@workspace/ui/components/card';
|
||||
import { Separator } from '@workspace/ui/components/separator';
|
||||
import { cn } from '@workspace/ui/lib/utils';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
import { Key, ReactNode } from 'react';
|
||||
|
||||
export function ProductShowcase() {
|
||||
const t = useTranslations('index');
|
||||
@@ -75,25 +76,35 @@ export function ProductShowcase() {
|
||||
return (
|
||||
<>
|
||||
{description && <li className='text-muted-foreground'>{description}</li>}
|
||||
{features.map((feature, index) => (
|
||||
<li
|
||||
className={cn('flex items-center gap-2', {
|
||||
'text-muted-foreground line-through': feature.type === 'destructive',
|
||||
})}
|
||||
key={index}
|
||||
>
|
||||
{feature.icon && (
|
||||
<Icon
|
||||
icon={feature.icon}
|
||||
className={cn('text-primary size-5', {
|
||||
'text-green-500': feature.type === 'success',
|
||||
'text-destructive': feature.type === 'destructive',
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{feature.label}
|
||||
</li>
|
||||
))}
|
||||
{features.map(
|
||||
(
|
||||
feature: {
|
||||
type: string;
|
||||
icon: string;
|
||||
label: ReactNode;
|
||||
},
|
||||
index: Key,
|
||||
) => (
|
||||
<li
|
||||
className={cn('flex items-center gap-2', {
|
||||
'text-muted-foreground line-through':
|
||||
feature.type === 'destructive',
|
||||
})}
|
||||
key={index}
|
||||
>
|
||||
{feature.icon && (
|
||||
<Icon
|
||||
icon={feature.icon}
|
||||
className={cn('text-primary size-5', {
|
||||
'text-green-500': feature.type === 'success',
|
||||
'text-destructive': feature.type === 'destructive',
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{feature.label}
|
||||
</li>
|
||||
),
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
'use client';
|
||||
|
||||
import { getStat } from '@/services/common/common';
|
||||
import { LocationsIcon, ServersIcon, UsersIcon } from '@repo/ui/lotties';
|
||||
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import LocationsLittie from '@workspace/ui/lotties/locations.json';
|
||||
import ServersLottie from '@workspace/ui/lotties/servers.json';
|
||||
import UsersLottie from '@workspace/ui/lotties/users.json';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useEffect, useState } from 'react';
|
||||
@@ -25,17 +28,17 @@ export function Stats() {
|
||||
{
|
||||
name: t('users'),
|
||||
number: data?.user || 999,
|
||||
icon: <UsersIcon className='size-24' />,
|
||||
icon: <DotLottieReact className='size-24' data={UsersLottie} autoplay loop />,
|
||||
},
|
||||
{
|
||||
name: t('servers'),
|
||||
number: data?.server || 30,
|
||||
icon: <ServersIcon className='size-24' />,
|
||||
icon: <DotLottieReact className='size-24' data={ServersLottie} autoplay loop />,
|
||||
},
|
||||
{
|
||||
name: t('locations'),
|
||||
number: data?.country || 10,
|
||||
icon: <LocationsIcon className='size-24' />,
|
||||
icon: <DotLottieReact className='size-24' data={LocationsLittie} autoplay loop />,
|
||||
},
|
||||
];
|
||||
return (
|
||||
@@ -77,12 +80,12 @@ function CountUp({ end, duration = 2000 }: { end: number; duration?: number }) {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
let startTime;
|
||||
let animationFrame;
|
||||
let startTime: number;
|
||||
let animationFrame: number;
|
||||
|
||||
const easeOutQuad = (t) => t * (2 - t);
|
||||
const easeOutQuad = (t: number) => t * (2 - t);
|
||||
|
||||
const updateCount = (timestamp) => {
|
||||
const updateCount = (timestamp: number) => {
|
||||
if (!startTime) startTime = timestamp;
|
||||
const progress = timestamp - startTime;
|
||||
const easedProgress = easeOutQuad(Math.min(progress / duration, 1));
|
||||
|
||||
Reference in New Issue
Block a user