Skip to content

(#102) 운동기록 리스트 캘린더 페이지 달력 아래로 이동 - #107

Merged
ldg-96 merged 3 commits into
developfrom
feature/exercise-move-list
Aug 4, 2025
Merged

(#102) 운동기록 리스트 캘린더 페이지 달력 아래로 이동#107
ldg-96 merged 3 commits into
developfrom
feature/exercise-move-list

Conversation

@ldg-96

@ldg-96 ldg-96 commented Jul 31, 2025

Copy link
Copy Markdown
Contributor

📝작업 내용

  • 운동기록 리스트 페이지를 메인페이지의 달력 아래로 이동

변경전

image

변경후

image
  • 임시 배경 이미지 추가
  • 점수 획득을 못하는 운동은 기록시 축하메세지를 띄워주지 않도록 변경
  • 상세기록 페이지에서 각 데이터 필드마다 margin이 적용되지 않던 오류 수정(이전 이슈에서 description을 넣는과정에서 css변경이 원인)
  • 운동기록, 운동기록수정 페이지의 완료 버튼을 하단에서 헤더로 이동
image

관련이슈

#102

@ldg-96
ldg-96 requested a review from SimYunSup July 31, 2025 19:20
Comment on lines +151 to +172
const calculateScoreDescription = (): string => {
if (!isCreate || !scoreData || !startedDate) {
return ''
}

const selectedDate = new Date(startedDate)
const selectedDate = new Date(startedDate)
if (scoreData.currentScore >= scoreData.maxScore) {
return '점수가 최대치에 도달했어요!'
}

// 점수가 최대치인 경우
if (scoreData.currentScore >= scoreData.maxScore) {
return '점수가 최대치에 도달했어요!'
}
// ... 나머지 계산 로직은 동일 ...
const validWindowStart = new Date(scoreData.validPeriod.startedAt)
if (selectedDate < validWindowStart) {
return '점수를 획득할 수 있는 기간이 지났어요'
}
const selectedDateStr = format(selectedDate, 'yyyy-MM-dd')
if (!scoreData.ValidDate.includes(selectedDateStr)) {
return '이 날은 이미 점수를 획득했어요'
}
const validWindowStart = new Date(scoreData.validPeriod.startedAt)
if (selectedDate < validWindowStart) {
return '점수를 획득할 수 있는 기간이 지났어요'
}
const selectedDateStr = format(selectedDate, 'yyyy-MM-dd')
if (!scoreData.ValidDate.includes(selectedDateStr)) {
return '이 날은 이미 점수를 획득했어요'
}

return ''
}
const scoreDescription = calculateScoreDescription()
return ''
}
const scoreDescription = calculateScoreDescription()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이전에 댓글로 못 달았는데, zod로 validate하면 안되는 것인가요?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 로직은 폼 제출을 막는 유효성 검증이 아닌 폼제출은 되지만 점수는 획득하지 못한다는 안내메세지입니다.

따라서 useStore를 사용해서 startedAt이 바뀔때마다 안내메세지를 표시해 주도록 하였습니다.

Comment on lines +39 to +40
const { data: cachedData } = useSWR<ExerciseRange[]>(swrKey, null)
const data = fetchedData || cachedData

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cachedData에 어떤 의미가 있나요?

@ldg-96 ldg-96 Aug 3, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당코드는 캘린더의 스와이프 애니메이션과 관련이 있습니다. 캘린더는 다음과 같이 동작해야합니다.

  1. 스와이프로 달력을 좌 우로 이동할 수 있어야 한다.
  2. 처음 조회된 달은 스탬프(운동기록이 있는 날짜)가 fade-in 효과를 통해 천천히 표시된다
  3. 한번 조회된적이 있는 달은 스탬프가 바로 표시된다.
  4. 전달, 혹은 다음달이 조회된적이 있는 달은 스와이프도중 미리 보여지는 달력에 스탬프가 표시되어있어야 한다.

MonthViewWithData 컴포넌트는 isActive prop을 받습니다. 현재달이 만약 8월이라면 7월과 9월의 데이터는 shouldFetch = false이기 때문에 받아오지 않습니다.

하지만 const { data: cachedData } = useSWR<ExerciseRange[]>(swrKey, null) 을 통해 캐쉬된적이 있는 달의 데이터를 받아오고 조회가 되었던 달은 스탬프를 표시해 주는 역할을 합니다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keepPreviousData는 작동하지 않나요?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SWR의 keepPreviousData옵션으로 제가구현했던 코드를 더 깔끔하게 리팩토링해볼 수 있을것 같습니다. 해당부분 기술부채에 추가해두었다가 추후에 리팩토링 해보도록 하겠습니다.

>
완료
</Typography>
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

함수로 구성하지 않은 것과 어떤 차이가 있을까요?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

함수로 구성하지 않을경우 단순히 React 엘리먼트가 됩니다. 정적이고 props를 받을 수 없고 상태관리 같은 기능들을 사용할 수 없습니다.

따라서 리액트는 함수로 코드를 작성하여 컴포넌트로 만드는것을 권장하는것 같습니다.

type Props = {
  children: ReactNode
  className?: string
  rightIcon?: React.ReactNode
  onClick?: () => void
}

const Header = ({
  children,
  className = 'center-title',
  rightIcon,
  onClick,
}: Props) => {
...
}

completeButton을 제가 rightIcon에 전달하려고 했을 때 컴포넌트를 호출해서 이와같이 엘리먼트로 만들어서 전달을 했어햐 했는대 함수 자체를 전달하려고 해서 오류가 났었습니다. 그래서 리뷰해주신 코드처럼 만들었는대 잘못된 사용방식임을 깨달았습니다.

해당 코드를 함수로구성하고 이를 호출해서 엘리먼트로 만들어 header에 전달해주는 방식으로 변경하였습니다.

@ldg-96
ldg-96 requested a review from SimYunSup August 3, 2025 21:32
@ldg-96
ldg-96 changed the base branch from dev-temp to develop August 4, 2025 10:58
@ldg-96
ldg-96 merged commit 999aca1 into develop Aug 4, 2025
1 check passed
ldg-96 added a commit that referenced this pull request Aug 4, 2025
@ldg-96
ldg-96 deleted the feature/exercise-move-list branch November 30, 2025 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants