Skip to content

feat: 모바일 버전 카테고리 선택하는 탭을 구현해요. - 1 #203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 22, 2025
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@vanilla-extract/css": "^1.17.0",
"@vanilla-extract/recipes": "^0.5.5",
"axios": "^1.6.8",
"clsx": "^2.1.1",
"country-flag-icons": "^1.5.13",
"date-fns": "^3.6.0",
"embla-carousel-autoplay": "^8.2.0",
Expand Down
1 change: 1 addition & 0 deletions packages/api/ku-key/.openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ models/get-friend-response-dto.ts
models/get-hot-club-response-dto.ts
models/get-my-comment-list-response-dto.ts
models/get-notice-response-dto.ts
models/get-nullable-timetable-response-dto.ts
models/get-point-history-response-dto.ts
models/get-post-list-response-dto.ts
models/get-post-list-with-board-response-dto.ts
Expand Down
14 changes: 12 additions & 2 deletions packages/api/ku-key/api/banner-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,14 @@ const bannerIdDeleteAxiosParamCreator = async (
* @summary 배너 이미지 생성
* @param {any} image 배너 이미지 파일
* @param {string} title 배너 제목
* @param {string} [link] 링크
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
const bannerPostAxiosParamCreator = async (
image: any,
title: string,
link?: string,
options: AxiosRequestConfig = {},
configuration?: Configuration,
): Promise<RequestArgs> => {
Expand All @@ -125,6 +127,10 @@ const bannerPostAxiosParamCreator = async (
localVarFormParams.append('title', title as any)
}

if (link !== undefined) {
localVarFormParams.append('link', link as any)
}

localVarHeaderParameter['Content-Type'] = 'multipart/form-data'

setSearchParams(localVarUrlObj, localVarQueryParameter)
Expand Down Expand Up @@ -175,16 +181,18 @@ const bannerIdDeleteFp = async (
* @summary 배너 이미지 생성
* @param {any} image 배너 이미지 파일
* @param {string} title 배너 제목
* @param {string} [link] 링크
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
const bannerPostFp = async (
image: any,
title: string,
link?: string,
options?: AxiosRequestConfig,
configuration?: Configuration,
): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<BannerDto>> => {
const localVarAxiosArgs = await bannerPostAxiosParamCreator(image, title, options, configuration)
const localVarAxiosArgs = await bannerPostAxiosParamCreator(image, title, link, options, configuration)
return createRequestFunction(localVarAxiosArgs, globalAxios, configuration)
}

Expand Down Expand Up @@ -246,6 +254,7 @@ export const bannerIdDelete = ({
export type BannerPostRequestParams = {
image: any
title: string
link?: string
options?: any
}

Expand All @@ -254,6 +263,7 @@ export type BannerPostRequestParams = {
* @summary 배너 이미지 생성
* @param {any} image 배너 이미지 파일
* @param {string} title 배너 제목
* @param {string} [link] 링크
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
Expand All @@ -267,7 +277,7 @@ export const bannerPost = ({
axios?: AxiosInstance
}) => {
return (params: BannerPostRequestParams): AxiosPromise<BannerDto> => {
return bannerPostFp(params.image, params.title, params.options, configuration).then(request =>
return bannerPostFp(params.image, params.title, params.link, params.options, configuration).then(request =>
request(axios, basePath),
)
}
Expand Down
8 changes: 4 additions & 4 deletions packages/api/ku-key/api/friendship-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import { DeleteFriendshipResponseDto } from '../models'
// @ts-ignore
import { GetFriendResponseDto } from '../models'
// @ts-ignore
import { GetReceivedFriendshipRequestCountDto } from '../models'
import { GetNullableTimetableResponseDto } from '../models'
// @ts-ignore
import { GetTimetableByTimetableIdDto } from '../models'
import { GetReceivedFriendshipRequestCountDto } from '../models'
// @ts-ignore
import { GetWaitingFriendResponseDto } from '../models'
// @ts-ignore
Expand Down Expand Up @@ -455,7 +455,7 @@ const friendshipFriendTimetableGetFp = async (
semester: string,
options?: AxiosRequestConfig,
configuration?: Configuration,
): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<GetTimetableByTimetableIdDto>>> => {
): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<GetNullableTimetableResponseDto>> => {
const localVarAxiosArgs = await friendshipFriendTimetableGetAxiosParamCreator(
username,
year,
Expand Down Expand Up @@ -652,7 +652,7 @@ export const friendshipFriendTimetableGet = ({
basePath?: string
axios?: AxiosInstance
}) => {
return (params: FriendshipFriendTimetableGetRequestParams): AxiosPromise<Array<GetTimetableByTimetableIdDto>> => {
return (params: FriendshipFriendTimetableGetRequestParams): AxiosPromise<GetNullableTimetableResponseDto> => {
return friendshipFriendTimetableGetFp(
params.username,
params.year,
Expand Down
6 changes: 3 additions & 3 deletions packages/api/ku-key/api/timetable-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { CreateTimetableCourseResponseDto } from '../models'
// @ts-ignore
import { CreateTimetableDto } from '../models'
// @ts-ignore
import { GetTimetableByTimetableIdDto } from '../models'
import { GetNullableTimetableResponseDto } from '../models'
// @ts-ignore
import { GetTimetableByUserIdResponseDto } from '../models'
// @ts-ignore
Expand Down Expand Up @@ -606,7 +606,7 @@ const timetableTimetableIdGetFp = async (
timetableId: number,
options?: AxiosRequestConfig,
configuration?: Configuration,
): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<GetTimetableByTimetableIdDto>> => {
): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<GetNullableTimetableResponseDto>> => {
const localVarAxiosArgs = await timetableTimetableIdGetAxiosParamCreator(timetableId, options, configuration)
return createRequestFunction(localVarAxiosArgs, globalAxios, configuration)
}
Expand Down Expand Up @@ -901,7 +901,7 @@ export const timetableTimetableIdGet = ({
basePath?: string
axios?: AxiosInstance
}) => {
return (params: TimetableTimetableIdGetRequestParams): AxiosPromise<GetTimetableByTimetableIdDto> => {
return (params: TimetableTimetableIdGetRequestParams): AxiosPromise<GetNullableTimetableResponseDto> => {
return timetableTimetableIdGetFp(params.timetableId, params.options, configuration).then(request =>
request(axios, basePath),
)
Expand Down
6 changes: 6 additions & 0 deletions packages/api/ku-key/models/banner-dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,10 @@ export interface BannerDto {
* @memberof BannerDto
*/
title: string
/**
* 배너 링크
* @type {string}
* @memberof BannerDto
*/
link: string | null
}
29 changes: 29 additions & 0 deletions packages/api/ku-key/models/get-nullable-timetable-response-dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* tslint:disable */
/* eslint-disable */
/**
* KU-KEY API
* API for KU-KEY service
*
* The version of the OpenAPI document: 1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/

import { GetTimetableByTimetableIdDto } from './get-timetable-by-timetable-id-dto'

/**
*
* @export
* @interface GetNullableTimetableResponseDto
*/
export interface GetNullableTimetableResponseDto {
/**
* 특정 시간표 정보
* @type {GetTimetableByTimetableIdDto}
* @memberof GetNullableTimetableResponseDto
*/
timetable: GetTimetableByTimetableIdDto | null
}
1 change: 1 addition & 0 deletions packages/api/ku-key/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export * from './get-friend-response-dto'
export * from './get-hot-club-response-dto'
export * from './get-my-comment-list-response-dto'
export * from './get-notice-response-dto'
export * from './get-nullable-timetable-response-dto'
export * from './get-point-history-response-dto'
export * from './get-post-list-response-dto'
export * from './get-post-list-with-board-response-dto'
Expand Down
2 changes: 1 addition & 1 deletion scripts/re-create-api-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ async function removeOperationId(filePath) {
}

// 스크립트 실행
await removeOperationId('https://15.164.27.130.nip.io/api-json')
await removeOperationId('https://dev.api.ku-key.devkor.club/api-json')
await execShellCommand(`yarn prettier --w "scripts/__generated__/ku-key-api.json"`)
7 changes: 5 additions & 2 deletions src/components/ui/profile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ const bgConfig: Record<CharacterType, string> = {
interface ProfileProps extends Pick<User, 'isAnonymous' | 'isDeleted' | 'character'> {
onlyTitle: boolean
bgWhite?: boolean
size?: number
}

const Profile = ({ isAnonymous, isDeleted, character, onlyTitle, bgWhite }: ProfileProps) => {
const Profile = ({ isAnonymous, isDeleted, character, onlyTitle, bgWhite, size = 20 }: ProfileProps) => {
const profileImg = characterConfig[character.type][character.level ?? 1]
const bgColor = bgConfig[character.type]

const w = size ?? (onlyTitle ? 15 : 20)
return (
<img
src={isDeleted ? Characters.CharacterDeleted : isAnonymous ? Characters.CharacterDefault : profileImg}
alt="Profile"
className={css({ w: onlyTitle ? 15 : 20, h: onlyTitle ? 15 : 20, rounded: 'full' })}
className={css({ w, h: w, rounded: 'full' })}
style={{ backgroundColor: bgWhite ? 'white' : bgColor }}
/>
)
Expand Down
152 changes: 152 additions & 0 deletions src/domain/Post/components/MobileFeedItem/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { useCallback, useMemo } from 'react'
import { LuBookmark, LuBookText, LuCookie, LuMessageCircle, LuMessageCircleQuestion, LuUsers } from 'react-icons/lu'
import { useNavigate } from 'react-router-dom'
import { match } from 'ts-pattern'

import * as s from './style.css'

import Profile from '@/components/ui/profile'
import { PostPreviewWithBoardName } from '@/packages/api/ku-key/models'
import { vars } from '@/theme/theme.css'
import { Typography } from '@/ui/Typography'

type Props = Pick<
PostPreviewWithBoardName,
| 'id'
| 'title'
| 'content'
| 'user'
| 'reactionCount'
| 'commentCount'
| 'scrapCount'
| 'commentCount'
| 'scrapCount'
| 'myScrap'
| 'thumbnailDir'
| 'boardName'
> & {
showCommunityBadge?: boolean
}
const MobileFeedItem = ({
id,
title,
content,
user,
reactionCount,
commentCount,
scrapCount,
myScrap,
thumbnailDir,
boardName,
showCommunityBadge,
}: Props) => {
const navigate = useNavigate()
const handleNavigate = useCallback(
() => navigate(`/community/${boardName.split(' ')[0].toLowerCase()}/post/${id}`),
[navigate, boardName, id],
)
const svg = useMemo(
() =>
match(boardName)
.with('Community Board', () => <LuUsers className={s.Icon} />)
.with('Question Board', () => <LuMessageCircleQuestion className={s.Icon} />)
.with('Information Board', () => <LuBookText className={s.Icon} />)
.otherwise(() => <LuBookText className={s.Icon} />),
[boardName],
)
return (
<div className={s.Wrapper} onClick={handleNavigate} role="button" tabIndex={0} onKeyDown={handleNavigate}>
<div className={s.BodyWrapper}>
{thumbnailDir && (
<div
className={s.Image}
style={{
backgroundImage: `url(${thumbnailDir})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
/>
)}
<div className={s.Text}>
{showCommunityBadge && (
<div className={s.Tag}>
{svg}
<Typography mobileTypography="miniTag1R" color="red3">
{boardName}
</Typography>
</div>
)}
<div className={s.TypoWrapper}>
<Typography
mobileTypography="headingM"
style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'pre-wrap',
display: '-webkit-box',
wordBreak: 'break-all',
width: '100%',
WebkitLineClamp: 1,
WebkitBoxOrient: 'vertical',
}}
>
{title}
</Typography>
</div>
<div className={s.TypoWrapper}>
<Typography
mobileTypography="bodyR"
color="darkGray1"
style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'pre-wrap',
display: '-webkit-box',
wordBreak: 'break-all',
width: '100%',
WebkitLineClamp: 2,
WebkitBoxOrient: 'vertical',
}}
>
{content}
</Typography>
</div>
</div>
</div>
<div className={s.FeedbackWrapper}>
<div className={s.Profile}>
<Profile onlyTitle={false} size={5} {...user} />
<Typography mobileTypography="miniTag1M" color="darkGray1">
{user.isAnonymous ? 'Anonymous' : user.username}
</Typography>
</div>
<div className={s.FeedBack}>
<div className={s.FeedBackIcon}>
<LuCookie size={16} />
<Typography mobileTypography="headingSB" color="darkGray2">
{reactionCount}
</Typography>
</div>
<div className={s.FeedBackIcon}>
<LuMessageCircle size={16} />
<Typography mobileTypography="headingSB" color="darkGray2">
{commentCount}
</Typography>
</div>
<div className={s.FeedBackIcon}>
<LuBookmark
size={16}
fill={myScrap ? vars.color.red2 : 'none'}
color={myScrap ? vars.color.red2 : 'darkGray2'}
/>
<Typography mobileTypography="headingSB" color="darkGray2">
{scrapCount}
</Typography>
</div>
</div>
</div>
</div>
)
}

export default MobileFeedItem
Loading