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
43 changes: 24 additions & 19 deletions app/routes/business/components/CampaignBrandCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import chatIcon from "../../../assets/chat-icon.svg";
import arrowRightIcon from "../../../assets/icon/arrow-right.svg";

interface CampaignBrandCardProps {
showChatSection?: boolean;
statusText?: string;
brandName?: string;
brandTags?: string[];
brandImageUrl?: string;
showChatSection?: boolean;
statusText?: string;
brandName?: string;
brandTags?: string[];
brandImageUrl?: string;
matchingRate?: number;
brandId?: number | string;
category?: string;
}

export default function CampaignBrandCard({
showChatSection,
export default function CampaignBrandCard({
showChatSection,
statusText,
brandName,
brandTags,
Expand All @@ -23,9 +23,9 @@ export default function CampaignBrandCard({
brandId,
category
}: CampaignBrandCardProps) {
const navigate = useNavigate();
const navigate = useNavigate();
const handleBrandClick = (e: React.MouseEvent) => {
e.stopPropagation();
e.stopPropagation();
if (brandId && category) {
navigate(`/brand?brandId=${brandId}&domain=${category}`);
} else {
Expand All @@ -41,13 +41,12 @@ export default function CampaignBrandCard({
<div className="w-[64px] h-[64px] flex items-center justify-center overflow-hidden border border-text-gray5 rounded-lg">
<img src={brandImageUrl} alt={brandName} className="w-full h-full object-cover" />
</div>

<div className="flex flex-col justify-center gap-1">
<div className="flex items-center gap-1">
<h2 className="text-title1 text-text-black leading-tight">
{brandName || "브랜드명"}
{brandName || "리얼매치"}
</h2>
<button
<button
type="button"
onClick={handleBrandClick}
className="flex items-center justify-center active:scale-90 transition-transform p-1"
Expand All @@ -57,18 +56,24 @@ export default function CampaignBrandCard({
</button>
</div>
<p className="text-callout1 text-text-gray3 mt-1">
{brandTags && brandTags.length > 0
? brandTags.map(tag => `#${tag}`).join(" ")
: "#태그정보없음"}
{brandTags && brandTags.length > 0
? brandTags.map(tag => `#${tag}`).join(" ")
: "#정밀매칭 #원스톱협업 #쌍방향제안"}
</p>
</div>
</div>

<div className="flex flex-col items-end justify-center h-[64px]">
<div className="flex items-baseline gap-1">
<span className="text-title5 text-core-1">매칭률</span>
<span className="text-title6 text-core-1">{matchingRate || 0}%</span>
</div>
{matchingRate === 0 ? (
<div className="flex items-baseline gap-1">
<span className="text-title6 text-core-1">광고</span>
</div>
) : (
<div className="flex items-baseline gap-1">
<span className="text-title5 text-core-1">매칭률</span>
<span className="text-title6 text-core-1">{matchingRate || 0}%</span>
</div>
)}
<span className="text-callout1 text-core-1 mt-3">{statusText}</span>
</div>
</div>
Expand Down
14 changes: 12 additions & 2 deletions app/routes/business/proposal/sent-proposal-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import arrowRightIcon from "../../../assets/icon/arrow-right.svg";
import arrowPurpleIcon from "../../../assets/arrow-purple.svg";
import profileIcon from "../../../assets/icon-profile.svg";
import ConfirmModal from "../../../components/common/ConfirmModal";
import adRealmatchLogo from "../../../assets/ad/ad-realmatch-logo.png";

export default function ProposalContent() {
const [searchParams] = useSearchParams();
Expand Down Expand Up @@ -54,7 +55,16 @@ export default function ProposalContent() {
const proposalResult = await getProposalDetail(proposalId);
setData(proposalResult);

if (proposalResult.brandId) {
if (proposalResult.brandId === 0) {
// brandId가 0이면 리얼매치 광고로 하드코딩
setBrand({
brandId: 0,
brandName: "리얼매치",
brandTags: ["정밀매칭", "원스톱협업", "쌍방향제안"],
brandImageUrl: adRealmatchLogo,
matchingRate: 0
});
} else if (proposalResult.brandId) {
const brandResult = await getBrandSummary(proposalResult.brandId);
setBrand(brandResult);
}
Expand Down Expand Up @@ -184,7 +194,7 @@ export default function ProposalContent() {
<div className="grid grid-cols-2 gap-4">
<CampaignInfoGroup label="협찬품">
<div className="w-full p-4 bg-bg-w border border-text-gray5 rounded-xl text-body1 flex justify-between items-center text-text-gray1">
<span className="truncate">{data.productId}</span>
<span className="truncate">{data.productId !== 0 ? data.productId : ""}</span>
<img src={arrowRightIcon} alt="arrow" className="w-4 h-4 opacity-30" />
</div>
</CampaignInfoGroup>
Expand Down
8 changes: 8 additions & 0 deletions app/routes/home/components/BannerCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ const fashionBanners: BannerItem[] = [

export default function BannerCarousel({
category,
loading,
}: {
category: CategoryKey;
loading?: boolean;
}) {
const banners = category === "beauty" ? beautyBanners : fashionBanners;
const displayBanners = [banners[banners.length - 1], ...banners, banners[0]];
Expand Down Expand Up @@ -79,6 +81,12 @@ export default function BannerCarousel({
}
}, [isSilentJumping]);

if (loading) {
return (
<div className="-mx-5 h-62.5 animate-pulse bg-gray-100" />
);
}

const handleStart = (clientX: number) => {
stop();
setIsDragging(true);
Expand Down
150 changes: 75 additions & 75 deletions app/routes/home/home-after-match.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ export default function HomeAfterMatchPage() {
return (
<div className="min-h-screen bg-white">
<div className="bg-white px-5 pt-0 pb-[calc(116px+env(safe-area-inset-bottom))]">
<BannerCarousel key={category} category={category} />
<BannerCarousel key={category} category={category} loading={homeCoreLoading} />

<CategoryTabs value={category} onChange={setCategory} />

Expand Down Expand Up @@ -561,46 +561,46 @@ export default function HomeAfterMatchPage() {
<div className="-mr-5 mt-3 flex gap-3 overflow-x-auto pb-2 pr-5">
{homeCoreLoading
? Array.from({ length: 4 }).map((_, i) => (
<div key={`camp-sk-${i}`} className="w-29.5 shrink-0">
<div className="relative aspect-square animate-pulse rounded-xl border border-core-2 bg-gray-200" />
<div className="mt-2 space-y-1.5">
<div className="flex items-baseline justify-between">
<div className="h-4 w-12 animate-pulse rounded bg-gray-200" />
<div className="h-4 w-8 animate-pulse rounded bg-gray-200" />
</div>
<div className="h-3 w-20 animate-pulse rounded bg-gray-200" />
<div className="h-3 w-16 animate-pulse rounded bg-gray-200" />
<div key={`camp-sk-${i}`} className="w-29.5 shrink-0">
<div className="relative aspect-square animate-pulse rounded-xl border border-core-2 bg-gray-200" />
<div className="mt-2 space-y-1.5">
<div className="flex items-baseline justify-between">
<div className="h-4 w-12 animate-pulse rounded bg-gray-200" />
<div className="h-4 w-8 animate-pulse rounded bg-gray-200" />
</div>
<div className="h-3 w-20 animate-pulse rounded bg-gray-200" />
<div className="h-3 w-16 animate-pulse rounded bg-gray-200" />
</div>
))
</div>
))
: campaigns.map((campaign, i) => {
const safeCampaignId = getCampaignId(campaign);
if (!safeCampaignId) return null;

return (
<CampaignCard
key={`match-${safeCampaignId}-${i}`}
item={{
id: String(safeCampaignId),
brandName: campaign.brandName,
matchRate: campaign.matchRate || 0,
descText: campaign.name || campaign.title || "",
rewardText: `원고료 ${campaign.reward?.toLocaleString()}원`,
ddayLabel:
campaign.dDay === 0
? "D-DAY"
: campaign.dDay
? `D-${campaign.dDay}`
: "",
progressText: String(campaign.applicants),
isLiked: campaign.isLiked,
logoUrl: campaign.logoUrl,
}}
onClick={() => goCampaignDetail(campaign)}
onLikeToggle={handleCampaignLikeToggle}
/>
);
})}
const safeCampaignId = getCampaignId(campaign);
if (!safeCampaignId) return null;

return (
<CampaignCard
key={`match-${safeCampaignId}-${i}`}
item={{
id: String(safeCampaignId),
brandName: campaign.brandName,
matchRate: campaign.matchRate || 0,
descText: campaign.name || campaign.title || "",
rewardText: `원고료 ${campaign.reward?.toLocaleString()}원`,
ddayLabel:
campaign.dDay === 0
? "D-DAY"
: campaign.dDay
? `D-${campaign.dDay}`
: "",
progressText: String(campaign.applicants),
isLiked: campaign.isLiked,
logoUrl: campaign.logoUrl,
}}
onClick={() => goCampaignDetail(campaign)}
onLikeToggle={handleCampaignLikeToggle}
/>
);
})}
</div>
</section>
{profileModel && (
Expand All @@ -623,46 +623,46 @@ export default function HomeAfterMatchPage() {
<div className="-mr-5 mt-3 flex gap-0.5 overflow-x-auto pb-2 pr-5">
{homeCoreLoading
? Array.from({ length: 4 }).map((_, i) => (
<div key={`pop-sk-${i}`} className="w-29.5 shrink-0">
<div className="relative aspect-square animate-pulse rounded-xl border border-core-2 bg-gray-200" />
<div className="mt-2 space-y-1.5">
<div className="flex items-baseline justify-between">
<div className="h-4 w-12 animate-pulse rounded bg-gray-200" />
<div className="h-4 w-8 animate-pulse rounded bg-gray-200" />
</div>
<div className="h-3 w-20 animate-pulse rounded bg-gray-200" />
<div className="h-3 w-16 animate-pulse rounded bg-gray-200" />
<div key={`pop-sk-${i}`} className="w-29.5 shrink-0">
<div className="relative aspect-square animate-pulse rounded-xl border border-core-2 bg-gray-200" />
<div className="mt-2 space-y-1.5">
<div className="flex items-baseline justify-between">
<div className="h-4 w-12 animate-pulse rounded bg-gray-200" />
<div className="h-4 w-8 animate-pulse rounded bg-gray-200" />
</div>
<div className="h-3 w-20 animate-pulse rounded bg-gray-200" />
<div className="h-3 w-16 animate-pulse rounded bg-gray-200" />
</div>
))
</div>
))
: popularCampaigns.map((campaign, i) => {
const safeCampaignId = getCampaignId(campaign);
if (!safeCampaignId) return null;

return (
<CampaignCard
key={`popular-${safeCampaignId}-${i}`}
item={{
id: String(safeCampaignId),
brandName: campaign.brandName,
matchRate: 0,
descText: campaign.name || campaign.title || "",
rewardText: `원고료 ${campaign.reward?.toLocaleString()}원`,
ddayLabel:
campaign.dDay === 0
? "D-DAY"
: campaign.dDay
? `D-${campaign.dDay}`
: "",
progressText: String(campaign.applicants),
isLiked: campaign.isLiked,
logoUrl: campaign.logoUrl,
}}
onClick={() => goCampaignDetail(campaign)}
onLikeToggle={handleCampaignLikeToggle}
/>
);
})}
const safeCampaignId = getCampaignId(campaign);
if (!safeCampaignId) return null;

return (
<CampaignCard
key={`popular-${safeCampaignId}-${i}`}
item={{
id: String(safeCampaignId),
brandName: campaign.brandName,
matchRate: 0,
descText: campaign.name || campaign.title || "",
rewardText: `원고료 ${campaign.reward?.toLocaleString()}원`,
ddayLabel:
campaign.dDay === 0
? "D-DAY"
: campaign.dDay
? `D-${campaign.dDay}`
: "",
progressText: String(campaign.applicants),
isLiked: campaign.isLiked,
logoUrl: campaign.logoUrl,
}}
onClick={() => goCampaignDetail(campaign)}
onLikeToggle={handleCampaignLikeToggle}
/>
);
})}
</div>
</section>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ function SelectBottomSheetInner({
<label
key={option.value}
className="flex items-center gap-2.5 cursor-pointer"
onClick={() => handleToggle(option.value)}
>
<div onClick={() => handleToggle(option.value)}>
<div>
<CheckIcon checked={selected.includes(option.value)} />
</div>
<span className="text-title3 text-text-gray1">{option.label}</span>
Expand All @@ -85,8 +86,8 @@ function SelectBottomSheetInner({
{/* 그 외 입력 */}
{hasCustomInput && (
<div>
<label className="flex items-center gap-2.5 cursor-pointer">
<div onClick={() => handleToggle("custom")}>
<label className="flex items-center gap-2.5 cursor-pointer" onClick={() => handleToggle("custom")}>
<div>
<CheckIcon checked={selected.includes("custom")} />
</div>
<span className="text-title3 text-text-gray1">그 외 입력</span>
Expand Down