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
2 changes: 1 addition & 1 deletion src/feature/album-entry/components/LetterContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default function LetterContent({ albumId }: LetterContentProps) {
{data.eventDate}
</p>
{!data.isExpired && (
<span className='typo-caption-sm-medium text-text-basic-inverse bg-element-primary mt-3 inline-flex items-center rounded-full px-2.5 py-1'>
<span className='typo-caption-sm-medium text-text-basic-inverse bg-element-alpha-dark mt-3 inline-flex items-center rounded-full px-2.5 py-1'>
앨범 소멸까지 {formatExpirationTime(data.expiredAt)}
</span>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/feature/album/4cut/components/ScreenAlbum4Cut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ export const ActionButton = ({
<button
type='button'
onClick={onClick}
className='bg-button-tertiary-fill text-text-subtle flex flex-1 items-center justify-center gap-1 rounded-[8px] py-[15px]'
className='text-text-subtle flex flex-1 items-center justify-center gap-1 rounded-[8px] bg-white py-[15px]'
>
<Icon width={24} height={24} color='var(--color-icon-basic)' />
<span className='typo-body-1xl-semibold'>{text}</span>
Expand Down
13 changes: 10 additions & 3 deletions src/feature/album/detail/components/AlbumBestCut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import AlbumBestCutPhotoList from './AlbumBestCutPhotoList';

import { AlbumDetailMode } from './ScreenAlbumDetail';

const BEST_CUT_TOOLTIP_DISMISSED_KEY = 'best-cut-tooltip-dismissed';

interface AlbumBestCutProps {
albumId: string;
photoCount?: number;
mode: AlbumDetailMode;
}

export default function AlbumBestCut({
albumId,
photoCount,
mode,
}: AlbumBestCutProps) {
const router = useRouter();
const abGroup = useABTestGroup();
Expand Down Expand Up @@ -52,15 +56,18 @@ export default function AlbumBestCut({
? '네컷사진 미리보기'
: abGroup === 'B'
? '네컷사진 만들기'
: '이대로 네컷 확정하기'
: '네컷사진 확정하기'
}
onClick={() => router.push(`/album/4cut/${albumId}`)}
onClick={() => {
handleCloseBubble();
router.push(`/album/4cut/${albumId}`);
}}
noFixed
disabled={photoCount < 4}
height={48}
/>

{isBubbleVisible && (
{isBubbleVisible && mode !== 'select' && (
<BubbleTooltip
message={
<span className='flex items-center gap-2 whitespace-nowrap'>
Expand Down
13 changes: 11 additions & 2 deletions src/feature/album/detail/components/AlbumInfos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,25 @@ import { useShallow } from 'zustand/shallow';
import AlbumBestCut from './AlbumBestCut';
import { AlbumInfoSummary } from './AlbumInfoSummary';

import { AlbumDetailMode } from './ScreenAlbumDetail';

interface AlbumInfosProps {
ref?: React.Ref<HTMLElement>;
albumId: string;
albumInfo?: AlbumInvitationResponseSchema;
isLoading: boolean;
isError: boolean;
photoCount?: number;
mode: AlbumDetailMode;
}

function AlbumInfos({ ref, albumId, photoCount, ...rest }: AlbumInfosProps) {
function AlbumInfos({
ref,
albumId,
photoCount,
mode,
...rest
}: AlbumInfosProps) {
const { albumType, setAlbumType } = useAlbumTypeStore(
useShallow((state) => ({
albumType: state.albumType,
Expand All @@ -31,7 +40,7 @@ function AlbumInfos({ ref, albumId, photoCount, ...rest }: AlbumInfosProps) {
className='border-divider-gray-light flex flex-col gap-6 border-b-[6px] px-5 py-4'
>
<AlbumInfoSummary {...rest} />
<AlbumBestCut albumId={albumId} photoCount={photoCount} />
<AlbumBestCut albumId={albumId} photoCount={photoCount} mode={mode} />
</section>
);
}
Expand Down
30 changes: 23 additions & 7 deletions src/feature/album/detail/components/PhotoList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ export default function PhotoList({
addSelectedPhoto,
deleteSelectedPhoto,
clearSelectedPhotos,
setSelectedPhotos,
isSelected,
} = useSelectedPhotosStore(
useShallow((state) => ({
selectedPhotos: state.selectedPhotos,
addSelectedPhoto: state.addSelectedPhoto,
deleteSelectedPhoto: state.deleteSelectedPhoto,
clearSelectedPhotos: state.clearSelectedPhotos,
setSelectedPhotos: state.setSelectedPhotos,
isSelected: state.isSelected,
})),
);
Expand Down Expand Up @@ -169,26 +171,40 @@ export default function PhotoList({
selectablePhotos.length > 0 &&
selectablePhotos.every(({ photoId }) => selectedPhotoIds.has(photoId));

const selectableStorePhotos = useMemo(
() =>
selectablePhotos.map(({ photoId, imageUrl }) => ({
id: photoId,
url: imageUrl ?? '',
})),
[selectablePhotos],
);

const handleToggleSelectAll = () => {
if (isAllSelected) {
setIsSelectAllMode(false);
clearSelectedPhotos();
return;
}
setIsSelectAllMode(true);
selectablePhotos.forEach(({ photoId, imageUrl }) => {
addSelectedPhoto({ id: photoId, url: imageUrl ?? '' });
});
setSelectedPhotos(selectableStorePhotos);
};

useEffect(() => {
if (mode !== 'select') return;
if (!isSelectAllMode) return;

selectablePhotos.forEach(({ photoId, imageUrl }) => {
addSelectedPhoto({ id: photoId, url: imageUrl ?? '' });
});
}, [addSelectedPhoto, isSelectAllMode, mode, selectablePhotos]);
const currentSelected = useSelectedPhotosStore.getState().selectedPhotos;
const currentIds = new Set(currentSelected.map((p) => p.id));

const isDifferent =
currentSelected.length !== selectableStorePhotos.length ||
selectableStorePhotos.some((p) => !currentIds.has(p.id));

if (isDifferent) {
setSelectedPhotos(selectableStorePhotos);
}
}, [isSelectAllMode, mode, selectableStorePhotos, setSelectedPhotos]);

return (
<section ref={photoListRef} className='relative p-4'>
Expand Down
1 change: 1 addition & 0 deletions src/feature/album/detail/components/ScreenAlbumDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export default function ScreenAlbumDetail({ albumId }: ScreenAlbumDetailProps) {
isLoading={isInvitationLoading}
isError={isInvitationError}
photoCount={totalPhotoCount}
mode={mode}
/>
<AlbumPhotoSection
isLoading={isLoading}
Expand Down
3 changes: 3 additions & 0 deletions src/store/useSelectedPhotosStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface SelectedPhotosState {
addSelectedPhoto: ({ id, url }: StorePhotoItem) => void;
deleteSelectedPhoto: (photoId: number) => void;
clearSelectedPhotos: () => void;
setSelectedPhotos: (photos: StorePhotoItem[]) => void;
isSelected: (photoId: number) => boolean;
}

Expand All @@ -34,6 +35,8 @@ export const useSelectedPhotosStore = create<SelectedPhotosState>(

clearSelectedPhotos: () => set({ selectedPhotos: [] }),

setSelectedPhotos: (photos) => set({ selectedPhotos: photos }),

isSelected: (photoId) => {
const { selectedPhotos } = get();
return selectedPhotos.some((p) => p.id === photoId);
Expand Down
Loading