Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions frontend/components/animate-ui/radix/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function DialogOverlay({className, ...props}: DialogOverlayProps) {
<DialogPrimitive.Overlay
data-slot="dialog-overlay"
className={cn(
'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
'fixed inset-0 z-50 bg-black/16 backdrop-blur-[2px] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 dark:bg-black/55',
className,
)}
{...props}
Expand Down Expand Up @@ -151,7 +151,7 @@ function DialogContent({
}}
transition={{...transition, duration: 0.15, ease: 'easeOut'}}
className={cn(
'fixed left-[50%] top-[50%] z-50 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg rounded-xl',
'fixed left-[50%] top-[50%] z-50 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border border-border/60 bg-background/95 p-6 shadow-[0_24px_60px_rgba(15,23,42,0.12)] ring-1 ring-black/[0.03] dark:border-border/70 dark:bg-background dark:shadow-[0_24px_60px_rgba(0,0,0,0.45)] dark:ring-white/[0.04]',
className,
)}
{...props}
Expand Down
4 changes: 1 addition & 3 deletions frontend/components/common/auth/CallbackHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import {useEffect, useState} from 'react';
import {useRouter, useSearchParams} from 'next/navigation';
import {LiquidButton} from '@/components/animate-ui/buttons/liquid';
import {GalleryVerticalEnd, CheckCircle2, AlertCircle} from 'lucide-react';
import {GalleryVerticalEnd} from 'lucide-react';
import services from '@/lib/services';
import {cn} from '@/lib/utils';

Expand Down Expand Up @@ -97,13 +97,11 @@ export function CallbackHandler({
)}
{status === 'success' && (
<div className="flex flex-col items-center gap-3">
<CheckCircle2 className="h-8 w-8 text-green-500" />
<h2 className="text-lg font-medium text-green-500">验证成功</h2>
</div>
)}
{status === 'error' && (
<div className="flex flex-col items-center gap-4 w-full max-w-sm">
<AlertCircle className="h-8 w-8 text-destructive" />
<div className="text-center space-y-3 w-full">
<h2 className="text-md font-medium text-destructive">验证失败 |{error}</h2>
<LiquidButton
Expand Down
353 changes: 202 additions & 151 deletions frontend/components/common/layout/ManagementBar.tsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function PaymentSettingsDialog({
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent
showCloseButton={false}
className="rounded-[24px] border-none bg-background p-0 shadow-none"
className="rounded-[24px] border border-border/50 bg-background/95 p-0 shadow-[0_24px_60px_rgba(15,23,42,0.10)] ring-1 ring-black/[0.03] dark:bg-background dark:shadow-[0_24px_60px_rgba(0,0,0,0.42)] dark:ring-white/[0.04]"
>
<div className="px-6 pt-4">
<div className="min-w-0">
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/common/project/CreateDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ export function CreateDialog({
</DialogTrigger>
<DialogContent
showCloseButton={false}
className={`${isMobile ? 'max-w-[92vw] max-h-[82vh]' : 'max-w-2xl max-h-[78vh]'} overflow-hidden rounded-[24px] border-none bg-background p-0 shadow-none`}
className={`${isMobile ? 'max-w-[92vw] max-h-[82vh]' : 'max-w-2xl max-h-[78vh]'} overflow-hidden rounded-[24px] border border-border/50 bg-background/95 p-0 shadow-[0_24px_60px_rgba(15,23,42,0.10)] ring-1 ring-black/[0.03] dark:bg-background dark:shadow-[0_24px_60px_rgba(0,0,0,0.42)] dark:ring-white/[0.04]`}
>
<DialogHeader className={`gap-2 px-6 pt-4 ${isMobile ? 'text-left' : ''}`}>
<div className="flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/common/project/EditDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export function EditDialog({
</DialogTrigger>
<DialogContent
showCloseButton={false}
className={`${isMobile ? 'max-w-[92vw] max-h-[82vh]' : 'max-w-2xl max-h-[78vh]'} overflow-hidden rounded-[24px] border-none bg-background p-0 shadow-none`}
className={`${isMobile ? 'max-w-[92vw] max-h-[82vh]' : 'max-w-2xl max-h-[78vh]'} overflow-hidden rounded-[24px] border border-border/50 bg-background/95 p-0 shadow-[0_24px_60px_rgba(15,23,42,0.10)] ring-1 ring-black/[0.03] dark:bg-background dark:shadow-[0_24px_60px_rgba(0,0,0,0.42)] dark:ring-white/[0.04]`}
>
<DialogHeader className={`gap-2 px-6 pt-4 ${isMobile ? 'text-left' : ''}`}>
<div className="flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
Expand Down
70 changes: 47 additions & 23 deletions frontend/components/common/project/ProjectCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,27 @@
import {Button} from '@/components/ui/button';
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from '@/components/ui/tooltip';
import {MotionEffect} from '@/components/animate-ui/effects/motion-effect';
import {CURRENCY_LABEL, DISTRIBUTION_MODE_NAMES, TRUST_LEVEL_CONFIG} from '@/components/common/project';
import {CURRENCY_LABEL, DISTRIBUTION_MODE_NAMES} from '@/components/common/project';
import {BadgeCheck, Boxes, Coins, Gauge, Pencil, ShieldCheck, Trash2, Waypoints} from 'lucide-react';
import {formatDateTimeWithSeconds} from '@/lib/utils';
import {ProjectListItem} from '@/lib/services/project/types';

const TRUST_LEVEL_SHORT_LABELS: Partial<Record<number, string>> = {
1: 'TL1',
2: 'TL2',
3: 'TL3',
4: 'TL4',
};

const trimTrailingZeros = (value: string): string => value.replace(/\.0+$|(\.\d*?[1-9])0+$/, '$1');

const formatCompactPrice = (price: number): {display: string; full: string; compacted: boolean} => {
const full = `${price.toFixed(2)} ${CURRENCY_LABEL}`;
const formatter = new Intl.NumberFormat('en-US', {minimumFractionDigits: 0, maximumFractionDigits: 2});
const numberOnly = trimTrailingZeros(formatter.format(price));
return {display: numberOnly, full, compacted: true};
};

interface ProjectCardProps {
project: ProjectListItem;
onClick?: (project: ProjectListItem) => void;
Expand All @@ -26,7 +42,7 @@ export function ProjectCard({
editButton,
}: ProjectCardProps) {
const priceNum = Number(project.price || '0');
const normalizedPrice = priceNum.toFixed(2);
const priceDisplay = formatCompactPrice(priceNum);

const now = new Date();
const startTime = new Date(project.start_time);
Expand All @@ -43,15 +59,15 @@ export function ProjectCard({

const visibleTags = (project.tags || []).slice(0, 3);
const hiddenTagCount = Math.max(0, (project.tags?.length || 0) - visibleTags.length);
const valueText = `${normalizedPrice} ${CURRENCY_LABEL}`;
const itemText = `${project.total_items}`;
const modeText = DISTRIBUTION_MODE_NAMES[project.distribution_type];
const description = project.description?.trim();
const trustText = TRUST_LEVEL_CONFIG[project.minimum_trust_level]?.name || `T${project.minimum_trust_level}`;
const trustText = TRUST_LEVEL_SHORT_LABELS[project.minimum_trust_level];
const riskText = `${String(project.risk_level).padStart(2, '0')}`;
const showRisk = project.risk_level > 0;
const showPrice = priceNum > 0;
const showIpLimit = !project.allow_same_ip;
const showTrustLevel = Boolean(trustText);

return (
<TooltipProvider>
Expand Down Expand Up @@ -118,9 +134,9 @@ export function ProjectCard({
{description || '暂无描述'}
</p>

<div className="mt-4 space-y-1.5">
<div className="flex items-start justify-between gap-3 sm:gap-4">
<div className="min-w-0 flex flex-wrap items-center gap-x-2 gap-y-1.5 text-[10px] leading-5 text-muted-foreground sm:text-[11px]">
<div className="mt-4 grid grid-cols-[minmax(0,1fr)_auto] items-end gap-x-3 sm:gap-x-4">
<div className="min-w-0 self-end">
<div className="flex max-h-11 flex-wrap items-center gap-x-2 gap-y-1 overflow-hidden text-[10px] leading-5 text-muted-foreground sm:gap-x-3 sm:text-[11px]">
{visibleTags.map((tag) => (
<span
key={tag}
Expand All @@ -134,15 +150,6 @@ export function ProjectCard({
+{hiddenTagCount}
</span>
)}
</div>

<div className="shrink-0 text-[10px] font-medium leading-5 text-foreground/85 sm:text-[11px]">
{modeText}
</div>
</div>

<div className="flex items-center justify-between gap-3 sm:gap-4">
<div className="min-w-0 flex flex-wrap items-center gap-x-2 gap-y-1 text-[10px] leading-5 text-muted-foreground md:flex-nowrap md:gap-x-3 sm:text-[11px]">
<span className="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap">
<Boxes className="h-3.5 w-3.5 text-foreground/50" />
{itemText}
Expand All @@ -154,26 +161,43 @@ export function ProjectCard({
</span>
)}
{showPrice && (
<Tooltip>
<TooltipTrigger asChild>
<span className="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap">
<Coins className="h-3.5 w-3.5 text-foreground/50" />
{priceDisplay.display}
</span>
</TooltipTrigger>
{priceDisplay.compacted && (
<TooltipContent side="top">
<p>{priceDisplay.full}</p>
</TooltipContent>
)}
</Tooltip>
)}
{showTrustLevel && (
<span className="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap">
<Coins className="h-3.5 w-3.5 text-foreground/50" />
{valueText}
<BadgeCheck className="h-3.5 w-3.5 text-foreground/50" />
{trustText}
</span>
)}
<span className="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap">
<BadgeCheck className="h-3.5 w-3.5 text-foreground/50" />
{trustText}
</span>
{showIpLimit && (
<span className="inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap">
<Waypoints className="h-3.5 w-3.5 text-foreground/50" />
限制 IP
</span>
)}
</div>
</div>

<div className="flex min-h-11 shrink-0 flex-col items-end justify-between gap-1 text-right">
<div className="text-[10px] font-medium leading-5 text-foreground/85 sm:text-[11px]">
{modeText}
</div>

<Tooltip>
<TooltipTrigger asChild>
<div className="inline-flex shrink-0 items-center self-center gap-1.5 text-left text-[10px] font-medium text-muted-foreground sm:text-[11px]">
<div className="inline-flex shrink-0 items-center gap-1.5 text-[10px] font-medium text-muted-foreground sm:text-[11px]">
<ShieldCheck className={`h-3.5 w-3.5 ${statusIconClassName}`} />
<span>{statusLabel}</span>
</div>
Expand Down
4 changes: 2 additions & 2 deletions frontend/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function DialogOverlay({
<DialogPrimitive.Overlay
data-slot="dialog-overlay"
className={cn(
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/16 backdrop-blur-[2px] dark:bg-black/55',
className,
)}
{...props}
Expand All @@ -60,7 +60,7 @@ function DialogContent({
<DialogPrimitive.Content
data-slot="dialog-content"
className={cn(
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg',
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border border-border/60 bg-background/95 p-6 shadow-[0_24px_60px_rgba(15,23,42,0.12)] ring-1 ring-black/[0.03] duration-200 sm:max-w-lg dark:border-border/70 dark:bg-background dark:shadow-[0_24px_60px_rgba(0,0,0,0.45)] dark:ring-white/[0.04]',
className,
)}
{...props}
Expand Down
Loading