Skip to content

Commit

Permalink
Merge pull request #81 from EveryUniv/chore/79(이가은)
Browse files Browse the repository at this point in the history
chore: 게시판 개선
  • Loading branch information
gaeunnlee authored Mar 4, 2024
2 parents d872050 + 119893f commit f9fd6d8
Show file tree
Hide file tree
Showing 31 changed files with 316 additions and 142 deletions.
5 changes: 5 additions & 0 deletions src/api/upload/types/upload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface IFormInfo {
title: string;
body: string;
files: File[];
}
20 changes: 20 additions & 0 deletions src/api/upload/upload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { client } from 'api';
import { IFormInfo } from './types/upload';
import { CONSTANTS } from 'constants/api';

export const uploadForm = async ({ formInfo, API_PATH }: { formInfo: IFormInfo; API_PATH: string }) => {
const token = localStorage.getItem(CONSTANTS.atk_key);

try {
const data = await client.post<IFormInfo>(API_PATH, formInfo, {
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data',
},
});

return data;
} catch (e) {
console.log(e);
}
};
Binary file added src/assets/images/organization-01.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/organization-02.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/components/common/board/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ Board.Cell = function Cell({ children, className, ...props }: CellProps) {
return (
<li {...props}>
<Box
className={className + ' rounded-xl shadow-[2px_2px_5px_2px_#00000010] leading-8 cursor-pointer'}
padding='0'
border='border-none'
className={className + 'rounded-xl shadow-[2px_2px_5px_2px_#00000010] text-sm cursor-pointer'}
>
{children}
</Box>
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/carousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default function Carousel({ data }: { data: string[] }) {
const [index, setIndex] = useState(0);

return (
<div className='flex justify-center aspect-square overflow-hidden bg-gray-200 rounded-lg mt-2'>
<div className='relative flex justify-center aspect-square overflow-hidden bg-gray-200 rounded-lg mt-2'>
<ArrowButton type='previous' index={index} setIndex={setIndex} length={data.length} />
<img className='size-full object-cover' src={data[index]} />
<ArrowButton type='next' index={index} setIndex={setIndex} length={data.length} />
Expand Down
7 changes: 6 additions & 1 deletion src/components/common/gnh/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ interface GnhProps {

const Gnh = ({ heading, subHeading, headingStyle, headingText, subHeadingText }: GnhProps) => (
<div className={`${headingStyle}`}>
<h2 className={`${headingText} text-2xl font-extrabold text-white`}>{heading}</h2>
<h2
className={`${headingText} text-2xl font-extrabold text-white`}
style={headingText.indexOf('text-xl') !== -1 ? { fontSize: '1.25rem' } : {}}
>
{heading}
</h2>
{subHeading && <h3 className={`${subHeadingText} text-white`}>{subHeading}</h3>}
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions src/components/main/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export default function Menu() {
{ title: '조직도', path: ROUTES.COUNCIL.ORGANIZATION },
{ title: '오시는 길', path: ROUTES.COUNCIL.LOCATION },
{ title: '공지', path: ROUTES.NOTICE.ROOT },
{ title: '회의록', path: ROUTES.NOTICE.ROOT },
{ title: '회칙', path: ROUTES.NOTICE.ROOT },
{ title: '회의록', path: ROUTES.CONFERENCE.ROOT },
{ title: '회칙', path: ROUTES.RULE.ROOT },
{ title: '청원게시판', path: ROUTES.PETITION.ROOT },
],
},
Expand Down
19 changes: 4 additions & 15 deletions src/components/main/post.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, { ReactNode, useEffect } from 'react';
import React, { ReactNode } from 'react';
import TextEditor from 'components/common/editor/index';
import { ImageProps } from 'hooks/useImageUpload';
import { IFormInfo } from 'hooks/useFormUpload';
import FloatingButton from 'components/ui/button/FloatingButton';
import { useNavigate } from 'react-router-dom';
import PostBox from 'components/ui/box/PostBox';
import Title from 'components/ui/text/board';
import { FaCamera } from 'react-icons/fa';
import { IFormInfo } from 'api/upload/types/upload';

interface PostProps {
formInfo: IFormInfo;
Expand All @@ -29,13 +28,7 @@ export default function Post({
addImage,
deleteImage,
pageTitle,
navigateUrl,
}: PostProps) {
const navigate = useNavigate();
useEffect(() => {
console.log(imageList);
}, [imageList]);

return (
<form onSubmit={handleSubmit} encType='multipart/form-data' className='flex-col'>
<Box>
Expand All @@ -45,7 +38,7 @@ export default function Post({
id='title'
name='title'
value={formInfo.title}
placeholder='청원 제목을 입력해주세요'
placeholder='제목을 입력해주세요'
className='w-full focus:outline-0'
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setFormInfo((prev) => {
Expand Down Expand Up @@ -87,11 +80,7 @@ export default function Post({
</div>
))}
</Box>
<FloatingButton
event={() => {
navigate(navigateUrl);
}}
>
<FloatingButton event={() => {}}>
<p className='text-white'>Upload</p>
</FloatingButton>
</form>
Expand Down
8 changes: 4 additions & 4 deletions src/components/ui/box/PostBox.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { ComponentProps } from 'react';
import { LuPaperclip } from 'react-icons/lu';
import { PiPaperclipFill } from 'react-icons/pi';
import { IWithReactChildren } from 'shared/interfaces/default-interfaces';
interface IPostBox {
shadow?: boolean;
Expand All @@ -12,7 +12,7 @@ export default function PostBox({
}: IPostBox & IWithReactChildren & ComponentProps<'div'>) {
return (
<div
className={`p-4 bg-white rounded-lg m-5 leading-8 break-words transition-opacity animate-fadeIn shadow-[2px_2px_5px_2px_#00000010] ${
className={`p-4 bg-white rounded-lg leading-8 break-words transition-opacity animate-fadeIn shadow-[2px_2px_5px_2px_#00000010] ${
className ?? ''
}`}
{...props}
Expand Down Expand Up @@ -41,7 +41,7 @@ export function FileBox({
}: IFileBox & IWithReactChildren & ComponentProps<'div'>) {
return (
<div
className={`px-4 py-5 bg-white rounded-lg shadow-[2px_2px_5px_2px_#00000010] m-5 leading-5 transition-opacity animate-fadeIn ${
className={`text-sm px-4 py-5 bg-white rounded-lg shadow-[2px_2px_5px_2px_#00000010] leading-5 transition-opacity animate-fadeIn ${
className ?? ''
}`}
{...props}
Expand All @@ -55,7 +55,7 @@ export function FileBox({
rel='noopener noreferrer'
key={file.id}
>
<LuPaperclip size={30} />
<PiPaperclipFill style={{ fontSize: '20px' }} />
<span className='overflow-hidden text-ellipsis truncate'>{file.originalName}</span>
</a>
</>
Expand Down
23 changes: 17 additions & 6 deletions src/components/ui/box/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import React, { ComponentProps } from 'react';
import { IWithReactChildren } from 'shared/interfaces/default-interfaces';
import React from 'react';

interface BoxProps extends React.HTMLAttributes<HTMLDivElement> {
type?: 'shadow' | 'shadowImage';
padding?: string;
border?: string;
}

export default function Box({ children, className, type, padding, border, ...props }: BoxProps) {
const boxType = {
shadow: { boxShadow: '1px 1px 3px 0px rgba(0, 0, 0, 0.1)', border: 'none' },
shadowImage: { padding: '0', boxShadow: '1px 1px 3px 0px rgba(0, 0, 0, 0.1)' },
};

export default function Box({ children, className, ...props }: IWithReactChildren & ComponentProps<'div'>) {
return (
<div
className={`p-4 bg-white border border-gray-200 rounded-lg shadow-sm transition-opacity animate-fadeIn ${
className ?? ''
}`}
className={`p-${padding ?? 4} ${
border ?? 'border border-gray-200'
} bg-white rounded-lg transition-opacity animate-fadeIn overflow-hidden ${className ?? ''} `}
style={type && boxType[type]}
{...props}
>
{children}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/chart/PetitionChartList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default function PetitionChartList({
<span>
{idx + 1}. {item.department}
</span>
<span>({(item.agreeCount / sum) * 100}%)</span>
<span>({Math.floor((item.agreeCount / sum) * 100)}%)</span>
</li>
))}
</ol>
Expand Down
5 changes: 5 additions & 0 deletions src/constants/heading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ export const HeadingStyle = {
headingStyle: 'mb-[3px] text-center',
subHeadingStyle: 'text-center font-normal text-[11px]',
},
default: {
header: 'mt-4 py-5 px-7',
heading: 'text-xl mb-1',
subHeading: 'font-semibold',
},
};
19 changes: 19 additions & 0 deletions src/hooks/query/upload/mutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useMutation } from 'react-query';
import { useAlert } from 'hooks/useAlert';
import { uploadForm } from 'api/upload/upload';
import { useNavigate } from 'react-router-dom';

export const usePostFormUpload = (NAVIGATE_PATH: string) => {
const { alert } = useAlert();
const navigate = useNavigate();

return useMutation({
mutationFn: uploadForm,
onSuccess: (data) => {
if (data !== undefined && data.status === 200) {
navigate(NAVIGATE_PATH);
alert('완료');
}
},
});
};
41 changes: 21 additions & 20 deletions src/hooks/useFormUpload.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import React, { useEffect } from 'react';
import { useApi } from './useApi';
import React from 'react';
import { IFormInfo } from 'api/upload/types/upload';
import { usePostFormUpload } from './query/upload/mutation';
import { useAlert } from './useAlert';

export interface IFormInfo {
title: string;
body: string;
files: File[];
}

export const useFormUpload = (initFormInfo: IFormInfo, apiPath: string) => {
export const useFormUpload = ({
initFormInfo,
API_PATH,
NAVIGATE_PATH,
}: {
initFormInfo: IFormInfo;
API_PATH: string;
NAVIGATE_PATH: string;
}) => {
const [formInfo, setFormInfo] = React.useState<IFormInfo>(initFormInfo);
const { mutate } = usePostFormUpload(NAVIGATE_PATH);
const { alert } = useAlert();

const handleUpdate = (value: string) => {
const cleanedValue = value.replaceAll(/<\/?p[^>]*>/g, '').replace(/<br>/g, '');
Expand All @@ -17,9 +23,8 @@ export const useFormUpload = (initFormInfo: IFormInfo, apiPath: string) => {
body: cleanedValue,
});
};
const { post } = useApi();

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData();
formData.append('title', formInfo.title);
Expand All @@ -29,17 +34,13 @@ export const useFormUpload = (initFormInfo: IFormInfo, apiPath: string) => {
formData.append('files', file);
}
}
post<IFormInfo, number>(apiPath, formInfo, {
authenticate: true,
contentType: 'multipart/form-data',
log: true,
});
if (formInfo.title.length > 0 && formInfo.body.length > 0) {
mutate({ formInfo, API_PATH });
} else {
alert('제목과 내용을 입력해주세요');
}
};

useEffect(() => {
console.log(initFormInfo);
}, [initFormInfo]);

return {
formInfo,
setFormInfo,
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useImageUpload.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IFormInfo } from 'api/upload/types/upload';
import React, { useEffect } from 'react';
import { IFormInfo } from './useFormUpload';

export interface ImageProps {
add: {
Expand Down
1 change: 1 addition & 0 deletions src/layouts/BoardLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface IBoardList {
expiresAt?: string;
agreeCount?: string;
blinded: string;
images?: [{ id: number; url: string; originalName: string; mimeType: string; thumbnailUrl: string }];
}

export default function BoardLayout({
Expand Down
10 changes: 10 additions & 0 deletions src/layouts/PostDetailLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React, { ComponentProps } from 'react';
import { IWithReactChildren } from 'shared/interfaces/default-interfaces';

export default function PostDetailLayout({ children, ...props }: IWithReactChildren & ComponentProps<'div'>) {
return (
<div className='p-5 flex flex-col gap-5' {...props}>
{children}
</div>
);
}
10 changes: 10 additions & 0 deletions src/layouts/SinglePageLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React, { ComponentProps } from 'react';
import { IWithReactChildren } from 'shared/interfaces/default-interfaces';

export default function SinglePageLayout({ children, ...props }: IWithReactChildren & ComponentProps<'div'>) {
return (
<div className='p-3 flex flex-col gap-5' {...props}>
{children}
</div>
);
}
25 changes: 23 additions & 2 deletions src/pages/conference/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
import Title, { Date } from 'components/ui/text/board';
import { API_PATH, CONSTANTS } from 'constants/api';
import { HeadingStyle } from 'constants/heading';
import { useEffectOnce } from 'hooks/useEffectOnce';
import { useLayout } from 'hooks/useLayout';
import BoardLayout, { IBoardList } from 'layouts/BoardLayout';
import React from 'react';

export default function ConferenceBoard() {
const { setLayout } = useLayout();

useEffectOnce(() => {
setLayout({
title: '총학생회',
backButton: true,
isMain: false,
fullscreen: false,
heading: '총학생회',
subHeading: '회의록',
headingStyle: HeadingStyle.default.header,
headingText: HeadingStyle.default.heading,
subHeadingText: HeadingStyle.default.subHeading,
margin: '',
rounded: true,
});
});

const Cell = ({ data }: { data: IBoardList }) => (
<div className='flex gap-2'>
<div className='flex gap-2 p-3'>
<Title content={data.title} className='grow text-center truncate' />
<Date content={data.createdAt} />
<Date content={data.createdAt} className='font-semibold' />
</div>
);
return (
Expand Down
Loading

0 comments on commit f9fd6d8

Please sign in to comment.