Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
9e52d6f
style: 워크스페이스 디자인 변경 (grid-cols-2로 수정 및 전체적인 디자인 디테일 깔끌하게 수정)
jjjsun Aug 6, 2026
47a5b5e
style: 워크스페이스 목록 디자인 디테일 수정
jjjsun Aug 6, 2026
c0a57dd
style: 빈상태를 전체 그리드 폭으로 랜더링
jjjsun Aug 6, 2026
10b1943
refactor: 플랫폼 sync mutation을 usePlatformSyncMutations 훅으로 분리
YermIm Aug 6, 2026
6b3207c
feat: Google OAuth 연동 성공 후 초기 데이터 동기화
YermIm Aug 6, 2026
fb0023d
Merge pull request #407 from WhereYouAd/design/#402
jjjsun Aug 6, 2026
9ef914b
feat: Naver 최초 연동 성공 후 sync 모달 자동 오픈
YermIm Aug 6, 2026
f051f5c
fix: Google OAuth 초기 sync 중 카드 로딩 표시
YermIm Aug 6, 2026
e4c35ba
Merge pull request #408 from WhereYouAd/feature/#404
YermIm Aug 6, 2026
7130514
feat: 타임라인 sort/filter 타입 정의
jjjsun Aug 6, 2026
1c3336b
feat: list키에 sort/status 반영
jjjsun Aug 6, 2026
8c66269
feat: 타임라인조회 API훅에 params추가
jjjsun Aug 6, 2026
f373264
feat: useTimelineList훅 params받아서 쿼리
jjjsun Aug 6, 2026
4dca963
feat: 필터/정렬 라벨링
jjjsun Aug 6, 2026
eadc24d
feat: 사이드바 모바일 off-canvas 상태 추가
YermIm Aug 6, 2026
ccbf747
feat: 타임라인 정렬/필터 컴포넌트 구현
jjjsun Aug 6, 2026
43ae445
feat: mock데이터 수정
jjjsun Aug 6, 2026
5970450
feat: 햄버거 메뉴 및 off-canvas 사이드바
YermIm Aug 6, 2026
c4c8315
feat: tablet Sidebar drawer UX 개선 및 submenu 잔류 버그 수정
YermIm Aug 6, 2026
f4d44a4
feat: 타임라인페이지에 구현된 컴포넌트 삽입
jjjsun Aug 6, 2026
08eba53
fix: 타임라인 정렬 라벨을 실제 정렬순서에 맞게 수정
jjjsun Aug 6, 2026
b173bb0
fix: 상대 경로 별칭 import로 수정
jjjsun Aug 6, 2026
3d16801
fix: 타임라인 바 정렬/필터 값 페이지 unmount후에도 남아이도록 Zustand로 이동
jjjsun Aug 6, 2026
70524a6
feat: 모바일에서 플랫폼 전환 버튼을 페이지 상단으로 이동
YermIm Aug 6, 2026
6d4f322
style: 플랫폼뷰 KPI 모바일 1열 적용
YermIm Aug 6, 2026
bc2325a
style: 모바일 플랫폼 선택 버튼 텍스트 가운데 정렬
YermIm Aug 6, 2026
f0ea819
style: 플랫폼뷰 KPI 통합에 맞춤
YermIm Aug 6, 2026
749f3d9
style: 성과 우수 플랫폼 모바일에서 로고만 표시
YermIm Aug 6, 2026
9cae937
style: 성과 효율 차트 모바일 Y축 숨김 및 라벨 여백 조정
YermIm Aug 6, 2026
c09dcee
style: 플랫폼 상세 카드 KPI heading3로 축소
YermIm Aug 6, 2026
9b8d68b
style: 예산 게이지 남은 % 축소
YermIm Aug 6, 2026
ba2db36
fix: 플랫폼 상세 카드 KPI를 heading2로 조정
YermIm Aug 6, 2026
e115f02
style: 캠페인 목록 모바일·태블릿 레이아웃 및 타이포 조정
YermIm Aug 6, 2026
5d72d3b
style: 캠페인 상세 모바일·태블릿 레이아웃 조정
YermIm Aug 6, 2026
0243704
style: 통합 캠페인 등록 태블릿/모바일 카드 패딩 정리
YermIm Aug 6, 2026
bef528a
style: 통합 캠페인 등록 모바일 설명 문구 축소
YermIm Aug 6, 2026
064fa89
style: 플랫폼 연동 카드 모바일 패딩 축소
YermIm Aug 6, 2026
4d4a98f
style: 플랫폼 연동 모바일 안내 문구·간격 조정
YermIm Aug 6, 2026
2bbd087
style: 광고 상세 모바일 패딩 축소
YermIm Aug 6, 2026
67e8e31
fix: 공통 모달 닫기 버튼·화면 좌우 여백 확보
YermIm Aug 6, 2026
675b786
ci: retrigger CI
YermIm Aug 6, 2026
e8763c8
Merge pull request #409 from WhereYouAd/feature/#401
jjjsun Aug 6, 2026
88cc6ef
fix: 타임라인 보기 단위 월 선택시 월초로 가도록 수정
jjjsun Aug 6, 2026
0b76a0b
Merge pull request #411 from WhereYouAd/bugfix/#410
jjjsun Aug 7, 2026
913d77f
fix: 캠페인 목록 모바일 플랫폼 열 폭 정렬
YermIm Aug 7, 2026
6365cbb
feat: 드랍다운 오픈시 높이 확장
jjjsun Aug 7, 2026
9511bd3
fix: 플랫폼 전환 버튼 높이 수정
YermIm Aug 7, 2026
f776f1f
feat: 타임라인 생성 모달 성과기간선택 드랍다운 높이 확장 적용
jjjsun Aug 7, 2026
5b87551
style: 타임라인 생성 모달 성과지표 칩 움직임 추가
jjjsun Aug 7, 2026
7657662
style: 그리드 세로 갭 축소
jjjsun Aug 7, 2026
131e7cb
fix: 플랫폼 전체보기 KPI 카드 숫자 오버플로우 처리
YermIm Aug 7, 2026
55dc49b
style: 광고 모아보기 모바일 패딩 수정
YermIm Aug 7, 2026
66c2431
Merge pull request #412 from WhereYouAd/feature/#405
YermIm Aug 7, 2026
d6daf06
feat: 타임라인 성과패널 열었을때 읿별 변화추이 차트 캠페인 시작날짜부터 보이도록 수정
jjjsun Aug 7, 2026
7b95f58
style: 성과 지표 칩 컬러 변경
jjjsun Aug 7, 2026
c2eb353
style: AI 지표 타이틀 추가
jjjsun Aug 7, 2026
7ac103b
style: KPI카드 스타일 변경
jjjsun Aug 7, 2026
e91d5a5
style: KPI지표카드 gap 추가
jjjsun Aug 7, 2026
4df5821
style: AI요약 타이틀 위치수정 및 컬러 수정
jjjsun Aug 7, 2026
84b5aff
fix: inFlow에서도 fullWidth 높이 제한 해제
jjjsun Aug 7, 2026
508c737
chore: AI 요약 버튼 문구 수정
jjjsun Aug 7, 2026
0096aa4
style: KPI 카드 grid로 변경
jjjsun Aug 7, 2026
eb10341
Merge pull request #414 from WhereYouAd/feature/#413
jjjsun Aug 7, 2026
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
9 changes: 8 additions & 1 deletion src/api/timeline/timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ICommonResponse } from "@/types/common/common";
import {
type ITimelineDetail,
type ITimelineListItem,
type ITimelineListParams,
type ITimelineMutationResponse,
type ITimelineUpsertRequest,
type TTimelineEmptyResponse,
Expand All @@ -23,10 +24,16 @@ export const getTimelineDetail = async (
//타임라인 목록 조회 API
export const getTimelineList = async (
orgId: number,
params: ITimelineListParams = {},
): Promise<ITimelineListItem[]> => {
const { data } = await axiosInstance.get<
ICommonResponse<ITimelineListItem[]>
>(`/api/org/${orgId}/timeline`);
>(`/api/org/${orgId}/timeline`, {
params: {
...(params.status ? { status: params.status } : {}),
...(params.sort ? { sort: params.sort } : {}),
},
});
return data.data;
};

Expand Down
3 changes: 3 additions & 0 deletions src/assets/icon/sidebar/menu.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions src/components/ads/AdDetailContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ export default function AdDetailContent({ ad }: { ad: IAd }) {
return (
<div className="animate-fade-in">
<div className="border-t border-surface-400/60">
<div className="flex flex-col gap-4 px-4 pb-2 pt-4 tablet:px-5">
<section className="rounded-lg border border-surface-400/40 bg-surface-100 px-4 py-3">
<div className="flex flex-col gap-4 px-4 pb-2 pt-4 tablet:px-5 mobile:gap-3 mobile:px-4 mobile:pt-3">
<section className="rounded-lg border border-surface-400/40 bg-surface-100 px-4 py-3 mobile:px-3 mobile:py-2.5">
<h3 className="mb-2 font-caption text-text-placeholder">
광고 소재
</h3>
Expand All @@ -70,7 +70,7 @@ export default function AdDetailContent({ ad }: { ad: IAd }) {
</p>
</section>

<section className="rounded-lg border border-surface-400/40 bg-surface-100 px-4 py-3">
<section className="rounded-lg border border-surface-400/40 bg-surface-100 px-4 py-3 mobile:px-3 mobile:py-2.5">
<h3 className="mb-2 font-caption text-text-placeholder">타겟</h3>
<div className="flex flex-wrap gap-2">
{tags.length > 0 ? (
Expand All @@ -91,7 +91,7 @@ export default function AdDetailContent({ ad }: { ad: IAd }) {
</div>
</section>

<section className="rounded-lg border border-surface-400/40 bg-surface-100 px-4 py-3">
<section className="rounded-lg border border-surface-400/40 bg-surface-100 px-4 py-3 mobile:px-3 mobile:py-2.5">
<h3 className="mb-2 font-caption text-text-placeholder">
랜딩 URL
</h3>
Expand All @@ -116,8 +116,8 @@ export default function AdDetailContent({ ad }: { ad: IAd }) {
</section>
</div>

<div className="mx-4 mb-4 mt-1 overflow-hidden rounded-lg border border-surface-400/40 bg-surface-100 tablet:mx-5">
<div className="flex flex-wrap items-start justify-between gap-3 gap-y-3 px-4 py-4">
<div className="mx-4 mb-4 mt-1 overflow-hidden rounded-lg border border-surface-400/40 bg-surface-100 tablet:mx-5 mobile:mx-4 mobile:mb-3">
<div className="flex flex-wrap items-start justify-between gap-3 gap-y-3 px-4 py-4 mobile:px-3 mobile:py-3">
<div className="min-w-0 flex-1">
<p className="font-caption text-text-placeholder">트래킹</p>
<p className="mt-1 font-body1 text-text-title">
Expand Down
21 changes: 12 additions & 9 deletions src/components/ads/AdRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ import NaverLogo from "@/assets/logo/social-logo/circle/naver-circle.svg?react";

/** 체크박스 | 광고 명 | 상태 | (플랫폼) | 펼침 — AdListTable과 동일 그리드 */
const adListTableGridColsWithPlatform =
"grid w-full min-w-0 grid-cols-[2.75rem_minmax(0,1fr)_5.5rem_2.75rem_2.5rem] items-center gap-x-3";
"grid w-full min-w-0 grid-cols-[2.75rem_minmax(0,1fr)_5.5rem_2.75rem_2.5rem] items-center gap-x-3 mobile:grid-cols-[2rem_minmax(0,1fr)_auto_2rem_1.75rem] mobile:gap-x-1.5";

const adListTableGridColsWithoutPlatform =
"grid w-full min-w-0 grid-cols-[2.75rem_minmax(0,1fr)_5.5rem_2.5rem] items-center gap-x-3";
"grid w-full min-w-0 grid-cols-[2.75rem_minmax(0,1fr)_5.5rem_2.5rem] items-center gap-x-3 mobile:grid-cols-[2rem_minmax(0,1fr)_auto_1.75rem] mobile:gap-x-1.5";

const adListTableGridPadding = {
header: "px-6 py-4 tablet:px-5 tablet:py-3.5",
row: "px-6 py-5 tablet:px-5 tablet:py-4",
header: "px-6 py-4 tablet:px-5 tablet:py-3.5 mobile:px-4 mobile:py-3",
row: "px-6 py-5 tablet:px-5 tablet:py-4 mobile:px-4 mobile:py-3",
} as const;

export function getAdListTableStatusCellClass() {
return "flex min-w-0 items-center justify-center justify-self-center self-center";
return "flex min-w-0 items-center justify-center justify-self-center self-center mobile:justify-self-end";
}

export function getAdListTableHeaderGridClass(hidePlatformColumn = false) {
Expand Down Expand Up @@ -117,7 +117,7 @@ export default function AdRow({
onClick={onToggle}
aria-expanded={isOpen}
className={twMerge(
"min-w-0 cursor-pointer truncate text-left font-body1 outline-none transition-colors hover:text-primary-500",
"min-w-0 cursor-pointer truncate text-left font-body1-rsp outline-none transition-colors hover:text-primary-500",
isPaused ? "text-text-muted" : "text-text-title",
isOpen && "text-primary-500",
)}
Expand All @@ -126,13 +126,16 @@ export default function AdRow({
</button>

<div className={getAdListTableStatusCellClass()}>
<Badge variant={runStatus === "running" ? "infoBlue" : "surface"}>
<Badge
variant={runStatus === "running" ? "infoBlue" : "surface"}
className="mobile:h-6 mobile:px-2"
>
{runStatusText}
</Badge>
</div>

{!hidePlatformColumn ? (
<div className="flex min-w-11 items-center justify-start justify-self-start">
<div className="flex min-w-11 items-center justify-start justify-self-start mobile:min-w-0">
<span className="flex shrink-0" title={platform}>
{LogoMap[platform] ?? (
<span className="font-caption text-text-muted">?</span>
Expand All @@ -146,7 +149,7 @@ export default function AdRow({
type="button"
onClick={onToggle}
aria-label={isOpen ? `${name} 상세 접기` : `${name} 상세 펼치기`}
className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-text-auth-sub transition-colors hover:bg-surface-200/80 hover:text-text-title"
className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-text-auth-sub transition-colors hover:bg-surface-200/80 hover:text-text-title mobile:h-8 mobile:w-8"
>
<ChevronIcon
className={twMerge(
Expand Down
9 changes: 7 additions & 2 deletions src/components/ads/CampaignPlatformSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,13 @@ export default function CampaignPlatformSection({
<div className="flex min-w-0 flex-1 items-center gap-3">
{PLATFORM_LOGO[platform]}
<div className="flex min-w-0 flex-col gap-1">
<h2 className="font-heading3 text-text-title">
{PLATFORM_LABEL[platform]}
<h2 className="text-text-title">
<span className="font-heading3 mobile:hidden">
{PLATFORM_LABEL[platform]}
</span>
<span className="hidden font-heading4 mobile:inline">
{PLATFORM_LABEL[platform]}
</span>
</h2>
{platformBudget?.adCampaignName ? (
<p className="truncate font-body2 text-text-muted">
Expand Down
40 changes: 27 additions & 13 deletions src/components/ads/CampaignRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,24 @@ interface ICampaignRowProps {
onClick?: () => void;
}

/** 헤더·행·스켈레톤 플랫폼 열 — 모바일에서 로고 최대 3개 폭 예약 */
export const CAMPAIGN_PLATFORM_COL_CLASS =
"mr-24 w-28 shrink-0 tablet:mr-20 tablet:w-24 mobile:mr-2 mobile:w-16";

/** 헤더·행·스켈레톤 예산 열 */
export const CAMPAIGN_BUDGET_COL_CLASS =
"w-[28%] shrink-0 tablet:w-[26%] mobile:w-[30%] mobile:max-w-28";

const LogoMap: Record<TPlatform, ReactNode> = {
meta: (
<MetaLogo className="h-7 w-7 shrink-0 text-text-title tablet:h-6 tablet:w-6" />
<MetaLogo className="h-7 w-7 shrink-0 text-text-title tablet:h-6 tablet:w-6 mobile:h-5 mobile:w-5" />
),
google: (
<GoogleLogo className="h-7 w-7 shrink-0 tablet:h-6 tablet:w-6 mobile:h-5 mobile:w-5" />
),
naver: (
<NaverLogo className="h-7 w-7 shrink-0 tablet:h-6 tablet:w-6 mobile:h-5 mobile:w-5" />
),
google: <GoogleLogo className="h-7 w-7 shrink-0 tablet:h-6 tablet:w-6" />,
naver: <NaverLogo className="h-7 w-7 shrink-0 tablet:h-6 tablet:w-6" />,
};

export default function CampaignRow({
Expand All @@ -42,7 +54,7 @@ export default function CampaignRow({
return (
<li
className={twMerge(
"flex list-none cursor-pointer items-center border-b border-surface-400/50 px-6 py-5 transition-colors last:border-b-0 tablet:px-5 tablet:py-4",
"flex list-none cursor-pointer items-center border-b border-surface-400/50 px-6 py-5 transition-colors last:border-b-0 tablet:px-5 tablet:py-4 mobile:px-3 mobile:py-3",
isSelected
? "bg-primary-100/35 hover:bg-primary-100/45"
: "bg-surface-100 hover:bg-surface-200/50",
Expand All @@ -59,7 +71,7 @@ export default function CampaignRow({
}}
>
<div
className="flex w-11 shrink-0 items-center justify-center tablet:w-10"
className="flex w-11 shrink-0 items-center justify-center tablet:w-10 mobile:w-8"
role="presentation"
onClick={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
Expand All @@ -73,20 +85,25 @@ export default function CampaignRow({
/>
</div>

<div className="min-w-0 flex-1 pr-5 tablet:pr-4">
<div className="min-w-0 flex-1 pr-5 tablet:pr-4 mobile:pr-2">
<div
className={twMerge(
"truncate font-body1",
"truncate font-body1-rsp",
isPaused ? "text-text-muted" : "text-text-title",
)}
>
{name}
</div>
</div>

<div className="mr-24 flex w-28 shrink-0 items-center justify-start tablet:mr-20 tablet:w-24">
<div
className={twMerge(
CAMPAIGN_PLATFORM_COL_CLASS,
"flex items-center justify-start",
)}
>
{providers && providers.length > 0 ? (
<div className="flex items-center justify-start gap-1">
<div className="flex items-center justify-start gap-1 mobile:gap-0.5">
{providers.map((p, idx) => (
<span key={idx} className="flex shrink-0">
{LogoMap[p.toLowerCase() as TPlatform] ?? (
Expand All @@ -101,10 +118,7 @@ export default function CampaignRow({
</div>

<div
className={twMerge(
"w-[28%] shrink-0 tablet:w-[26%]",
isPaused && "opacity-80",
)}
className={twMerge(CAMPAIGN_BUDGET_COL_CLASS, isPaused && "opacity-80")}
>
<ProgressBar value={budgetUsageRate} />
</div>
Expand Down
25 changes: 19 additions & 6 deletions src/components/ads/CampaignTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { twMerge } from "tailwind-merge";

import type { ICampaign } from "@/types/ads/campaign";

import CampaignRow from "./CampaignRow";
import CampaignRow, {
CAMPAIGN_BUDGET_COL_CLASS,
CAMPAIGN_PLATFORM_COL_CLASS,
} from "./CampaignRow";
Comment thread
jjjsun marked this conversation as resolved.

interface ICampaignTableProps {
campaigns: ICampaign[];
Expand Down Expand Up @@ -53,9 +56,9 @@ export default function CampaignTable({
: "rounded-xl border border-surface-400/40",
)}
>
<div className="flex shrink-0 items-center border-b border-surface-400/50 bg-surface-200/60 px-6 py-4 tablet:px-5 tablet:py-3.5">
<div className="flex shrink-0 items-center border-b border-surface-400/50 bg-surface-200/60 px-6 py-4 tablet:px-5 tablet:py-3.5 mobile:px-3 mobile:py-3">
<div
className="flex w-11 shrink-0 items-center justify-center tablet:w-10"
className="flex w-11 shrink-0 items-center justify-center tablet:w-10 mobile:w-8"
role="presentation"
onClick={(e) => e.stopPropagation()}
>
Expand All @@ -71,10 +74,20 @@ export default function CampaignTable({
<div className="min-w-0 flex-1 font-label text-text-muted">
캠페인 명
</div>
<div className="w-28 shrink-0 text-left font-label text-text-muted whitespace-nowrap mr-24 tablet:w-24 tablet:mr-20">
플랫폼
<div
className={twMerge(
CAMPAIGN_PLATFORM_COL_CLASS,
"whitespace-nowrap text-left font-label text-text-muted",
)}
>
<span className="mobile:hidden">플랫폼</span>
</div>
<div className="w-[28%] shrink-0 text-left font-label text-text-muted tablet:w-[26%]">
<div
className={twMerge(
CAMPAIGN_BUDGET_COL_CLASS,
"text-left font-label text-text-muted",
)}
>
<span className="tablet:hidden">예산 소진 현황</span>
<span className="hidden tablet:inline">예산</span>
</div>
Expand Down
Loading
Loading