Skip to content

Commit

Permalink
Merge pull request #180 from KNU-HAEDAL/develop
Browse files Browse the repository at this point in the history
진행상황 합병
  • Loading branch information
Dobbymin authored Oct 1, 2024
2 parents 4f3719d + ba4c3f7 commit 4e9edc3
Show file tree
Hide file tree
Showing 36 changed files with 1,082 additions and 823 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ https://zzansuni-fe-vercel.vercel.app/
사용자들에게 챌린지에 대해 공유 할 수 있으며, 랭킹을 통해 서로 경쟁할 수
있습니다.

### 개발자 소개

| 백엔드 | 백엔드 | 프론트엔드 | 프론트엔드 | 백엔드 |
| :----------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------: |
| [<img src="https://github.com/momnpa333.png" width="100px">](https://github.com/momnpa333) | [<img src="https://github.com/kwonssshyeon.png" width="100px">](https://github.com/kwonssshyeon) | [<img src="https://github.com/Dobbymin.png" width="100px">](https://github.com/Dobbymin) | [<img src="https://github.com/joojjang.png" width="100px">](https://github.com/joojjang) | [<img src="https://github.com/bayy1216.png" width="100px">](https://github.com/bayy1216) |
| 권다운 | 권수현 | 김강민 | 김민주 | 손홍석 |

### 개발 동기

기획 단계에서 팀원들과 다양한 아이디어에 대해 생각을 해 보았고, 공통적으로
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --host",
"build": "tsc && vite build",
"port": "vite --host 0.0.0.0 --port 5173",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
Expand Down
63 changes: 42 additions & 21 deletions src/apis/challenge-record/challenge.record.api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { AxiosError } from 'axios';

import { multiPartClient, axiosClient } from '../AxiosClient';
import {
ApiResponse,
Expand All @@ -9,34 +11,42 @@ import {

// POST: /api/challenges/{challengeId}/verification
export async function postVerification(
id: number,
image: File,
content: string
): Promise<ChallengeVerificationData> {
const formData = new FormData();
formData.append(
challengeId: number,
content: string,
image: File
): Promise<void> {
const requestBody = new FormData();
requestBody.append(
'body',
new Blob([JSON.stringify({ content })], { type: 'application/json' })
);
formData.append('image', image);
requestBody.append('image', image);

const response = await multiPartClient.post<ChallengeVerificationData>(
`api/challenges/${id}/verifications`,
formData
`api/challenges/${challengeId}/verification`,
requestBody
);
console.log('postVerification response: ', response.data);
return response.data;
console.log('postVerification response: ', response.data); // test
}

// GET: /api/challenges/{challengeId}/record
export async function getChallengeRecord(
id: number
challengeId: number
): Promise<ChallengeRecordData> {
const response = await axiosClient.get<ApiResponse<ChallengeRecordData>>(
`api/challenges/${id}/record`
);
console.log('getChallengeRecord response: ', response.data);
return response.data.data;
try {
const response = await axiosClient.get(
`api/challenges/${challengeId}/record`
);
// console.log('getChallengeRecord response: ', response.data); // test
return response.data.data;
} catch (error) {
if (error instanceof AxiosError) {
throw new Error(
`getChallengeRecord error: ${error.response?.data.message || error.message}`
);
} else {
throw new Error('getChallengeRecord error: unexpected');
}
}
}

// GET: /api/challenges/record/{recordId}
Expand All @@ -50,11 +60,22 @@ export async function getChallengeRecordDetailorigin(
return response.data.data;
}

export async function getChallengeRecordDetail(
export async function getChallengeRecordDetails(
recordId: number
): Promise<ChallengeRecordDetailData> {
const response = await axiosClient.get(`api/challenges/record/${recordId}`);
return response.data;
try {
const response = await axiosClient.get(`api/challenges/record/${recordId}`);
// console.log('getChallengeRecordDetails response: ', response.data); // test
return response.data.data;
} catch (error) {
if (error instanceof AxiosError) {
throw new Error(
`getChallengeRecord error: ${error.response?.data.message || error.message}`
);
} else {
throw new Error('getChallengeRecord error: unexpected');
}
}
}

// GET: /api/user/challenges/completes
Expand Down
30 changes: 10 additions & 20 deletions src/apis/challenge-record/challenge.record.response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,19 @@ export type ApiResponse<T> = {
};

export type ChallengeRecordData = {
result: string;
data: {
title: string;
totalCount: number;
successCount: number;
startDate: string;
endDate: string;
recordIds: number[];
};
message: string;
errorCode: string;
title: string;
totalCount: number;
successCount: number;
startDate: string;
endDate: string;
recordIds: number[];
};

export type ChallengeRecordDetailData = {
result: string;
data: {
id: 0;
createdAt: string;
content: string;
imageUrl: string;
};
message: string;
errorCode: string;
id: 0;
createdAt: string;
content: string;
imageUrl: string;
};

export type CompleteChallengeData = {
Expand Down
27 changes: 27 additions & 0 deletions src/apis/recently-review/getRecentlyReview.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { RecentlyReviewResponse } from './getRecentlyReview.response';
import { axiosClient } from '@/apis/AxiosClient';
import { useQuery } from '@tanstack/react-query';

const getRecentlyReviewPath = () => '/api/challengeGroups/shorts';

const recentlyReviewQueryKey = [getRecentlyReviewPath()];

const getRecentlyReview = async (
page: number,
size: number
): Promise<RecentlyReviewResponse> => {
const response = await axiosClient.get(getRecentlyReviewPath(), {
params: {
page,
size,
},
});
return response.data;
};

export const useGetRecentlyReview = (page: number, size: number) => {
return useQuery<RecentlyReviewResponse, Error>({
queryKey: [recentlyReviewQueryKey, page, size],
queryFn: () => getRecentlyReview(page, size),
});
};
24 changes: 24 additions & 0 deletions src/apis/recently-review/getRecentlyReview.response.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import ApiResponse from '@/apis/ApiResponse';

export type RecentlyReviewResponse = {
totalPage: number;
hasNext: boolean;
data: {
challengeId: number;
challengeTitle: string;
user: {
id: number;
nickname: string;
profileImageUrl: string;
tierInfo: {
tier: string;
totalExp: number;
currentExp: number;
};
};
content: string;
rating: number;
}[];
};

export type ChallengeListResponse = ApiResponse<RecentlyReviewResponse>;
Binary file added src/assets/shorts/shorts-img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions src/assets/stamp-active.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/assets/stamp-inactive.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions src/components/common/challenge-title/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Text } from '@chakra-ui/react';
import styled from '@emotion/styled';

type ChallengeTitleProps = {
category: string;
title: string;
};

const ChallengeTitle = ({ category, title }: ChallengeTitleProps) => {
return (
<Wrapper>
<Text fontSize='var(--font-size-xs)' color='var(--color-green-01)'>
{category}
</Text>
<Text fontSize='var(--font-size-xl)' fontWeight='700'>
{title}
</Text>
</Wrapper>
);
};

export default ChallengeTitle;

const Wrapper = styled.div`
margin: 16px;
display: flex;
flex-direction: column;
text-align: left;
`;
5 changes: 4 additions & 1 deletion src/components/common/cta/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const CTA = ({ label, disabled, onClick }: CTAProps) => {

export default CTA;

export const CTA_CONTAINER_HEIGHT = '4rem';

const StyledCTA = styled.button<{ disabled?: boolean }>`
width: calc(100% - 16px); // 부모 요소의 좌우 padding 빼고
border: none;
Expand Down Expand Up @@ -53,7 +55,8 @@ export const CTAContainer = styled.div`
bottom: 0;
display: flex;
width: 100%;
height: 4rem;
height: ${CTA_CONTAINER_HEIGHT};
padding: 8px 16px;
background-color: var(--color-white);
z-index: 1;
`;
37 changes: 29 additions & 8 deletions src/components/common/form/textarea/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,41 @@
import { Text } from '@chakra-ui/react';
import styled from '@emotion/styled';

type TextareaProps = {
placeholder?: string;
value: string;
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
minValueLength?: number;
valid?: boolean;
};

const Textarea = ({ placeholder, value, onChange, valid }: TextareaProps) => {
const Textarea = ({
placeholder,
value,
onChange,
minValueLength,
valid,
}: TextareaProps) => {
return (
<StyledTextarea
placeholder={placeholder}
value={value}
onChange={onChange}
valid={valid}
/>
<>
<StyledTextarea
placeholder={placeholder}
value={value}
onChange={onChange}
valid={valid}
/>
{/* 최소 길이 제한 있을 때만 보이기 */}
{minValueLength && (
<Text
fontSize='var(--font-size-xs)'
color={valid ? `var(--color-grey-01)` : `var(--color-class-05)`}
textAlign='right'
margin='8px 16px 0'
>
{value.length} / 최소 {minValueLength}
</Text>
)}
</>
);
};

Expand All @@ -29,10 +50,10 @@ const StyledTextarea = styled.textarea<{ valid?: boolean }>`
? 'var(--color-grey-02) 1px solid'
: 'var(--color-class-05) 1px solid'};
padding: 12px;
width: 100%;
height: 180px;
resize: none;
outline: none;
margin: 0 16px;
&::placeholder {
color: var(--color-grey-01);
Expand Down
9 changes: 5 additions & 4 deletions src/components/common/tabs/tab-panels/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,20 @@ export const TabPanel = ({ children, value, selectedIndex }: TabPanelProps) => {
};

export const StyledTabPanels = styled.div`
height: 100%;
width: 100%;
position: relative;
text-align: center;
display: flex;
flex-direction: column;
flex: 1;
`;

export const StyledTabPanel = styled.div<{
active: boolean;
}>`
display: ${(p) => (p.active ? 'flex' : 'none')};
font-size: 2rem;
flex-direction: column;
flex: 1;
width: 100%;
height: 100%;
justify-content: center;
font-size: 2rem;
`;
25 changes: 9 additions & 16 deletions src/components/features/layout/nav-bar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useNavigate } from 'react-router-dom';

import { navBarData } from '@/constants/nav-bar';
import { Box } from '@chakra-ui/react';
import { Box, Image } from '@chakra-ui/react';
import styled from '@emotion/styled';

export const NAVBAR_HEIGHT = '3.44rem';
Expand All @@ -14,14 +14,10 @@ const NavBar = () => {
};

return (
<Wrapper>
<Wrapper as='nav'>
{navBarData.map((item) => (
<Tab key={item.title}>
<Icon
src={item.icon}
// alt={item.title}
onClick={() => handleNav(item.path)}
/>
<Tab as='a' key={item.title} onClick={() => handleNav(item.path)}>
<IconImage src={item.icon} alt={item.title} />
</Tab>
))}
</Wrapper>
Expand All @@ -44,20 +40,17 @@ const Wrapper = styled(Box)`
background-color: #fafafa;
`;

const Tab = styled.div`
width: 50%;
const Tab = styled.a`
width: 50%; // 요소마다 부모 요소의 너비를 균등하게 차지하도록
height: 100%;
display: inline-flex;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
`;

const Icon = styled.button<{ src: string }>`
const IconImage = styled(Image)`
width: 2rem;
height: 2rem;
outline: none;
background-image: url(${({ src }) => src});
background-size: cover;
background-position: center;
background-repeat: no-repeat;
`;
Loading

0 comments on commit 4e9edc3

Please sign in to comment.