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
1 change: 1 addition & 0 deletions app/matching-result/_components/ScreenMatchingResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const ScreenMatchingResult = () => {
return (
<main className="relative flex min-h-screen flex-col items-center px-4 py-2 pb-10">
<BackButton
onClick={() => router.push("/main")}
text={
<div className="flex items-center gap-1.5">
<Image
Expand Down
3 changes: 0 additions & 3 deletions app/matching/_components/ImportantOptionDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ interface ImportantOptionDrawerProps {
const OPTIONS: { label: string; value: ImportantOption }[] = [
{ label: "MBTI", value: "MBTI" },
{ label: "관심사", value: "HOBBY" },
{ label: "나이", value: "AGE" },
{ label: "연락빈도", value: "CONTACT" },
];

Expand Down Expand Up @@ -62,7 +61,6 @@ export default function ImportantOptionDrawer({
selectedOption,
selections = {
MBTI: "",
AGE: "",
HOBBY: "",
CONTACT: "",
},
Expand Down Expand Up @@ -271,7 +269,6 @@ export default function ImportantOptionDrawer({
onPointerDown={handlePointerDown}
onPointerMove={handlePointerMove}
onPointerUp={handlePointerUp}
onClick={onSelect}
/>
))}
</div>
Expand Down
3 changes: 1 addition & 2 deletions app/matching/_components/MatchingOptionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,15 @@
onPointerDown,
onPointerMove,
onPointerUp,
onClick,

Check warning on line 26 in app/matching/_components/MatchingOptionCard.tsx

View workflow job for this annotation

GitHub Actions / lint

'onClick' is defined but never used
}: MatchingOptionCardProps) {
return (
<button
onPointerDown={(e) => onPointerDown?.(e, value)}
onPointerMove={onPointerMove}
onPointerUp={onPointerUp}
onClick={() => onClick?.(value)}
className={cn(
"flex h-[75px] w-full cursor-grab touch-none items-center justify-between gap-1 rounded-lg border px-[17px] transition-all outline-none focus-visible:ring-2 focus-visible:ring-offset-2 active:scale-[0.98] active:cursor-grabbing",
"flex h-[75px] w-full cursor-grab touch-pan-y items-center justify-between gap-1 rounded-lg border px-[17px] transition-all outline-none focus-visible:ring-2 focus-visible:ring-offset-2 active:scale-[0.98] active:cursor-grabbing",
isSelected
? "border-color-main-700 ring-color-main-700 bg-white ring-1"
: "border-color-gray-64 bg-color-gray-50",
Expand Down
3 changes: 1 addition & 2 deletions app/matching/_components/ScreenMatching.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { MatchingInterestCategory } from "@/lib/constants/matchingInterests";
const hobbyMapping: Record<MatchingInterestCategory, HobbyOption> = {
스포츠: "SPORTS",
문화: "CULTURE",
예술: "MUSIC",
음악: "MUSIC",
여행: "TRAVEL",
자기계발: "DAILY",
게임: "GAME",
Expand Down Expand Up @@ -195,7 +195,6 @@ const ScreenMatching = () => {
selectedOption={importantOption}
selections={{
MBTI: selectedMBTI || "",
AGE: selectedAgeGroup || "",
HOBBY: selectedHobbyCategory || "",
CONTACT: selectedFrequency || "",
}}
Expand Down
2 changes: 1 addition & 1 deletion app/mypage/_components/HobbyEditDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ const HobbyEditDrawer = ({
getHobbiesByCategory(cat);
return (
<div key={cat} className="flex flex-col">
{/* 스포츠, 문화예술 등 */}
{/* 스포츠, 문화, 음악 등 */}
<h2 className="typo-16-600 mb-3 text-black">{cat}</h2>
<div className="flex flex-wrap gap-3">
{predefined.map((hobby) => (
Expand Down
2 changes: 1 addition & 1 deletion app/profile-image/_components/TermsDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const TermsDrawer = ({ children }: TermsDrawerProps) => {
const categoryMap: Record<string, string> = {
스포츠: "SPORTS",
문화: "CULTURE",
예술: "MUSIC",
음악: "MUSIC",
여행: "LEISURE",
자기계발: "DAILY",
게임: "GAME",
Expand Down
2 changes: 1 addition & 1 deletion components/common/charge-confirm/ConfirmChargeDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export default function ConfirmChargeDrawer({
const queryClient = useQueryClient();
const drawerContext = React.useContext(ChargeDrawerContext);
const { mutate: purchase, isPending } = usePurchaseProduct();

const [open, setOpen] = React.useState(false);
const [agreed, setAgreed] = React.useState(false);
const [name, setName] = React.useState(depositorName);
Expand Down Expand Up @@ -246,7 +247,6 @@ export default function ConfirmChargeDrawer({

{/* ── 하단 버튼 영역 ── */}
<div className="flex w-full flex-col items-center gap-4">
{/* CTA 버튼 */}
<Button disabled={!agreed || isPending} onClick={handleConfirm}>
{isPending ? "요청 중..." : "충전 요청 보내기"}
</Button>
Expand Down
68 changes: 44 additions & 24 deletions components/common/charge/ChargeInventoryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,66 @@ import {
} from "@/lib/constants/charge";

import { useItems } from "@/hooks/useItems";
import { usePurchaseLimits } from "@/hooks/usePurchaseLimits";

export default function ChargeInventoryCard() {
const { data, isLoading } = useItems();
const { data: itemData } = useItems();
const { data: limitData } = usePurchaseLimits();

const limits = limitData?.data.limits || [];
const matchingLimit = limits.find((l) => l.itemType === "MATCHING_TICKET");
const optionLimit = limits.find((l) => l.itemType === "OPTION_TICKET");

const ticketCounts = {
matching: data?.data.matchingTicketCount ?? 0,
option: data?.data.optionTicketCount ?? 0,
matching: itemData?.data.matchingTicketCount ?? 0,
option: itemData?.data.optionTicketCount ?? 0,
};

return (
<div className="bg-color-gray-50 flex flex-col gap-2 rounded-[16px] p-4">
{/* 보유 수량 */}
<div className="border-color-gray-100 flex flex-col gap-2 border-b pb-3">
{INVENTORY_ROWS.map((row) => (
<div key={row.key} className="flex items-center gap-2">
<Image
src={row.icon}
alt={row.alt}
width={ICON_SIZE.sm}
height={ICON_SIZE.sm}
/>
<div className="flex items-center gap-8">
<span className="typo-10-600 text-color-gray-400">
{row.label}
</span>
<span className="typo-16-700 text-color-text-black">
{ticketCounts[row.key as keyof typeof ticketCounts]}개
</span>
{INVENTORY_ROWS.map((row) => {
const limit = row.key === "matching" ? matchingLimit : optionLimit;
return (
<div key={row.key} className="flex items-center gap-2">
<Image
src={row.icon}
alt={row.alt}
width={ICON_SIZE.sm}
height={ICON_SIZE.sm}
/>
<div className="flex flex-1 items-center justify-between pr-2">
<span className="typo-10-600 text-color-gray-400">
{row.label}
</span>
<div className="flex items-center gap-1">
<span className="typo-16-700 text-color-text-black">
{limit?.ownedQuantity ?? 0}개
</span>
{limit?.pendingQuantity ? (
<span className="typo-10-600 text-color-brand-primary-flame">
(+{limit.pendingQuantity} 대기중)
</span>
) : null}
</div>
</div>
</div>
</div>
))}
);
})}
</div>

{/* 구매 가능 한도 */}
<div className="flex items-center justify-between py-1">
<span className="typo-10-600 text-color-gray-400">구매 가능 한도</span>
<div className="flex items-center gap-6">
{Object.values(PURCHASE_LIMITS).map((limit) => (
<span key={limit.label} className="typo-10-600 text-color-gray-400">
{limit.label} {limit.current}/{limit.max}
<div className="flex items-center gap-4">
{limits.map((limit) => (
<span
key={limit.itemType}
className="typo-10-600 text-color-gray-400"
>
{limit.itemName} {limit.ownedQuantity + limit.pendingQuantity}/
{limit.maxQuantity}
</span>
))}
</div>
Expand Down
17 changes: 14 additions & 3 deletions components/common/charge/DepositorNameContent.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
"use client";

import React from "react";
import React, { useState, useEffect } from "react";
import Image from "next/image";
import { AxiosError } from "axios";
import { cn } from "@/lib/utils";
import { isValidDepositorName } from "@/lib/validators";
import Button from "@/components/ui/Button";
import { useUpdateRealName } from "@/hooks/useUpdateRealName";
import { useRealName } from "@/hooks/useRealName";

export default function DepositorNameContent() {
const [name, setName] = React.useState("");
const [name, setName] = useState("");
const { data: realNameData } = useRealName();
const { mutate: updateName, isPending } = useUpdateRealName();

const isInitialized = React.useRef(false);
useEffect(() => {
if (realNameData?.data?.realName && !isInitialized.current) {
// eslint-disable-next-line react-hooks/set-state-in-effect
setName(realNameData.data.realName);
isInitialized.current = true;
}
}, [realNameData]);

const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
if (isValidDepositorName(value)) {
Expand All @@ -32,7 +43,7 @@ export default function DepositorNameContent() {
};

return (
<div className="flex h-full flex-col gap-[23px] pt-8 pb-[100px]">
<div className="flex flex-col gap-[23px] pt-8 pb-[100px]">
{/* ── 입금자명 입력 ── */}
<div className="flex flex-col gap-2">
<span className="typo-14-500 text-[#666666]">입금자명</span>
Expand Down
44 changes: 44 additions & 0 deletions hooks/usePurchaseLimits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { api } from "@/lib/axios";
import { useQuery } from "@tanstack/react-query";

export type ItemType = "MATCHING_TICKET" | "OPTION_TICKET";

export interface PurchaseLimit {
itemType: ItemType;
itemName: string;
ownedQuantity: number;
pendingQuantity: number;
maxQuantity: number;
remainingQuantity: number;
purchasable: boolean;
}

export interface PurchaseLimitsResponse {
code: string;
status: number;
message: string;
data: {
limits: PurchaseLimit[];
};
}

/**
* 아이템 구매 한도 조회 API 호출 함수
*/
export const getPurchaseLimits = async (): Promise<PurchaseLimitsResponse> => {
const { data } = await api.get<PurchaseLimitsResponse>(
"/api/v1/shop/purchase/limits",
);
return data;
};

/**
* 아이템 구매 한도 조회 훅
*/
export const usePurchaseLimits = () => {
return useQuery({
queryKey: ["purchaseLimits"],
queryFn: getPurchaseLimits,
staleTime: 1000 * 60, // 1분 유지
});
};
31 changes: 31 additions & 0 deletions hooks/useRealName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { api } from "@/lib/axios";
import { useQuery } from "@tanstack/react-query";

interface RealNameResponse {
code: string;
status: number;
message: string;
data: {
realName: string | null;
};
}

/**
* 사용자 실명 조회 API 호출 함수
*/
export const getRealName = async (): Promise<RealNameResponse> => {
const { data } = await api.get<RealNameResponse>("/api/members/real-name");
console.log("📡 [GET] /api/members/real-name 응답 데이터:", data);
Comment thread
dasosann marked this conversation as resolved.
return data;
};

/**
* 사용자 실명 조회 훅
*/
export const useRealName = () => {
return useQuery({
queryKey: ["realName"],
queryFn: getRealName,
staleTime: 1000 * 60 * 5, // 5분
});
};
3 changes: 1 addition & 2 deletions hooks/useUpdateRealName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ export const useUpdateRealName = () => {
mutationFn: (realName: string) => postRealName(realName),
onSuccess: (data) => {
console.log("✅ 실명 수정 성공:", data);
// 실명이 바뀌었으므로 관련 쿼리 무효화 (필요시)
// queryClient.invalidateQueries({ queryKey: ["userProfile"] });
queryClient.invalidateQueries({ queryKey: ["realName"] });
},
onError: (error: AxiosError<{ message: string }>) => {
const errorData = error.response?.data;
Expand Down
2 changes: 1 addition & 1 deletion lib/constants/hobbies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const HOBBIES = {
"📱 웹툰",
"💃 댄스",
],
예술: [
음악: [
"🎤 K-POP",
"🎶 팝",
"🧢 힙합",
Expand Down
4 changes: 2 additions & 2 deletions lib/constants/matchingInterests.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const MATCHING_INTEREST_CATEGORIES = [
"스포츠",
"문화",
"예술",
"음악",
"여행",
"자기계발",
"게임",
Expand All @@ -18,7 +18,7 @@ export interface MatchingInterestItem {
export const MATCHING_INTEREST_ITEMS: MatchingInterestItem[] = [
{ category: "스포츠", imageSrc: "/interest/스포츠.png" },
{ category: "문화", imageSrc: "/interest/문화.png" },
{ category: "예술", imageSrc: "/interest/예술.png" },
{ category: "음악", imageSrc: "/interest/예술.png" },
{ category: "여행", imageSrc: "/interest/여행.png" },
{ category: "자기계발", imageSrc: "/interest/자기계발.png" },
{ category: "게임", imageSrc: "/interest/게임.png" },
Expand Down
2 changes: 1 addition & 1 deletion lib/types/matching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type HobbyOption =
| "DAILY"
| "GAME";

export type ImportantOption = "AGE" | "MBTI" | "HOBBY" | "CONTACT";
export type ImportantOption = "MBTI" | "HOBBY" | "CONTACT";

export interface MatchingRequest {
ageOption?: AgeOption | null;
Expand Down
Loading