Skip to content

Commit

Permalink
Merge branch 'develop' into fix/mvp-9th-qa
Browse files Browse the repository at this point in the history
  • Loading branch information
alstn2468 committed Nov 24, 2024
2 parents c2c402a + 6d300ca commit 81f0292
Show file tree
Hide file tree
Showing 14 changed files with 775 additions and 702 deletions.
243 changes: 135 additions & 108 deletions .pnp.cjs

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
"@boolti/api": "*",
"@boolti/icon": "*",
"@boolti/ui": "*",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"@react-pdf/renderer": "^3.4.4",
Expand All @@ -29,8 +33,6 @@
"qrcode.react": "^3.1.0",
"react": "^18.2.0",
"react-daum-postcode": "^3.1.3",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-hook-form": "^7.50.0",
Expand Down
11 changes: 5 additions & 6 deletions apps/admin/src/components/ShowCastInfo/ShowCastInfo.styles.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Button, mq_lg } from '@boolti/ui';
import { mq_lg } from '@boolti/ui';
import styled from '@emotion/styled';
import { m } from 'framer-motion';

const Container = styled.div`
position: relative;
border-radius: 8px;
background: ${({ theme }) => theme.palette.grey.w};
box-shadow: 0px 8px 14px 0px ${({ theme }) => theme.palette.shadow};
Expand Down Expand Up @@ -36,7 +37,7 @@ const Handle = styled.button`
align-items: center;
justify-content: center;
color: ${({ theme }) => theme.palette.grey.g40};
cursor: move;
cursor: grab;
user-select: none;
user-zoom: none;
`
Expand All @@ -46,9 +47,7 @@ const Name = styled.span`
${({ theme }) => theme.typo.sh2};
`;

const EditButton = styled(Button)`
padding: 13px 18px;
const EditButtonWrapper = styled.div`
span {
display: none;
margin-left: 8px;
Expand Down Expand Up @@ -150,7 +149,7 @@ export default {
Name,
Cast,
CollapseButton,
EditButton,
EditButtonWrapper,
CastItem,
UserImage,
Username,
Expand Down
154 changes: 64 additions & 90 deletions apps/admin/src/components/ShowCastInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,122 +1,95 @@
import { useDialog } from '@boolti/ui';
import { useDrag, useDrop } from 'react-dnd'
import { TextButton, useDialog } from '@boolti/ui';
import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

import Styled from './ShowCastInfo.styles';
import { EditIcon, ChevronDownIcon, ChevronUpIcon, UserIcon, MenuIcon } from '@boolti/icon';
import { useRef, useState } from 'react';
import { useState } from 'react';
import ShowCastInfoFormDialogContent, {
TempShowCastInfoFormInput,
} from '../ShowCastInfoFormDialogContent';

interface Props {
showCastInfo: TempShowCastInfoFormInput;
index: number;
onSave: (value: TempShowCastInfoFormInput) => Promise<void>;
onDropHover: (draggedItemId: number, hoverIndex: number) => void;
onDrop?: () => void;
onDelete?: () => Promise<void>;
}

interface DragItem {
id: number
index: number
}

const ShowCastInfo = ({ showCastInfo, index, onSave, onDropHover, onDrop, onDelete }: Props) => {
const ref = useRef<HTMLDivElement>(null)
const [{ isDragging }, drag, preview] = useDrag<DragItem, unknown, { isDragging: boolean }>(() => ({
type: 'castTeam',
previewOptions: {
captureDraggingState: true,
},
item: { id: showCastInfo.id, index },
collect: (monitor) => ({
isDragging: monitor.isDragging()
}),
}))
const [, drop] = useDrop<DragItem>({
accept: 'castTeam',
hover(item: DragItem, monitor) {
if (!ref.current) return;
if (!monitor.canDrop()) return;
if (item.id === showCastInfo.id) return;

const dragIndex = item.index;
const hoverIndex = index;

const hoverBoundingRect = ref.current.getBoundingClientRect();
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
const clientOffset = monitor.getClientOffset();
if (!clientOffset) return;

const hoverClientY = clientOffset.y - hoverBoundingRect.top;
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) return;
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) return;

item.index = hoverIndex;

onDropHover(item.id, index);
},
drop() {
onDrop?.()
}
})

const ShowCastInfo = ({ showCastInfo, onSave, onDelete }: Props) => {
const { members = [] } = showCastInfo;
const memberLength = members.length ?? 0;
const dialog = useDialog();
const [isOpen, setIsOpen] = useState(false);

const toggle = () => setIsOpen((prev) => !prev);
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
isDragging
} = useSortable({ id: showCastInfo.id });

preview(drop(ref))
const style = {
transform: CSS.Translate.toString(transform),
transition,
backgroundColor: isDragging ? 'rgba(231, 234, 242, 0.5)' : undefined,
backdropFilter: isDragging ? 'blur(3px)' : undefined,
zIndex: isDragging ? 100 : 99,
cursor: isDragging ? 'grabbing' : undefined,
};

const toggle = () => setIsOpen((prev) => !prev);

return (
<Styled.Container ref={ref} style={{ opacity: isDragging ? 0.4 : 1 }}>
<Styled.Container ref={setNodeRef} style={style}>
<Styled.Header>
<Styled.HeaderNameWrapper>
<Styled.Handle type="button" ref={drag} onScroll={(event) => { event.stopPropagation() }}>
<Styled.Handle type="button" {...attributes} {...listeners}>
<MenuIcon />
</Styled.Handle>
<Styled.Name>
{showCastInfo.name}
</Styled.Name>
</Styled.HeaderNameWrapper>
<Styled.EditButton
colorTheme="line"
size="bold"
onClick={(e) => {
e.preventDefault();
dialog.open({
title: '출연진 정보 편집',
isAuto: true,
content: (
<ShowCastInfoFormDialogContent
onSave={async (castInfo) => {
try {
await onSave(castInfo);
dialog.close();
} catch {
return new Promise((_, reject) => reject('저장 중 오류가 발생하였습니다.'));
}
}}
prevShowCastInfo={showCastInfo}
onDelete={async () => {
try {
await onDelete?.();
dialog.close();
} catch {
return new Promise((_, reject) => reject('삭제 중 오류가 발생하였습니다.'));
}
}}
/>
),
});
}}
>
<EditIcon />
<span>정보 편집</span>
</Styled.EditButton>
<Styled.EditButtonWrapper>
<TextButton
type="button"
colorTheme="netural"
size="regular"
onClick={(e) => {
e.preventDefault();
dialog.open({
title: '출연진 정보 편집',
isAuto: true,
content: (
<ShowCastInfoFormDialogContent
onSave={async (castInfo) => {
try {
await onSave(castInfo);
dialog.close();
} catch {
return new Promise((_, reject) => reject('저장 중 오류가 발생하였습니다.'));
}
}}
prevShowCastInfo={showCastInfo}
onDelete={async () => {
try {
await onDelete?.();
dialog.close();
} catch {
return new Promise((_, reject) => reject('삭제 중 오류가 발생하였습니다.'));
}
}}
/>
),
});
}}
>
<EditIcon />
<span>정보 편집</span>
</TextButton>
</Styled.EditButtonWrapper>
</Styled.Header>
{memberLength > 0 && (
<>
Expand All @@ -141,6 +114,7 @@ const ShowCastInfo = ({ showCastInfo, index, onSave, onDropHover, onDrop, onDele
))}
</Styled.Cast>
<Styled.CollapseButton
type="button"
onClick={(e) => {
e.preventDefault();
toggle();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from '@dnd-kit/utilities';
import ShowCastInfoMemberRow, { ShowCastInfoMemberRowProps } from "./ShowCastInfoMemberRow";

interface DraggableShowCastInfoMemberRowProps extends ShowCastInfoMemberRowProps {
id: string
}

const DraggableShowCastInfoMemberRow = ({ id, ...props }: DraggableShowCastInfoMemberRowProps) => {
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
isDragging
} = useSortable({ id });

const style = {
transform: CSS.Translate.toString(transform),
transition,
opacity: isDragging ? 0 : 1
};

return (
<ShowCastInfoMemberRow {...props} ref={setNodeRef} draggingStyle={style} {...attributes} {...listeners} />
)
}

export default DraggableShowCastInfoMemberRow
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const ShowInfoFormLabel = styled.span<ShowInfoFormLabelProps>`
`;

const MemberList = styled.div`
display: flex;
flex-direction: column;
gap: 20px;
max-height: 364px;
overflow-y: scroll;
::-webkit-scrollbar {
Expand Down Expand Up @@ -70,7 +73,7 @@ const Handle = styled.button`
color: ${({ theme }) => theme.palette.grey.g40};
margin-top: 12px;
margin-right: 8px;
cursor: move;
cursor: grab;
user-select: none;
user-zoom: none;
`
Expand Down Expand Up @@ -102,9 +105,9 @@ const Row = styled.div`
display: flex;
justify-content: center;
align-items: flex-start;
margin-bottom: 20px;
background-color: ${({ theme }) => theme.palette.grey.w};
border-radius: 4px;
position: relative;
z-index: 99;
`;

const TrashCanButton = styled.button`
Expand Down Expand Up @@ -185,6 +188,30 @@ const ErrorMessage = styled.span`
color: ${({ theme }) => theme.palette.status.error};
`;

const DraggableShowCastInfoMemberRow = styled.div`
border-radius: 4px;
cursor: grabbing;
backdrop-filter: blur(1.5px);
z-index: 100;
& > div > div > div {
background: none;
}
&::after {
content: '';
position: absolute;
top: -10px;
left: -10px;
width: calc(100% + 20px);
height: calc(100% + 20px);
background-color: rgba(231, 234, 242, 0.5);
border-radius: 4px;
z-index: -1;
}
`


export default {
ShowInfoFormLabel,
InputWrapper,
Expand All @@ -204,4 +231,5 @@ export default {
DeleteButton,
ErrorMessage,
FieldWrap,
DraggableShowCastInfoMemberRow
};
Loading

0 comments on commit 81f0292

Please sign in to comment.