fix(reputation): skeleton loading + no empty-card flash
The marketplace Reputation tab showed a bare 'Loading...' text under 'Reviews & trade records', and TradeRecommendationsCard rendered its 'No recommendations yet.' card while still loading (then it vanished for a self/empty view) — together they read as broken. - Reviews/trade-records now render row-shaped skeletons while loading. - TradeRecommendationsCard renders nothing while its query is loading when the count is 0 (and only shows for a non-self viewer who can add one).
This commit is contained in:
parent
52eff36bce
commit
86c9f6f856
2 changed files with 24 additions and 3 deletions
|
|
@ -48,8 +48,10 @@ export function TradeRecommendationsCard({ pubkey, className }: { pubkey: string
|
||||||
const isSelf = user?.pubkey === pubkey;
|
const isSelf = user?.pubkey === pubkey;
|
||||||
const count = recs?.length ?? 0;
|
const count = recs?.length ?? 0;
|
||||||
|
|
||||||
// Nothing to show: no recommendations and the viewer can't add one.
|
// Don't flash an empty "No recommendations yet." card while the query is still
|
||||||
if (!isLoading && count === 0 && (!user || isSelf)) return null;
|
// loading (it then vanishes for a self/empty view) — render nothing until we
|
||||||
|
// know, and only show the card when there's something (or the viewer can add).
|
||||||
|
if (count === 0 && (isLoading || !user || isSelf)) return null;
|
||||||
|
|
||||||
const handleRecommend = async () => {
|
const handleRecommend = async () => {
|
||||||
setBusy(true);
|
setBusy(true);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { Link } from 'react-router-dom';
|
||||||
import type { NostrEvent } from '@nostrify/nostrify';
|
import type { NostrEvent } from '@nostrify/nostrify';
|
||||||
import { Star, ThumbsUp, ArrowUpRight } from 'lucide-react';
|
import { Star, ThumbsUp, ArrowUpRight } from 'lucide-react';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||||
import { TradeReputationCard } from '@/components/TradeReputationCard';
|
import { TradeReputationCard } from '@/components/TradeReputationCard';
|
||||||
import { TradeRecommendationsCard } from '@/components/TradeRecommendationsCard';
|
import { TradeRecommendationsCard } from '@/components/TradeRecommendationsCard';
|
||||||
|
|
@ -72,6 +73,20 @@ function ReviewRow({ ev, selfPubkey }: { ev: NostrEvent; selfPubkey: string }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Loading placeholder shaped like a review row. */
|
||||||
|
function ReviewSkeleton() {
|
||||||
|
return (
|
||||||
|
<div className="flex items-start gap-3 rounded-xl border border-white/8 bg-white/[0.03] p-3">
|
||||||
|
<Skeleton className="h-9 w-9 shrink-0 rounded-full" />
|
||||||
|
<div className="min-w-0 flex-1 space-y-2">
|
||||||
|
<Skeleton className="h-3.5 w-40" />
|
||||||
|
<Skeleton className="h-3 w-full" />
|
||||||
|
<Skeleton className="h-3 w-24" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marketplace → Reputation tab: this trader's reputation, peer recommendations,
|
* Marketplace → Reputation tab: this trader's reputation, peer recommendations,
|
||||||
* and their trade records / reviews (from kind-31871 attestations).
|
* and their trade records / reviews (from kind-31871 attestations).
|
||||||
|
|
@ -112,7 +127,11 @@ export function TradeReputationPanel({ pubkey }: { pubkey: string }) {
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<p className="text-sm text-gray-500">{t('common.loading')}</p>
|
<div className="space-y-2">
|
||||||
|
<ReviewSkeleton />
|
||||||
|
<ReviewSkeleton />
|
||||||
|
<ReviewSkeleton />
|
||||||
|
</div>
|
||||||
) : attestations.length === 0 ? (
|
) : attestations.length === 0 ? (
|
||||||
<Card className="border-dashed border-white/10">
|
<Card className="border-dashed border-white/10">
|
||||||
<CardContent className="py-10 text-center">
|
<CardContent className="py-10 text-center">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue