From e6b65e7e17bb42d550426180708f9497c98aa85c Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Tue, 11 Jun 2024 16:15:38 +0900 Subject: [PATCH 01/17] =?UTF-8?q?feat=20=EA=B8=80=EC=93=B0=EA=B8=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/{addboard.tsx => addboard/index.tsx} | 0 src/api/api.ts | 31 ++++++++++---- src/api/axios.ts | 2 +- src/components/AddBoardContainer.tsx | 30 ++++++++++---- src/components/AddBoardForm.tsx | 48 ++++++++++++++-------- src/components/BestPostsContainer.tsx | 1 - src/components/Post.tsx | 15 +++++-- src/components/TotalPostsContainer.tsx | 1 + styles/AddBoardForm.module.css | 28 +++++++++++-- styles/Post.module.css | 1 + 10 files changed, 115 insertions(+), 42 deletions(-) rename pages/{addboard.tsx => addboard/index.tsx} (100%) diff --git a/pages/addboard.tsx b/pages/addboard/index.tsx similarity index 100% rename from pages/addboard.tsx rename to pages/addboard/index.tsx diff --git a/src/api/api.ts b/src/api/api.ts index 9c4502941..c7dc651a1 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -3,7 +3,7 @@ import instance from './axios'; import { articlesType, writingType } from './apiType'; import { url } from 'inspector'; import Cookies from 'js-cookie'; -import { form } from '../components/AddBoardForm'; +import { formType } from '../components/AddBoardForm'; import { title } from 'process'; export const getBestPosts = async (params: string): Promise => { @@ -39,7 +39,7 @@ export const getTotalPosts = async (params: string): Promise => { throw error; } }; -export const tempSignUP = async () => { +export const tempSignIn = async () => { const TEMP_URL = '/auth/signIn'; try { if (!Cookies.get('accessToken')) { @@ -59,7 +59,11 @@ export const postImage = async (image: File | null) => { try { if (image) { - const response = await instance.post(URL, { image: image }); + const response = await instance.post( + URL, + { image: image }, + { headers: { 'Content-Type': 'multipart/form-data' } } + ); const imageUrl = response.data.url; return imageUrl; } @@ -67,14 +71,23 @@ export const postImage = async (image: File | null) => { } catch (error) {} }; -export const postArticles = async (formData: form, imageUrl: string) => { +export const postArticles = async (formData: formType, imageUrl: string) => { const URL = '/articles'; try { - const response = await instance.post(URL, { - image: imageUrl, - content: formData.content, - title: formData.title, - }); + const response = await instance.post( + URL, + { + image: imageUrl, + content: formData.content, + title: formData.title, + }, + { + headers: { + 'Content-Type': 'application/json', + accept: 'application/json', + }, + } + ); } catch (error) {} }; diff --git a/src/api/axios.ts b/src/api/axios.ts index 94c9f3265..27899d752 100644 --- a/src/api/axios.ts +++ b/src/api/axios.ts @@ -11,7 +11,7 @@ const instance = axios.create({ instance.interceptors.request.use( (config: InternalAxiosRequestConfig) => { - const token = Cookies.get('token'); + const token = Cookies.get('accessToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } diff --git a/src/components/AddBoardContainer.tsx b/src/components/AddBoardContainer.tsx index bc2bd6918..4ec78c764 100644 --- a/src/components/AddBoardContainer.tsx +++ b/src/components/AddBoardContainer.tsx @@ -1,15 +1,24 @@ +import { useRouter } from 'next/router'; import React, { ChangeEvent, useEffect, useState } from 'react'; -import { postArticles, postImage, tempSignUP } from '../api/api'; +import { postArticles, postImage, tempSignIn } from '../api/api'; import AddBoardForm from './AddBoardForm'; -import { form } from './AddBoardForm'; +import { formType } from './AddBoardForm'; const AddBoardContainer = () => { - const [formData, setFormData] = useState
({ + const routes = useRouter(); + const [previewImage, setPreviewImage] = useState(''); + const [formData, setFormData] = useState({ title: '', content: '', image: null, }); + const onCancelHandler = (e: React.MouseEvent) => { + URL.revokeObjectURL(previewImage); + setPreviewImage(''); + setFormData((prev) => ({ ...prev, ['image']: null })); + }; + const onChangeHandler = (e: ChangeEvent) => { if (e.target.name === 'title') { setFormData((prev) => ({ ...prev, ['title']: e.target.value })); @@ -17,26 +26,31 @@ const AddBoardContainer = () => { setFormData((prev) => ({ ...prev, ['content']: e.target.value })); } else if (e.target.name === 'image') { const file = e.target.files?.[0]; - if (file) setFormData((prev) => ({ ...prev, ['image']: file })); + if (file) { + setFormData((prev) => ({ ...prev, ['image']: file })); + const objectURL = URL.createObjectURL(file); + setPreviewImage(objectURL); + } } }; const onSubmitHandler = async (e: React.FormEvent) => { e.preventDefault(); const url = await postImage(formData.image); - console.log(url); - - // postArticles(formData, url); + const result = await postArticles(formData, url); + routes.push('/boards'); }; useEffect(() => { - tempSignUP(); + tempSignIn(); }, []); return ( <> diff --git a/src/components/AddBoardForm.tsx b/src/components/AddBoardForm.tsx index 62186af35..c42a813ea 100644 --- a/src/components/AddBoardForm.tsx +++ b/src/components/AddBoardForm.tsx @@ -1,20 +1,24 @@ import React, { ChangeEvent } from 'react'; import style from '@/styles/AddBoardForm.module.css'; -export interface form { +export interface formType { title: string; content: string; image: File | null; } interface AddBoardFormProps { - formData: form; + formData: formType; + previewImage: string; + onCancelHandler: (e: React.MouseEvent) => void; onChangeHandler: (e: ChangeEvent) => void; onSubmitHandler: (e: React.FormEvent) => void; } const AddBoardForm = ({ formData, + previewImage, onChangeHandler, onSubmitHandler, + onCancelHandler, }: AddBoardFormProps) => { return ( @@ -38,7 +42,6 @@ const AddBoardForm = ({ className={style.titleInput} placeholder='제목을 입력해주세요' /> -

*내용

이미지

- - - +
+ + {previewImage && ( +
+
+ X +
+ 미리보기이미지 +
+ )} + +
); }; diff --git a/src/components/BestPostsContainer.tsx b/src/components/BestPostsContainer.tsx index 3345f87c9..4566ff4c2 100644 --- a/src/components/BestPostsContainer.tsx +++ b/src/components/BestPostsContainer.tsx @@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react'; import BestPosts from './BestPosts'; import { writingType } from '../api/apiType'; -const URL = 'page=1&pageSize=3&orderBy=like'; const BestPostsContainer = ({ bestPosts }: { bestPosts: writingType[] }) => { return ; }; diff --git a/src/components/Post.tsx b/src/components/Post.tsx index ef88420cf..d96645115 100644 --- a/src/components/Post.tsx +++ b/src/components/Post.tsx @@ -3,6 +3,7 @@ import style from '@/styles/Post.module.css'; import profile from '@/src/img/profile.png'; import heart from '@/src/img/heart.png'; import { convertTime } from '../util/convertTime'; +import Link from 'next/link'; interface postItem { image: string | null; @@ -10,12 +11,20 @@ interface postItem { likeCount: number; nickName: string; createdAt: string; + id: number; } -const Post = ({ image, content, likeCount, nickName, createdAt }: postItem) => { +const Post = ({ + image, + content, + likeCount, + nickName, + createdAt, + id, +}: postItem) => { const contentDate = convertTime(createdAt); return ( -
+

{content}

{image ? ( @@ -39,7 +48,7 @@ const Post = ({ image, content, likeCount, nickName, createdAt }: postItem) => {

{likeCount}+

- + ); }; diff --git a/src/components/TotalPostsContainer.tsx b/src/components/TotalPostsContainer.tsx index 414eb3bde..ffa77d24b 100644 --- a/src/components/TotalPostsContainer.tsx +++ b/src/components/TotalPostsContainer.tsx @@ -35,6 +35,7 @@ const TotalPostsContainer = () => { {posts.map((element) => ( Date: Thu, 13 Jun 2024 18:08:03 +0900 Subject: [PATCH 02/17] =?UTF-8?q?feat=20=EC=83=81=EC=84=B8=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20ssr=EB=A1=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/{addboard/index.tsx => addboard.tsx} | 0 pages/addboard/[id].tsx | 7 ----- pages/board/[id].tsx | 30 ++++++++++++++++++++ pages/boards.tsx | 3 +- src/api/api.ts | 22 +++++++++++++-- src/api/apiType.ts | 32 +++++++++++----------- src/components/AddBoardForm.tsx | 6 +++- src/components/Post.tsx | 2 +- src/components/TotalPosts.tsx | 2 +- src/components/boardContainer.tsx | 7 +++++ styles/AddBoardForm.module.css | 8 +++++- styles/Post.module.css | 7 +++-- 12 files changed, 92 insertions(+), 34 deletions(-) rename pages/{addboard/index.tsx => addboard.tsx} (100%) delete mode 100644 pages/addboard/[id].tsx create mode 100644 pages/board/[id].tsx create mode 100644 src/components/boardContainer.tsx diff --git a/pages/addboard/index.tsx b/pages/addboard.tsx similarity index 100% rename from pages/addboard/index.tsx rename to pages/addboard.tsx diff --git a/pages/addboard/[id].tsx b/pages/addboard/[id].tsx deleted file mode 100644 index dd186363f..000000000 --- a/pages/addboard/[id].tsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from 'react'; - -const addboard = () => { - return
; -}; - -export default addboard; diff --git a/pages/board/[id].tsx b/pages/board/[id].tsx new file mode 100644 index 000000000..307151f80 --- /dev/null +++ b/pages/board/[id].tsx @@ -0,0 +1,30 @@ +import { articleType } from '@/src/api/apiType'; +import { GetServerSideProps } from 'next'; +import { AxiosError } from 'axios'; +import React from 'react'; +import { getArticle } from '@/src/api/api'; +import { useRouter } from 'next/router'; +interface articleProps { + article: articleType; +} +const board: React.FC = ({ article }) => { + return
; +}; + +export const getServerSideProps: GetServerSideProps = async ( + context +) => { + const { id } = context.query; + + try { + const article = await getArticle(id as string); + return { + props: { article }, + }; + } catch (error) { + const err = error as AxiosError; + throw err; + } +}; +export default board; + diff --git a/pages/boards.tsx b/pages/boards.tsx index fef804d03..f2e98a232 100644 --- a/pages/boards.tsx +++ b/pages/boards.tsx @@ -18,7 +18,8 @@ const boards: React.FC = ({ bestPosts }) => { ); }; -export const getServerSideProps: GetServerSideProps = async () => { + +export const getServerSideProps: GetServerSideProps = async() => { const URL = 'page=1&pageSize=3&orderBy=like'; try { const bestPosts = await getBestPosts(URL); diff --git a/src/api/api.ts b/src/api/api.ts index c7dc651a1..667fbb10b 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -1,10 +1,8 @@ import axios, { AxiosError, AxiosResponse } from 'axios'; import instance from './axios'; -import { articlesType, writingType } from './apiType'; -import { url } from 'inspector'; +import { articlesType, articleType, writingType } from './apiType'; import Cookies from 'js-cookie'; import { formType } from '../components/AddBoardForm'; -import { title } from 'process'; export const getBestPosts = async (params: string): Promise => { const URL = `/articles?${params}`; @@ -91,3 +89,21 @@ export const postArticles = async (formData: formType, imageUrl: string) => { } catch (error) {} }; +export const getArticle = async (articleId: string): Promise => { + const URL = `/articles/${articleId}`; + try { + const response: AxiosResponse = await instance.get(URL); + const articleData = response.data; + return articleData; + } catch (error) { + const err = error as AxiosError; + if (err.response) { + console.error('Response error:', err.response.status); + console.error('Response data:', err.response.data); + throw err; + } + console.error(error); + throw error; + } +}; + diff --git a/src/api/apiType.ts b/src/api/apiType.ts index a33dbe2f8..262bda0b0 100644 --- a/src/api/apiType.ts +++ b/src/api/apiType.ts @@ -1,20 +1,6 @@ -export interface articlesType { +export interface articlesType extends articleType { totalCount?: number; - list: [ - { - updatedAt: string; - createdAt: string; - likeCount: number; - writer: { - nickname: string; - id: number; - }; - image: string | null; - content: string; - title: string; - id: number; - } - ]; + list: [articleType]; } export interface writingType { @@ -31,3 +17,17 @@ export interface writingType { id: number; } +export interface articleType { + updatedAt: string; + createdAt: string; + likeCount: number; + writer: { + nickname: string; + id: number; + }; + image: string | null; + content: string; + title: string; + id: number; +} + diff --git a/src/components/AddBoardForm.tsx b/src/components/AddBoardForm.tsx index c42a813ea..123ff47b6 100644 --- a/src/components/AddBoardForm.tsx +++ b/src/components/AddBoardForm.tsx @@ -27,7 +27,11 @@ const AddBoardForm = ({ diff --git a/src/components/Post.tsx b/src/components/Post.tsx index d96645115..2fd27c911 100644 --- a/src/components/Post.tsx +++ b/src/components/Post.tsx @@ -24,7 +24,7 @@ const Post = ({ }: postItem) => { const contentDate = convertTime(createdAt); return ( - +

{content}

{image ? ( diff --git a/src/components/TotalPosts.tsx b/src/components/TotalPosts.tsx index bc57d539a..0f85b0b8d 100644 --- a/src/components/TotalPosts.tsx +++ b/src/components/TotalPosts.tsx @@ -8,7 +8,7 @@ const TotalPosts = () => {

게시글

- + 글쓰기
diff --git a/src/components/boardContainer.tsx b/src/components/boardContainer.tsx new file mode 100644 index 000000000..ccfb81246 --- /dev/null +++ b/src/components/boardContainer.tsx @@ -0,0 +1,7 @@ +import React, { useEffect } from 'react'; + +const boardContainer = () => { + return
; +}; + +export default boardContainer; diff --git a/styles/AddBoardForm.module.css b/styles/AddBoardForm.module.css index ed6af35ae..9576d4010 100644 --- a/styles/AddBoardForm.module.css +++ b/styles/AddBoardForm.module.css @@ -23,11 +23,17 @@ height: 42px; border-radius: 8px; border: none; - background-color: #9ca3af; + font-weight: 600; font-size: 16px; color: #ffffff; } +.ableBtn { + background-color: #3692ff; +} +.disableBtn { + background-color: #9ca3af; +} .titleInput { margin-top: 10px; width: 100%; diff --git a/styles/Post.module.css b/styles/Post.module.css index 1199cb293..a04d657ed 100644 --- a/styles/Post.module.css +++ b/styles/Post.module.css @@ -1,20 +1,21 @@ .postFrame { margin-bottom: 30px; height: 112px; - border-bottom: 1px solid #e5e7eb; + text-decoration: none; } + .contentFrame { display: flex; justify-content: space-between; + padding-bottom: 5px; + border-bottom: 1px solid #e5e7eb; } - .content { font-weight: 600; font-size: 20px; color: #1f2937; } - .contentImage { width: 72px; height: 72px; From 5df14a38aa9584b208ba0501e4f2394dfa365c40 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Fri, 14 Jun 2024 17:08:01 +0900 Subject: [PATCH 03/17] =?UTF-8?q?feat=20=EB=8C=93=EA=B8=80=20=EB=B6=88?= =?UTF-8?q?=EB=9F=AC=EC=98=A4=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/board/[id].tsx | 3 +- src/api/api.ts | 31 +++++++- src/api/apiType.ts | 17 +++++ src/components/Board.tsx | 40 ++++++++++ src/components/Comment.tsx | 38 +++++++++ src/components/CommentContainer.tsx | 37 +++++++++ src/components/CommentInput.tsx | 17 +++++ src/components/Post.tsx | 6 +- src/components/TotalPostsContainer.tsx | 6 +- src/img/kebab.png | Bin 0 -> 188 bytes src/util/getCreatedTime.ts | 11 +++ styles/Board.module.css | 102 +++++++++++++++++++++++++ styles/Comment.module.css | 43 +++++++++++ styles/CommentInput.module.css | 29 +++++++ styles/Post.module.css | 8 +- 15 files changed, 379 insertions(+), 9 deletions(-) create mode 100644 src/components/Board.tsx create mode 100644 src/components/Comment.tsx create mode 100644 src/components/CommentContainer.tsx create mode 100644 src/components/CommentInput.tsx create mode 100644 src/img/kebab.png create mode 100644 src/util/getCreatedTime.ts create mode 100644 styles/Board.module.css create mode 100644 styles/Comment.module.css create mode 100644 styles/CommentInput.module.css diff --git a/pages/board/[id].tsx b/pages/board/[id].tsx index 307151f80..2ab8294e7 100644 --- a/pages/board/[id].tsx +++ b/pages/board/[id].tsx @@ -4,11 +4,12 @@ import { AxiosError } from 'axios'; import React from 'react'; import { getArticle } from '@/src/api/api'; import { useRouter } from 'next/router'; +import Board from '@/src/components/Board'; interface articleProps { article: articleType; } const board: React.FC = ({ article }) => { - return
; + return ; }; export const getServerSideProps: GetServerSideProps = async ( diff --git a/src/api/api.ts b/src/api/api.ts index 667fbb10b..93895285c 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -1,6 +1,12 @@ import axios, { AxiosError, AxiosResponse } from 'axios'; import instance from './axios'; -import { articlesType, articleType, writingType } from './apiType'; +import { + articlesType, + articleType, + commentsType, + commentType, + writingType, +} from './apiType'; import Cookies from 'js-cookie'; import { formType } from '../components/AddBoardForm'; @@ -107,3 +113,26 @@ export const getArticle = async (articleId: string): Promise => { } }; +export const getComments = async ( + articleId: string, + limit: number, + cursor?: number +): Promise<[commentType]> => { + const URL = `/articles/${articleId}/comments?limit=${limit}${ + cursor ? `&cursor=${cursor}` : '' + }`; + try { + const response: AxiosResponse = await instance.get(URL); + return response.data.list; + } catch (error) { + const err = error as AxiosError; + if (err.response) { + console.error('Response error:', err.response.status); + console.error('Response data:', err.response.data); + throw err; + } + console.error(error); + throw error; + } +}; + diff --git a/src/api/apiType.ts b/src/api/apiType.ts index 262bda0b0..22c32d170 100644 --- a/src/api/apiType.ts +++ b/src/api/apiType.ts @@ -31,3 +31,20 @@ export interface articleType { id: number; } +export interface commentsType extends commentType { + list: [commentType]; + nextCursor: number; +} + +export interface commentType { + id: number; + content: string; + createdAt: string; + updatedAt: string; + writer: { + id: number; + nickname: string; + image: string | null; + }; +} + diff --git a/src/components/Board.tsx b/src/components/Board.tsx new file mode 100644 index 000000000..547c8e80b --- /dev/null +++ b/src/components/Board.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import style from '@/styles/Board.module.css'; +import { articleType } from '../api/apiType'; +import kebab from '@/src/img/kebab.png'; +import profile from '@/src/img/profile.png'; +import heart from '@/src/img/heart.png'; +import { convertTime } from '../util/convertTime'; +import CommentContainer from './CommentContainer'; + +const Board = ({ article }: { article: articleType }) => { + const createdAt = convertTime(article.createdAt); + + return ( +
+
+

{article.title}

+ +
+ +
+ 프로필이미지 +

{article.writer.nickname}

+

{createdAt}

+ 좋아요 +

{article.likeCount}

+
+

{article.content}

+ +
+ ); +}; + +export default Board; + diff --git a/src/components/Comment.tsx b/src/components/Comment.tsx new file mode 100644 index 000000000..bb712b0f5 --- /dev/null +++ b/src/components/Comment.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import kebab from '@/src/img/kebab.png'; +import profile from '@/src/img/profile.png'; +import style from '@/styles/Comment.module.css'; +import { getCreatedTime } from '../util/getCreatedTime'; +interface commentProps { + content: string; + image: string | null; + nickName: string; + createdAt: string; +} +const Comment = ({ content, image, nickName, createdAt }: commentProps) => { + const { day, hours } = getCreatedTime(createdAt); + return ( +
+
+

{content}

+ +
+
+ 프로필 +
+

{nickName}

+

{`${day}일 ${hours}시간 전`}

+
+
+
+ ); +}; + +export default Comment; + diff --git a/src/components/CommentContainer.tsx b/src/components/CommentContainer.tsx new file mode 100644 index 000000000..bda7c321c --- /dev/null +++ b/src/components/CommentContainer.tsx @@ -0,0 +1,37 @@ +import { useRouter } from 'next/router'; +import React, { useEffect, useState } from 'react'; +import { getComments } from '../api/api'; +import { commentsType, commentType } from '../api/apiType'; +import Comment from './Comment'; +import CommentInput from './CommentInput'; + +const CommentContainer = () => { + const router = useRouter(); + const [comments, setComments] = useState<[commentType] | []>([]); + const id = router.query['id']; + const saveComment = async () => { + try { + const result = await getComments(id as string, 5); + setComments(result); + } catch (error) {} + }; + useEffect(() => { + saveComment(); + }, []); + return ( + <> + + {comments.map((element) => ( + + ))} + + ); +}; + +export default CommentContainer; + diff --git a/src/components/CommentInput.tsx b/src/components/CommentInput.tsx new file mode 100644 index 000000000..74dbe2435 --- /dev/null +++ b/src/components/CommentInput.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import style from '@/styles/CommentInput.module.css'; +const CommentInput = () => { + return ( +
+

댓글 달기

+ + +
+ ); +}; + +export default CommentInput; + diff --git a/src/components/Post.tsx b/src/components/Post.tsx index 2fd27c911..d060b3bc7 100644 --- a/src/components/Post.tsx +++ b/src/components/Post.tsx @@ -12,6 +12,7 @@ interface postItem { nickName: string; createdAt: string; id: number; + onClickHandler: (id: number) => void; } const Post = ({ @@ -21,10 +22,11 @@ const Post = ({ nickName, createdAt, id, + onClickHandler, }: postItem) => { const contentDate = convertTime(createdAt); return ( - +
onClickHandler(id)}>

{content}

{image ? ( @@ -48,7 +50,7 @@ const Post = ({

{likeCount}+

- +
); }; diff --git a/src/components/TotalPostsContainer.tsx b/src/components/TotalPostsContainer.tsx index ffa77d24b..47d383a5c 100644 --- a/src/components/TotalPostsContainer.tsx +++ b/src/components/TotalPostsContainer.tsx @@ -8,7 +8,6 @@ export const URL = `page=1&pageSize=5`; const TotalPostsContainer = () => { const router = useRouter(); const { orderBy, keyword } = router.query; - const [posts, setPosts] = useState([]); const getPosts = async () => { if (orderBy) { @@ -27,6 +26,10 @@ const TotalPostsContainer = () => { } } }; + + const onClickHandler = (id: number) => { + router.push(`/board/${id}`); + }; useEffect(() => { getPosts(); }, [orderBy, keyword]); @@ -34,6 +37,7 @@ const TotalPostsContainer = () => { <> {posts.map((element) => ( U6<8+ci z=R`Qq1QU@5*DpM<2x8cEZ~4zTMIYB*GjKW>DXcnEo~!srm3yPfVr_;;dP2GN>~cRD dZHz85%1+WS{j~aw?H-`v44$rjF6*2Ung9%@H_`wA literal 0 HcmV?d00001 diff --git a/src/util/getCreatedTime.ts b/src/util/getCreatedTime.ts new file mode 100644 index 000000000..ce110c3c2 --- /dev/null +++ b/src/util/getCreatedTime.ts @@ -0,0 +1,11 @@ +export const getCreatedTime = (date: string) => { + const now = new Date(); + const before = new Date(date); + const time = now.getTime() - before.getTime(); + const timeDifferenceInSeconds = Math.floor(time / 1000); + // 초를 시, 분, 초로 변환 + const day = Math.floor(timeDifferenceInSeconds / 86400); + const hours = Math.floor((timeDifferenceInSeconds % 86400) / 3600); + return { day: day, hours: hours }; +}; + diff --git a/styles/Board.module.css b/styles/Board.module.css new file mode 100644 index 000000000..b0d7754b7 --- /dev/null +++ b/styles/Board.module.css @@ -0,0 +1,102 @@ +.boardFrame { + margin: 0px auto; + width: 1200px; +} +.articleFrame { + margin-top: 30px; + display: flex; + justify-content: space-between; + align-items: center; +} +.title { + font-weight: 700; + font-size: 20px; + color: #1f2937; +} +.kebabImage { + width: 24px; + height: 24px; +} +.kebabButton { + cursor: pointer; + background-color: #ffffffff; + border: none; + width: 24px; + height: 24px; +} +.boardDataFrame { + margin-top: 10px; + display: flex; + align-items: center; + gap: 5px; + padding-bottom: 10px; + border-bottom: 1px solid #e5e7eb; +} +.profileImage { + width: 24px; + height: 24px; +} +.nickName { + font-weight: 400; + font-size: 14px; + color: #4b5563; +} +.createdAt { + font-weight: 400; + font-size: 12px; + color: #9ca3af; +} +.likeImage { + width: 24px; + height: 24px; +} +.likeCount { + font-weight: 400; + font-size: 14px; + color: #6b7280; +} +.content { + margin-top: 15px; + font-weight: 400; + font-size: 16px; + color: #1f2937; +} +.commentFrame { + margin-top: 50px; + gap: 10px; + display: flex; + flex-direction: column; +} +.comment { + font-weight: 600; + font-size: 16px; + color: #111827; +} +.commentInput { + height: 104px; + border: none; + border-radius: 12px; + background-color: #f3f4f6; +} +.registerButton { + align-self: flex-end; + width: 74px; + height: 42px; + border-radius: 8px; + cursor: pointer; + background-color: #9ca3af; + color: #ffffffff; + border: none; +} +@media (max-width: 1199px) { + .boardFrame { + width: 696px; + } +} + +@media (max-width: 769px) { + .boardFrame { + width: 343px; + } +} + diff --git a/styles/Comment.module.css b/styles/Comment.module.css new file mode 100644 index 000000000..c862933dd --- /dev/null +++ b/styles/Comment.module.css @@ -0,0 +1,43 @@ +.commentFrame { + margin-top: 10px; + height: 97px; + border-bottom: 1px solid #e5e7eb; +} +.contentFrame { + display: flex; + justify-content: space-between; +} +.kebabButton { + cursor: pointer; + background-color: #ffffff; + border: none; +} +.kebabImage { + width: 24px; + height: 24px; +} +.content { + font-weight: 400; + font-size: 14px; + color: #1f2937; +} +.userInfoFrame { + display: flex; + gap: 4px; + align-items: center; +} +.profile { + width: 32px; + height: 32px; +} +.nickName { + font-weight: 400; + font-size: 12px; + color: #4b5563; +} +.createdAt { + font-weight: 400; + font-size: 12px; + color: #9ca3af; +} + diff --git a/styles/CommentInput.module.css b/styles/CommentInput.module.css new file mode 100644 index 000000000..2c639040b --- /dev/null +++ b/styles/CommentInput.module.css @@ -0,0 +1,29 @@ +.commentFrame { + margin-top: 50px; + gap: 10px; + display: flex; + flex-direction: column; + margin-bottom: 50px; +} +.comment { + font-weight: 600; + font-size: 16px; + color: #111827; +} +.commentInput { + height: 104px; + border: none; + border-radius: 12px; + background-color: #f3f4f6; +} +.registerButton { + align-self: flex-end; + width: 74px; + height: 42px; + border-radius: 8px; + cursor: pointer; + background-color: #9ca3af; + color: #ffffffff; + border: none; +} + diff --git a/styles/Post.module.css b/styles/Post.module.css index a04d657ed..818f81d4c 100644 --- a/styles/Post.module.css +++ b/styles/Post.module.css @@ -1,15 +1,15 @@ .postFrame { + cursor: pointer; margin-bottom: 30px; height: 112px; - text-decoration: none; + border-bottom: 1px solid #e5e7eb; } .contentFrame { display: flex; justify-content: space-between; padding-bottom: 5px; - border-bottom: 1px solid #e5e7eb; } .content { font-weight: 600; @@ -31,9 +31,9 @@ } .userInfo { - width: 180px; + width: 200px; display: flex; - justify-content: space-around; + justify-content: space-between; align-items: center; } .userInfo .profileImage { From ba99ad648ae2b26f347db779c1924b50110143b7 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Fri, 14 Jun 2024 17:25:00 +0900 Subject: [PATCH 04/17] =?UTF-8?q?feat=20noComment=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CommentContainer.tsx | 23 +++++++++++++++-------- src/components/NoComment.tsx | 11 +++++++++++ src/img/noComment.png | Bin 0 -> 5874 bytes styles/NoComment.module.css | 5 +++++ 4 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 src/components/NoComment.tsx create mode 100644 src/img/noComment.png create mode 100644 styles/NoComment.module.css diff --git a/src/components/CommentContainer.tsx b/src/components/CommentContainer.tsx index bda7c321c..b710a58c2 100644 --- a/src/components/CommentContainer.tsx +++ b/src/components/CommentContainer.tsx @@ -4,6 +4,7 @@ import { getComments } from '../api/api'; import { commentsType, commentType } from '../api/apiType'; import Comment from './Comment'; import CommentInput from './CommentInput'; +import NoComment from './NoComment'; const CommentContainer = () => { const router = useRouter(); @@ -18,17 +19,23 @@ const CommentContainer = () => { useEffect(() => { saveComment(); }, []); + console.log(comments); + return ( <> - {comments.map((element) => ( - - ))} + {comments.length !== 0 ? ( + comments.map((element) => ( + + )) + ) : ( + + )} ); }; diff --git a/src/components/NoComment.tsx b/src/components/NoComment.tsx new file mode 100644 index 000000000..b201545c9 --- /dev/null +++ b/src/components/NoComment.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import noComment from '@/src/img/noComment.png'; +import style from '@/styles/NoComment.module.css'; +const NoComment = () => { + return ( + 댓글 없음 + ); +}; + +export default NoComment; + diff --git a/src/img/noComment.png b/src/img/noComment.png new file mode 100644 index 0000000000000000000000000000000000000000..428167b33e0166242649cd16951663d63d561483 GIT binary patch literal 5874 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 J{ZOz9`!A*iH-rEH literal 0 HcmV?d00001 diff --git a/styles/NoComment.module.css b/styles/NoComment.module.css new file mode 100644 index 000000000..eca82a7f0 --- /dev/null +++ b/styles/NoComment.module.css @@ -0,0 +1,5 @@ +.noComment { + margin: 0 auto; + display: block; +} + From a9f7bcce9209e78ecd74102b6f9b4c257cb206cb Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Tue, 18 Jun 2024 09:40:59 +0900 Subject: [PATCH 05/17] =?UTF-8?q?fix=20=EC=9E=84=EC=8B=9C=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=EC=9D=98=20=EA=B0=92=20=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/api.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api/api.ts b/src/api/api.ts index 93895285c..61a8f6264 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -10,6 +10,8 @@ import { import Cookies from 'js-cookie'; import { formType } from '../components/AddBoardForm'; +const E_MAIL = 'leedong0225@icloud.com'; +const PASS_WORD = 'abcd1234'; export const getBestPosts = async (params: string): Promise => { const URL = `/articles?${params}`; try { @@ -48,8 +50,8 @@ export const tempSignIn = async () => { try { if (!Cookies.get('accessToken')) { const response = await instance.post(TEMP_URL, { - email: 'leedong0225@icloud.com', - password: 'abcd1234', + email: E_MAIL, + password: PASS_WORD, }); const { accessToken, refreshToken } = response.data; Cookies.set('accessToken', accessToken); From 204cd25dae19f1b5c2a83eff286848302fd00e42 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Tue, 18 Jun 2024 09:55:26 +0900 Subject: [PATCH 06/17] fix remove response --- src/api/api.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/api/api.ts b/src/api/api.ts index 61a8f6264..40c3c1c0e 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -12,6 +12,7 @@ import { formType } from '../components/AddBoardForm'; const E_MAIL = 'leedong0225@icloud.com'; const PASS_WORD = 'abcd1234'; + export const getBestPosts = async (params: string): Promise => { const URL = `/articles?${params}`; try { @@ -45,11 +46,12 @@ export const getTotalPosts = async (params: string): Promise => { throw error; } }; + export const tempSignIn = async () => { const TEMP_URL = '/auth/signIn'; try { if (!Cookies.get('accessToken')) { - const response = await instance.post(TEMP_URL, { + await instance.post(TEMP_URL, { email: E_MAIL, password: PASS_WORD, }); @@ -65,7 +67,7 @@ export const postImage = async (image: File | null) => { try { if (image) { - const response = await instance.post( + await instance.post( URL, { image: image }, { headers: { 'Content-Type': 'multipart/form-data' } } @@ -80,7 +82,7 @@ export const postImage = async (image: File | null) => { export const postArticles = async (formData: formType, imageUrl: string) => { const URL = '/articles'; try { - const response = await instance.post( + await instance.post( URL, { image: imageUrl, From 4030e245c1b91da2a091fd952e91485b099abab0 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Tue, 18 Jun 2024 09:57:20 +0900 Subject: [PATCH 07/17] =?UTF-8?q?fix=20=EB=A6=AC=EC=8A=A4=ED=8F=B0?= =?UTF-8?q?=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/api.ts b/src/api/api.ts index 40c3c1c0e..c20a4a841 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -51,7 +51,7 @@ export const tempSignIn = async () => { const TEMP_URL = '/auth/signIn'; try { if (!Cookies.get('accessToken')) { - await instance.post(TEMP_URL, { + const response = await instance.post(TEMP_URL, { email: E_MAIL, password: PASS_WORD, }); @@ -67,7 +67,7 @@ export const postImage = async (image: File | null) => { try { if (image) { - await instance.post( + const response = await instance.post( URL, { image: image }, { headers: { 'Content-Type': 'multipart/form-data' } } From 3ee3092c7e11e53d76b208f04743417cd2906ea9 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Tue, 18 Jun 2024 10:03:43 +0900 Subject: [PATCH 08/17] fix change tuple to array chabge e.target.name to tragetName --- src/api/api.ts | 2 +- src/api/apiType.ts | 4 ++-- src/components/AddBoardContainer.tsx | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/api/api.ts b/src/api/api.ts index c20a4a841..2939d01bc 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -121,7 +121,7 @@ export const getComments = async ( articleId: string, limit: number, cursor?: number -): Promise<[commentType]> => { +): Promise => { const URL = `/articles/${articleId}/comments?limit=${limit}${ cursor ? `&cursor=${cursor}` : '' }`; diff --git a/src/api/apiType.ts b/src/api/apiType.ts index 22c32d170..c47cc5e19 100644 --- a/src/api/apiType.ts +++ b/src/api/apiType.ts @@ -1,6 +1,6 @@ export interface articlesType extends articleType { totalCount?: number; - list: [articleType]; + list: articleType[]; } export interface writingType { @@ -32,7 +32,7 @@ export interface articleType { } export interface commentsType extends commentType { - list: [commentType]; + list: commentType[]; nextCursor: number; } diff --git a/src/components/AddBoardContainer.tsx b/src/components/AddBoardContainer.tsx index 4ec78c764..deb721691 100644 --- a/src/components/AddBoardContainer.tsx +++ b/src/components/AddBoardContainer.tsx @@ -20,11 +20,12 @@ const AddBoardContainer = () => { }; const onChangeHandler = (e: ChangeEvent) => { - if (e.target.name === 'title') { + const targetName = e.target.name; + if (targetName === 'title') { setFormData((prev) => ({ ...prev, ['title']: e.target.value })); - } else if (e.target.name === 'content') { + } else if (targetName === 'content') { setFormData((prev) => ({ ...prev, ['content']: e.target.value })); - } else if (e.target.name === 'image') { + } else if (targetName === 'image') { const file = e.target.files?.[0]; if (file) { setFormData((prev) => ({ ...prev, ['image']: file })); From 30b0c5d8bf365e9d1fbd4e996d26a831278c1378 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Tue, 18 Jun 2024 16:11:35 +0900 Subject: [PATCH 09/17] =?UTF-8?q?feat=20=EB=8C=93=EA=B8=80=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/favicon.ico | Bin 25931 -> 1508 bytes src/api/api.ts | 18 ++++++++++++- src/components/CommentContainer.tsx | 28 +++++++++++++++---- src/components/CommentInput.tsx | 40 +++++++++++++++++++--------- src/components/ListBackButton.tsx | 9 +++++++ 5 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 src/components/ListBackButton.tsx diff --git a/public/favicon.ico b/public/favicon.ico index 718d6fea4835ec2d246af9800eddb7ffb276240c..6b2a63e99177918a9d1b90637d784779ab4d718e 100644 GIT binary patch literal 1508 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 LrJugUA?W`A8`#=m diff --git a/src/api/api.ts b/src/api/api.ts index 2939d01bc..70d71fd04 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -126,7 +126,9 @@ export const getComments = async ( cursor ? `&cursor=${cursor}` : '' }`; try { - const response: AxiosResponse = await instance.get(URL); + const response: AxiosResponse = await instance.get(URL, { + headers: {}, + }); return response.data.list; } catch (error) { const err = error as AxiosError; @@ -140,3 +142,17 @@ export const getComments = async ( } }; +export const postComment = async (articleId: string, content: string) => { + const URL = `/articles/${articleId}/comments`; + await instance.post( + URL, + { content: content }, + { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + } + ); +}; + diff --git a/src/components/CommentContainer.tsx b/src/components/CommentContainer.tsx index b710a58c2..af7fdf3d9 100644 --- a/src/components/CommentContainer.tsx +++ b/src/components/CommentContainer.tsx @@ -1,6 +1,6 @@ import { useRouter } from 'next/router'; -import React, { useEffect, useState } from 'react'; -import { getComments } from '../api/api'; +import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; +import { getComments, postComment } from '../api/api'; import { commentsType, commentType } from '../api/apiType'; import Comment from './Comment'; import CommentInput from './CommentInput'; @@ -8,22 +8,40 @@ import NoComment from './NoComment'; const CommentContainer = () => { const router = useRouter(); - const [comments, setComments] = useState<[commentType] | []>([]); + const [comments, setComments] = useState([]); const id = router.query['id']; + const ref = useRef(null); const saveComment = async () => { try { const result = await getComments(id as string, 5); setComments(result); } catch (error) {} }; + const onChangeHandler = (e: React.ChangeEvent) => { + if (ref.current) { + ref.current.value = e.target.value; + } + }; + const registerCommentHandler = async () => { + const content = ref.current?.value; + try { + await postComment(id as string, content as string); + } catch (error) { + } finally { + window.location.reload(); + } + }; useEffect(() => { saveComment(); }, []); - console.log(comments); return ( <> - + {comments.length !== 0 ? ( comments.map((element) => ( { - return ( -
-

댓글 달기

- - -
- ); -}; + +interface CommentInputProps { + registerCommentHandler: () => void; + onChangeHandler: (e: React.ChangeEvent) => void; +} +const CommentInput = forwardRef( + ({ registerCommentHandler, onChangeHandler }, ref) => { + return ( +
+

댓글 달기

+ + +
+ ); + } +); export default CommentInput; diff --git a/src/components/ListBackButton.tsx b/src/components/ListBackButton.tsx new file mode 100644 index 000000000..24f1c2141 --- /dev/null +++ b/src/components/ListBackButton.tsx @@ -0,0 +1,9 @@ +import Link from 'next/link'; +import React from 'react'; + +const ListBackButton = () => { + return 목록으로 돌아가기; +}; + +export default ListBackButton; + From ac5774c436cfa9ab0b7f85f69f25daed502d9e9e Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Wed, 19 Jun 2024 16:44:50 +0900 Subject: [PATCH 10/17] =?UTF-8?q?feat=20=EB=92=A4=EB=A1=9C=EA=B0=80?= =?UTF-8?q?=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Board.tsx | 9 +++++++-- src/components/CommentContainer.tsx | 8 ++++++-- src/img/back.png | Bin 0 -> 340 bytes styles/Board.module.css | 29 ++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 src/img/back.png diff --git a/src/components/Board.tsx b/src/components/Board.tsx index 547c8e80b..5837e97bf 100644 --- a/src/components/Board.tsx +++ b/src/components/Board.tsx @@ -6,7 +6,8 @@ import profile from '@/src/img/profile.png'; import heart from '@/src/img/heart.png'; import { convertTime } from '../util/convertTime'; import CommentContainer from './CommentContainer'; - +import Link from 'next/link'; +import backButton from '@/src/img/back.png'; const Board = ({ article }: { article: articleType }) => { const createdAt = convertTime(article.createdAt); @@ -18,7 +19,6 @@ const Board = ({ article }: { article: articleType }) => { 케밥버튼
-
{

{article.content}

+ + + 목록으로 돌아가기 + + ); }; diff --git a/src/components/CommentContainer.tsx b/src/components/CommentContainer.tsx index af7fdf3d9..a5a73f0b7 100644 --- a/src/components/CommentContainer.tsx +++ b/src/components/CommentContainer.tsx @@ -1,7 +1,7 @@ import { useRouter } from 'next/router'; -import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { getComments, postComment } from '../api/api'; -import { commentsType, commentType } from '../api/apiType'; +import { commentType } from '../api/apiType'; import Comment from './Comment'; import CommentInput from './CommentInput'; import NoComment from './NoComment'; @@ -11,17 +11,20 @@ const CommentContainer = () => { const [comments, setComments] = useState([]); const id = router.query['id']; const ref = useRef(null); + const saveComment = async () => { try { const result = await getComments(id as string, 5); setComments(result); } catch (error) {} }; + const onChangeHandler = (e: React.ChangeEvent) => { if (ref.current) { ref.current.value = e.target.value; } }; + const registerCommentHandler = async () => { const content = ref.current?.value; try { @@ -31,6 +34,7 @@ const CommentContainer = () => { window.location.reload(); } }; + useEffect(() => { saveComment(); }, []); diff --git a/src/img/back.png b/src/img/back.png new file mode 100644 index 0000000000000000000000000000000000000000..030a04614dc2f1c17041ebc9734e813dc6618515 GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^l0YoM!3HGxw}u@9Qk(@Ik;M!Q+`=Ht$S`Y;1W=H% zILO_JVcj{Imp~3nx}&cn1H;CC?mvmFK>kZl7srqa#S88z;6C;PY-sjUe2 z>U|_@py4Bw07onUfMV==e1>6EUWOlB`NRR8Q| z`@Lte{e)90+-5VY?_d2t?}qK{JE|YQ37oH)u(QDb_{XVF9;?6DIOAE&hUKND(|++B zDQe03HSe4B-eosi+ur2QQs4XKUb4Z;oqv-gYM58ZxJh}tzTbT!sA!s=T8dqu#+|_M kmoxtyIi$0^_v#0h``5JkOVr9A0zJ*(>FVdQ&MBb@03qarrT_o{ literal 0 HcmV?d00001 diff --git a/styles/Board.module.css b/styles/Board.module.css index b0d7754b7..4fe611dfd 100644 --- a/styles/Board.module.css +++ b/styles/Board.module.css @@ -2,17 +2,20 @@ margin: 0px auto; width: 1200px; } + .articleFrame { margin-top: 30px; display: flex; justify-content: space-between; align-items: center; } + .title { font-weight: 700; font-size: 20px; color: #1f2937; } + .kebabImage { width: 24px; height: 24px; @@ -32,24 +35,29 @@ padding-bottom: 10px; border-bottom: 1px solid #e5e7eb; } + .profileImage { width: 24px; height: 24px; } + .nickName { font-weight: 400; font-size: 14px; color: #4b5563; } + .createdAt { font-weight: 400; font-size: 12px; color: #9ca3af; } + .likeImage { width: 24px; height: 24px; } + .likeCount { font-weight: 400; font-size: 14px; @@ -88,6 +96,27 @@ color: #ffffffff; border: none; } +.backButton { + position: relative; + width: 240px; + height: 48px; + border-radius: 40px; + text-align: center; + line-height: 48px; + background-color: #3692ff; + display: block; + margin: 30px auto; + text-decoration: none; + color: #ffffffff; +} +.backButtonImage { + width: 24px; + height: 24px; + position: absolute; + top: 12px; + right: 24px; +} + @media (max-width: 1199px) { .boardFrame { width: 696px; From 5875c4da918e4d60c11ed1cd7ba3af065de0f8cf Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Wed, 19 Jun 2024 17:30:22 +0900 Subject: [PATCH 11/17] =?UTF-8?q?feat=20loginPage=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/login.tsx | 9 ++ src/components/LoginForm.tsx | 89 ++++++++++++++++++ src/components/LoginFormContainer.tsx | 33 +++++++ src/img/bigLogo.png | Bin 0 -> 6385 bytes src/img/google.png | Bin 0 -> 1589 bytes src/img/hidePassword.png | Bin 0 -> 847 bytes src/img/kakao.png | Bin 0 -> 1454 bytes src/img/openPassword.png | Bin 0 -> 709 bytes styles/Login.module.css | 130 ++++++++++++++++++++++++++ 9 files changed, 261 insertions(+) create mode 100644 pages/login.tsx create mode 100644 src/components/LoginForm.tsx create mode 100644 src/components/LoginFormContainer.tsx create mode 100644 src/img/bigLogo.png create mode 100644 src/img/google.png create mode 100644 src/img/hidePassword.png create mode 100644 src/img/kakao.png create mode 100644 src/img/openPassword.png create mode 100644 styles/Login.module.css diff --git a/pages/login.tsx b/pages/login.tsx new file mode 100644 index 000000000..835193505 --- /dev/null +++ b/pages/login.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import LoginFormContainer from '@/src/components/LoginFormContainer'; + +const LoginPage = () => { + return ; +}; + +export default LoginPage; + diff --git a/src/components/LoginForm.tsx b/src/components/LoginForm.tsx new file mode 100644 index 000000000..2d0bfef16 --- /dev/null +++ b/src/components/LoginForm.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import style from '@/styles/Login.module.css'; +import bigLogo from '@/src/img/bigLogo.png'; +import kakaoImage from '@/src/img/kakao.png'; +import googleImage from '@/src/img/google.png'; +import openPassword from '@/src/img/openPassword.png'; +import hidePassword from '@/src/img/hidePassword.png'; +import { OnChange, onClick } from './LoginFormContainer'; +import Link from 'next/link'; + +interface Login { + email: string; + password: string; + onChangePassword: OnChange; + onChangeEmail: OnChange; +} +interface isHide { + isOpen: boolean; + onClick: onClick; +} +const LoginForm = ({ + email, + password, + onChangeEmail, + onChangePassword, + isOpen, + onClick, +}: Login & isHide) => { + return ( + <> +
+ + + +
+ 이메일 + +
+ 비밀번호 + +
+
+ + +
+

간편 로그인 하기

+
+ + 구글 + + + 카카오 + +
+
+
+
+ 판다 마켓이 처음이신가요? 회원가입 +
+ + ); +}; + +export default LoginForm; + diff --git a/src/components/LoginFormContainer.tsx b/src/components/LoginFormContainer.tsx new file mode 100644 index 000000000..be57a144a --- /dev/null +++ b/src/components/LoginFormContainer.tsx @@ -0,0 +1,33 @@ +import React, { ChangeEvent, useState } from 'react'; +import LoginForm from './LoginForm'; + +export type OnChange = (e: ChangeEvent) => void; +export type onClick = () => void; +const LoginFormContainer = () => { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [isOpen, setIsOpen] = useState(false); + const onChangeEmail: OnChange = (e) => { + setEmail(e.target.value); + }; + const onChangePassword: OnChange = (e) => { + setPassword(e.target.value); + }; + const onClick: onClick = () => { + setIsOpen(!isOpen); + }; + + return ( + + ); +}; + +export default LoginFormContainer; + diff --git a/src/img/bigLogo.png b/src/img/bigLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..9dd1bab9be1a411ac5c3aab640d3f9b6349d60d7 GIT binary patch literal 6385 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 IM6N<$f`J09kN^Mx literal 0 HcmV?d00001 diff --git a/src/img/openPassword.png b/src/img/openPassword.png new file mode 100644 index 0000000000000000000000000000000000000000..467cf49aa9fb2d4ef242cdda581fcbf2f8cb4c52 GIT binary patch literal 709 zcmV;$0y_PPP)Iz1a)>z+N!Qv5b6d4snlJ#0dRtrU8O)Fn+icAxhf&uh1|e5sE=T^ zs|Nc`XB>LI%}DT`$20TI&o>5mkbf<>kJ0hlcSTr)MTM#$&xG1XRPJ=to8RZV z6Tq^X`P{G#Ux!w{d1e^y(Q2Q|&dZK?`IWbAYOSx;Ho2zl(k^9q% zT`&Tp&5^2HO?x)}+}R1R3QpLWe(kkm{j*Zznh%q$J$~mCP>~Rv+-+EMoS`2j@aCk= z0If}sRf{CU)Zpd%2hO6%`oqg{|6n@lJ(l(;0yD^Enz5buh_A$8FmnrlG!3{QHyJ!C zk0FtMa~( z)N^%RJ_-@FV*qDz=1PCL?6r(!z}z0+04%~50zTn?f0LeCL5mM>_T|i70Yvs1YkZh8 z=#4;8D~`$yD^^8}Lb91v=SkD0ugt5qa!(qhF~PFze2_B+L?8ezzsqxgg3y=;ewYlN zMv|>Ph(Y)|QzluhWwLzfxwqRCLr&ETm3Q8v7lh}e?B3y?Y3F|GOCrKX|00000NkvXXu0mjf=FdQ` literal 0 HcmV?d00001 diff --git a/styles/Login.module.css b/styles/Login.module.css new file mode 100644 index 000000000..46634e68b --- /dev/null +++ b/styles/Login.module.css @@ -0,0 +1,130 @@ +.root { + --inputColor: #3692ff; + --fontColor: #1f2937; +} + +.section { + margin-top: 60px; + display: flex; + flex-direction: column; + gap: 24px; + align-items: center; +} + +.section .loginBox { + display: flex; + flex-direction: column; + text-align: left; + font-size: 18px; + font-weight: 700; + color: var(--fontColor); + gap: 24px; +} +.section input { + background: #f3f4f6; + height: 56px; + border-radius: 12px; + width: 640px; + border: none; +} +.email-error-message { + position: relative; + left: 10px; + bottom: 10px; + font-size: 15px; + color: #f74747; +} +.section .error-border { + border: 2px solid red; +} +.section input:focus { + background-color: #ffffff; + border-color: var(--inputColor); +} +.section input::placeholder { + padding: 16px 24px; +} +.email-error-message { + position: relative; + left: 10px; + bottom: 10px; + font-size: 15px; + color: #f74747; +} +.passwordLabel { + display: flex; + align-items: center; + justify-content: center; + position: relative; +} +.passwordLabel img { + cursor: pointer; + position: absolute; + right: 30px; +} +.pw-error-message { + position: relative; + left: 10px; + bottom: 10px; + font-size: 15px; + color: #f74747; +} +.loginButton { + cursor: pointer; + width: 640px; + height: 56px; + border-radius: 40px; + background: #9ca3af; + border: #9ca3af; + color: #ffffff; + font-weight: 600; + font-size: 20px; + text-align: center; +} +.simpleLoginBox { + margin-top: 24px; + background: #e6f2ff; + display: flex; + align-items: center; + width: 640px; + height: 74px; + border-radius: 8px; + justify-content: space-between; +} +.simpleLoginBox p { + padding-left: 24px; +} +.simpleLoginIcons { + width: 100px; + margin-right: 16px; + display: flex; + align-items: center; + justify-content: space-between; +} +.signUp { + display: flex; + justify-content: center; + margin-top: 30px; +} + +@media (max-width: 769px) { + .section .homeBtn > img { + width: 198px; + height: 66px; + } + .section input { + background: #f3f4f6; + + height: 56px; + border: none; + border-radius: 12px; + width: 343px; + } + .loginButton { + width: 343px; + } + .simpleLoginBox { + width: 344px; + } +} + From 72cf7e6fb1d8cd9c38fc54052359e5aa72b429ce Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Wed, 19 Jun 2024 20:12:27 +0900 Subject: [PATCH 12/17] =?UTF-8?q?feat=20signup=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=B0=8F=20=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/index.tsx | 118 ++++++- pages/signUp.tsx | 9 + src/components/SignUpContainer.tsx | 101 ++++++ src/components/SignUpForm.tsx | 115 +++++++ src/img/bottomImage.png | Bin 0 -> 64279 bytes src/img/facebook.png | Bin 0 -> 387 bytes src/img/hotIem.png | Bin 0 -> 13514 bytes src/img/instagram.png | Bin 0 -> 405 bytes src/img/registerImage.png | Bin 0 -> 10642 bytes src/img/schoolPanda.png | Bin 0 -> 61930 bytes src/img/search.png | Bin 0 -> 17023 bytes src/img/twitter.png | Bin 0 -> 326 bytes src/img/youtube.png | Bin 0 -> 288 bytes src/util/loginCheck.ts | 46 +++ styles/Main.module.css | 499 +++++++++++++++++++++++++++++ styles/signup.module.css | 135 ++++++++ 16 files changed, 1020 insertions(+), 3 deletions(-) create mode 100644 pages/signUp.tsx create mode 100644 src/components/SignUpContainer.tsx create mode 100644 src/components/SignUpForm.tsx create mode 100644 src/img/bottomImage.png create mode 100644 src/img/facebook.png create mode 100644 src/img/hotIem.png create mode 100644 src/img/instagram.png create mode 100644 src/img/registerImage.png create mode 100644 src/img/schoolPanda.png create mode 100644 src/img/search.png create mode 100644 src/img/twitter.png create mode 100644 src/img/youtube.png create mode 100644 src/util/loginCheck.ts create mode 100644 styles/Main.module.css create mode 100644 styles/signup.module.css diff --git a/pages/index.tsx b/pages/index.tsx index 5b86e056d..b35d375dc 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,5 +1,117 @@ import React from 'react'; -export default function Home() { - return <>; -} +import schoolPanda from '@/src/img/schoolPanda.png'; +import hotItem from '@/src/img/hotIem.png'; +import search from '@/src/img/search.png'; +import bottomImage from '@/src/img/bottomImage.png'; +import registerImage from '@/src/img/registerImage.png'; +import instagramIcon from '@/src/img/instagram.png'; +import facebookIcon from '@/src/img/facebook.png'; +import twitterIcon from '@/src/img/twitter.png'; +import youtubeIcon from '@/src/img/youtube.png'; +import style from '@/styles/Main.module.css'; +import Link from 'next/link'; + +const MainPage = () => { + return ( + <> +
+
+
+

+ 일상의 모든 물건을
+ 거래해보세요 +

+ 구경하러 가기 +
+ 가방팬더 +
+
+
+ 인기상품 +
+

+ 인기 상품을
+ 확인해 보세요 +

+

+ 가장 HOT한 중고거래 물품을 +
+ 판다 마켓에서 확인해 보세요 +

+
+
+
+
+
+
+

+ 구매를 원하는 +
+ 상품을 검색하세요 +

+

+ 구매하고 싶은 물품은 검색해서 +
+ 쉽게 찾아보세요 +

+
+ 검색 +
+
+
+
+ 등록이미지 +
+

+ 판매를 원하는
+ 상품을 등록하세요 +

+

+ 어떤 물건이든 판매하고 싶은 상품을 +
+ 쉽게 등록하세요 +

+
+
+
+
+

+ 믿을 수 있는 +
+ 판다마켓 중고거래 +

+ 가방들고있는판다들 +
+
+ + + + ); +}; + +export default MainPage; diff --git a/pages/signUp.tsx b/pages/signUp.tsx new file mode 100644 index 000000000..e80b76469 --- /dev/null +++ b/pages/signUp.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import SignUpContainer from '@/src/components/SignUpContainer'; + +const SignUpPage = () => { + return ; +}; + +export default SignUpPage; + diff --git a/src/components/SignUpContainer.tsx b/src/components/SignUpContainer.tsx new file mode 100644 index 000000000..2a591e843 --- /dev/null +++ b/src/components/SignUpContainer.tsx @@ -0,0 +1,101 @@ +import React, { ChangeEvent, useEffect, useState } from 'react'; +import SignUpForm from './SignUpForm'; +import { emailError, pwError, isPassword } from '@/src/util/loginCheck'; +import style from '@/styles/signup.module.css'; + +export interface SignUp { + email: string; + nickName: string; + password: string; + repeatPassWord: string; +} + +export interface Show { + passShow: boolean; + repeatShow: boolean; +} + +const SignUpContainer = () => { + const [userInfo, setUserInfo] = useState({ + email: '', + nickName: '', + password: '', + repeatPassWord: '', + }); + const [isShow, setIsShow] = useState({ + passShow: false, + repeatShow: false, + }); + + const passwordHideHandler = () => { + setIsShow({ ...isShow, passShow: !isShow.passShow }); + }; + + const repeatPasswordHideHandler = () => { + setIsShow({ ...isShow, repeatShow: !isShow.repeatShow }); + }; + + const onChangeHandler = (e: ChangeEvent) => { + const { name, value } = e.target; + setUserInfo((prev) => ({ ...prev, [name]: value })); + }; + + useEffect(() => { + const onEmailFocus = document.querySelector( + `.${style.emailInput}` + ) as HTMLInputElement; + const emailErrorBox = document.querySelector( + `.${style.emailError}` + ) as HTMLDivElement; + + onEmailFocus.addEventListener('focusout', () => + emailError(onEmailFocus, emailErrorBox) + ); + + const onPasswordFocus = document.querySelector( + `.${style.passwordInput}` + ) as HTMLInputElement; + const passwordErrorBox = document.querySelector( + `.${style.pwError}` + ) as HTMLDivElement; + + const passwordRepeatFocus = document.querySelector( + `.${style.passwordRepeatInput}` + ) as HTMLInputElement; + const passwordRepeatErrorBox = document.querySelector( + `.${style.pwRepeatError}` + ) as HTMLInputElement; + + onPasswordFocus.addEventListener('focusout', () => + pwError(onPasswordFocus, passwordErrorBox) + ); + + passwordRepeatFocus.addEventListener('focusout', () => + isPassword(onPasswordFocus, passwordRepeatFocus, passwordRepeatErrorBox) + ); + + return () => { + onEmailFocus.removeEventListener('focusout', () => + emailError(onEmailFocus, emailErrorBox) + ); + onPasswordFocus.removeEventListener('focusout', () => + isPassword(onPasswordFocus, passwordRepeatFocus, passwordRepeatErrorBox) + ); + passwordRepeatFocus.removeEventListener('focusout', () => + isPassword(onPasswordFocus, passwordRepeatFocus, passwordRepeatErrorBox) + ); + }; + }, []); + return ( + + ); +}; + +export default SignUpContainer; + diff --git a/src/components/SignUpForm.tsx b/src/components/SignUpForm.tsx new file mode 100644 index 000000000..ede9c66e0 --- /dev/null +++ b/src/components/SignUpForm.tsx @@ -0,0 +1,115 @@ +import React, { ChangeEvent } from 'react'; +import { Show, SignUp } from './SignUpContainer'; +import styles from '@/styles/signup.module.css'; +import hideEyes from '@/src/img/hidePassword.png'; +import openEyes from '@/src/img/openPassword.png'; +import kakao from '@/src/img/kakao.png'; +import google from '@/src/img/google.png'; +import bigLogo from '@/src/img/bigLogo.png'; +import Link from 'next/link'; + +interface SignUpInfo { + userInfo?: SignUp; + onChangeHandler: (e: ChangeEvent) => void; +} +interface EyesButton { + isShow: Show; + passwordHideHandler: () => void; + repeatPasswordHideHandler: () => void; +} + +const SignUpForm = ({ + userInfo, + onChangeHandler, + isShow, + passwordHideHandler, + repeatPasswordHideHandler, +}: SignUpInfo & EyesButton) => { + return ( +
+ + + +
+ 이메일 + +
+ 닉네임 + + 비밀번호 + +
+ 비밀번호 확인 + +
+ +
+
+

간편로그인하기

+ +
+

+ 이미 회원이신가요? 로그인 +

+
+ ); +}; + +export default SignUpForm; + diff --git a/src/img/bottomImage.png b/src/img/bottomImage.png new file mode 100644 index 0000000000000000000000000000000000000000..2c5b867b38063202d4ec60071ed8f4fd0d778974 GIT binary patch literal 64279 zcmeFYbyt+%_dh&zDGVi@f`k%EcXtgjprnY>-5t`BlF}tL2&lx+NH}zZDBUr14$Xb> z{(S$rpTlp~VhwYyIp^%N^L6AjT+dW=tv4+4Q6t0>FsfIt{)AP_n&E;cX{wDW!p zc*Ap6e&YrL5s*Iop@A~9DS<&WHytHeP}MN)Ht+${N=8El1p1LcaAS@I0$qJmk(bf) zM%$go%cflqV7s}WkVucG!h4UY{Hj(ln2_cvElr=NVC=_~0HJF`9F~Q@u5V98qnVhL zXX0GGA2C-(t7O}=;NlIRse%Urg?wbt+ZXJa&Er~saD`a(p?xLZvJPP(L?hu7-9QE| zY?{qa=|XSy&Y<%irw7*s8InjO($?b^*%$?o_Wxf0j|2bXzzr)d2qbMWASvQu9i@*i zBUBd2!C_O-qybGRB?%51_t)*23iR;5Ri8g--mzfT0A^``LTEuC{9`8n%BI=mb~Jut z$!sZg+)WS&?1l^22?TeA6SGndPdIE)-(xoFEg=Zx5++Ru8eOBm{^1Xjp=Ev>ioZ^S z2LdrFf_nkeNx@&?An$~`%{rq;MbtKN$=Ha1K-~%-L7@EYn{`v4Nc@#+FoNmb1@pM1 z$4wOr2oy{y&4>fCe#JQ`o;WnFucsZ!zLI-4b<~`bWe5h&(_PRn3X&%6i#&Ra2_~{O z07&>8@jwDgLncr93liyA7Lv*9ONA8|bPy5BtTa z_yvH(PoojEpnQ>CMaoFw6~T3JLl7DWBo9Ux0Z9+KG`pO!DS%%7F2cIGBwELQSd3Ed z4Gt*kWfiRIj`nHrmsQx#-X6c-P~6Ikhk2N)z=2mD%gM>;F2QyvxJN}F=73WYF+km9 zsyzk&@>2lb7Gkpkd_0U)d3KF|vS81~;Q7*zYfZs`cc z=!I5geqnWY#ap@|k`J#M+e_m03-OTCuo?-kX7@s0!gf<&1{g!Q7!4F0L9J_keL+>I z8`>ysim%lrM7Udm$NAMvFnSBA1|ELcs>zue1Mt2s8|Y)7z4khq3@M<}L1*^+f<-ab z!?g(P6IC8ge$uwrt{<%S->DE#BY;WXvVc+qH?92g-QpiJ+AQbRe7xouhrdCK2y$gM z7^44l^gF2t**Rcy<`eY(i7cRG!4wZCDa$e#S?kQG)9`L}X5Sn~?W?&hx0p7(r!{Zk zUr@Ta^wN3?(C!?v^9N9F3S-W|tvy7T3u*dr+o`4F{MqppqfCaTx!Hdd-~p>%a6W=I zH9Cl-r%f02pDNT+@z9);1Dgpw2q)O7bFwWH9s>U`xJlx>U;C&(GysSWOOGFn%Ad4; zcz6)9UrLpO`2l8S6bQ@`eo%FgnRD|Vucs$scFij5xPqGrY0t(Uf*ON9hzBH|{}|YI zGS*Lc({tAR_bj5T;OOt)x)s6gIl-Ltz5|-QuX_!dqUo`2ls$=7z=VYddFDTpyL2h- ziiaN^YX%`WHuL+sDvlllPxB2MJb`xskz+@G)#yey_#GT@5+FwY|7O`5iw;lK7p>!Ky)xnzS4cJn{_QPK?C>(2=e$pZmWLrgYv9T z@d2s_0t^2))Ni!O@l*3L2{0nP#Jfuc0_nw8R7_V`oqc{ZR^acn!g+{c055pX0gI=Mg-I@sg+kiaswvPUq*mcNsFm zA;5vb{5ND6z}^vvGRLG&*Y@~!ohiZq1na8yqgDNu+btVpDJN6^DIe(E7^VSitV_$V&YbC7{;KUtr4@`wLwj`HHWHb+L6@D_2%qUYx$%W65 z9LEsb^6j&79{|KM_CNS6kZgFQNORlF!XNhO&$FEwdO~wA4QV@f!}I|Y4h}8|dpOXa zneKLaK2eS*u<`(42hiPrCiJO}h2t2;#ngsOI`Twn|DFw+()-^ez^wwJQR}Us75Mf} zJocZRl^gV*#va$zwfJMypyZF(?-B+5X43SWv5}Ab&g>lrPuQVmn=xSHSHtGCa=Czs zU=sbuNknTN5x?~o4}DBak~yM5w;@_rRZFNbLdTJ?W39n)6{~Ol( zOVi{*>&By9?fIZfW04O^M_ys+e`x#Ry+U$2)Fj8`)#rz4=;8l8TCMLjrxUb$XS8h- zyQfsd1w6r}1RNVkuUNY)s17<>os5eRlx)?!57P%b&MOMP+p`0eej&BxK@{6UAlkx8GMn)g^C*^#H5 zR@8b1z|>&gUmSQKem&0A%$f1=AG~U=SRXzR;eDp2O4W@iC1ZigGElK1bNNu;7-x7C zR<`S(G-9Ahh;OJrz3Rh*J-4uT(Qa~sqck|Hn|x9HfB-{j!PPhX5dW}Zj>DS9fJ3RHuZ)330(az59-BZ=UP>=Z!jkY^QFk|i^E19lG~R;KmbnUF5$Mc72kUBR7a64~s>15Qk-Y;!|Dd72T4>C8 z&HjD^o4I2TMwgS-S4$SXDr<>?*FQUtY_%0^FO@I6MI%q7F?(0}N5pD)PVX6C%d;HK zJXY(5odu=S{qU;@XjPhIYv<8OqkF*qb+1r0kGoK1Kt08aN|L zrDhe>asj)7bD%mM5I!`>F`CO*{EETpP_w;dz|a|A148p~-K%4G{YAO{z)so^nZilF zkgqzJFqFYpoleajYu+Ngmn`B|WuyY8bkw~I8K5!BoP`BWZJ2I2Wx22sUK?N0lbNFa z7v$anurr@f58U!Jna<7~BA_}r)dU~R65>&K{I-^g$bxc2mv#N|EJc0~YonA<%}ds% z2{vM`rlvddsc&ggR)!Wlf`?7sIcH@N00;tgfH6UBE4)=7m-O-VMKi45ob^BF*(()& z89_x*D0GHj9<+89Pb*RzmN{r4l?L^KLU=ZWXG*bq4bnAx&x8Y2sJilGP8xPB&^Ltv zPw(4+AY6J{#Z32+cUT7&7MO=W zjbY3Cc+QZ#aNhsSF|48oB#GzXXUic(D{*zKc&t)38`rF6#n&YyI03OXf59}ptaHLg z;U@7jPZu6zaZW$jsNt>l3gv|iGrrzdV+SzZ5zrkOR zW^p-K=lGPSS6CdXb}9r8!%ug&z~uqhV66|J$feL5un`A-g)w`z59N2`DW`vG+AQma z^bzsEH-I>T4lrKPI6Mo3Cp?F^-_A~#TSd{w{-FF)=eUHCRY2p+ANW>qnQW>@Fg0tk zt1b)m&MTR$sz%F&yROLV>oQqm(JFMGPlf8KNxI2;Miia6Yh}csAx;gD2cpY1K2BTJ z1f&rsl_l|9UUojoYDZ)o57do=E+YL{uVJrGwK0iV-r*okj}z*GV@1qEC#11H@-35q zM7s$6GVof3Sz1?xG7vE#gpp~+7Uncz7JRf-1+elQ%{X;Z&F+0{tF zkFFMOW(J;pf%@ZgWTeKhF|wTIauOyU7_jlucKj~9-4fd{%t^3|Mg zq)Gxq;m)aE=)omGbb}PD3pS=PtLKo}b4YzrtS}73(@pNflOS`GldBB{Wg0M`P3AZI z?a!!t+MBgGX9fyITJ_WU$hVc^E&8#9CHo{H|H@ z**GQy>n`9xpD6>=p#-}Z=VU&0(hwuqTZYCpn3E-$?m27UR^;T|-?^+-QSaoG*D~aF zUt%!Na@o)2^2@dMuF1wM$w5;jAL*Y3b2?LMvCMc@6j?I~JTdsNxG*0uA5o-awxG<^ z!+KRzH2D;(IBd|g@|+@%=*>v4pHh19taV^l@5@+eL$sI_~d|1E@UZL~F+j!{7 zyVbF-TbgVwH5+5+FIRc@0|$GKD)l9n!N8p^|x5TR$;6T{JAfaQQOg zNL|Sj9q+Cko|RRWL`i`xuE}#n9zgN+v1Az`3$f3Rd9P@2(&X>bN-ypwcDVVnFn8ZP(O_zmSNqTA|8S;Z(ixu! zVE=*Lb_(?Si)|9Kzza)#f?WWGCGRIftIuMNQu|IZ?@l^o#+&zKFi+`ZDo(AbC>EoU zY8bU2pgAw~+BCW;|4fO9!B&~3gRvlmHuDj1uY5N@?V&dSjM)w)@6=ew1Q8f1vMuC14p&s@bZ z^abcZUc)TVFSsgI5muzqSUTlCOmt_Jw`GH%*7SV**=)~nQbynvqW=|*)Iy?u8-CN*C5WX zfxj>qFk+=akPp}dQ#FH2>8s;_FoLGM^T=R@<%SUkbfSh6Ni zlOj{P&k^=gj45)u4>U@TPR$DYyQv7LM-{QmdCe&%XdxL4mRl0u;qUb^X^uM5!am<~ zZ88lP>RGVo3_V)hvhs5U%mz%zg$ep#XH%e8-?6?*+cJH+U|N<$=+VVy+3KIHQ!-^% zMc*J7e)9V4&Ud<}8=JiUl3P|pp1M<5@A+r`yW1GUlN>$fvEkX)T>nvtP0=c@DYfNf zYP!@G2Q}c*pC3k>j~+*R{HS=jAWL`=t8kOmvb##VY8P`WI zgOG{3o~$TMoh7El&Z-y&om$^SKErzZps&4N{y%e&QK1(ze*22Ehll@EUlMH0jb&YR zQGC(C1fy|A9T9S5jrZgV%pf6d*VChty^2tg0pE+thPfhsBW^|5y zbGs(xY94Fh4?ULwf!PU{7H7`GT;wPd!c0BHo)ym(Isz`=zjyg%HUnEQc$u;4&OVzr z#PVsZTxC)pp(Bj+(oz%&FI^!hGlrUlA8C*=CCMMO_?!UbyRkFjlm+KG^lCHH(-?6m zvTj`3?n=mx8**4Ppm2nZo6EEI5uvqjvzDpp~U?-;YF+P)?s=RQ-p z&7&2s{qJbbdv(*?gYQYN%dl%KhrV7Pv?ru-nW%zkY&>RRvX_dVKFbPkzUAJ=&JfE` zBM#O&hK`NE2&At$WO}AnZ#lybq;YZD6~xm(w|%tr!2x9+8)= zwP=+xw8dqo?5uHrmZ!w+b5|)^H>}Ypn%U$Y!Gz6Htn#0i5 zh8cYPzJ^%=y0UnBd9qpIED^fF^Ti3%Y1M_!uC1~A31aNPKYK)*2jb1;Q|3&He*oPjQQWNgMLg^J&#enUieXUfgWwPPRetxcA4_3O?&g#*-b&C`sfTy9Q4U8?TcFjIE?zE1ESL8*%lecM1lz%!xCi}DS#hf z)voNMm*?5JL~hUd`DOyy1OCm-##t!6*|vW!#>LNKI3-&4z2Ly_Qy>m*zrB}vnt#H@ ziDtsmo%yu-)QL6tiwvHKG`V++4Rq#T7wQt{_DB1Lo8kAj^k^we3XOz|?z6asgrk7i3#5f@9hPFm$e7~TnS>%=UhgHu0I5?5hR2Z`vMb@{U)%4P zC&i<10BiitQ5yn+T$<;;e_H1xwh4(uz;16rDkhi@@MKWmqu=TE{!17HzIge9w4#k& zaOK*VDnG{bQ|BJcnPATq5QK|xIb{cuEQY?rR5ml5(;Vx3_mxwEDCBhPX{05o^x#8? zWxtneSD1HBeR9*;x>EH?w)xl>%hi!Bw{QGv@iHv%f*usCbF9(lO-6RNbIoft6g!)7 z5U?*Y^K%`q$f6;?OgerS{YPjhbv`<>N3!^Cx5QZNEl8@E13jm8iYc*_W7^z^0S%-caq~|jB9&AALsJT(+M2X&qA0}6h7KRSwx%(5Vv3tyErLIzTPS?Bpbls2F@Xnt4 z_j~*6+)@%fBBVy)oCJAT4rjk8lWREErwAOXm73RF3b#w6Yo@P=GOsyqZ*UHo(&eWasaO=SR zuehKJk-GE83VbfWQ8WLy0|RIKS4SXurcvN_lek04pgZxETo;P6c8$rb0BboP zt`Kpl+zW)SzLrpE1HQ}-1f7tnCe^hkC^P>Z?#kFNiCQ<_>ghup+%>Qgpc?c*f-wEN zz|^SP%~M|pmec;5)cXjVUQ%w6JgFc_E+fyFqjWjn*zi{=2Bf_wQxnq_j6YM6$_}#_ zxGP{Znn^Dvoh~|TJQ?v!;V)7bOL9orwsyK-Oo?)|0A6Z*e-C*#OzEbV8hmiG zX%$zX(Mk48Z8>FH%Eu2MlO|J*%vQOtsr+5c@xZpiJm{?l^61g|{8~+9mS-0Jrs^~({ z`Ki%Gg5|QigbkDy>)g_>%;$(>!25_7A_se|Pr0XNF4tBOyr*rZii}#ip%E{2&2K{N z1@G!!GoC}jCA4nus`P>ci52;xSqWE-;F6j~^^!7Eox%W{h0D-htjt*YYqce(wt67n zvko@6H7qR5Zr2+bXm=NLV6LV#W4Tu40>S$Ru1CCe zdl@1)=_l@zjKBIEO1Y>BdYPmQIRF^YQ{K166XwLIr{yG?np>n?Seig5Qkw*NhaEy2 z97~G6|Hzi%H|EC%F~U_iY}}RmWr8*Dfo_OD9#%JXFU`x?49i;%D0MrL1A@u1L8DQ$ z-pM{KegVQs7(1d%4;burAKO3!g46nTtSd6pc8$iG5O;0#^q38c7V$Lb;|O%3{o?mE zxO?C&_DLOTPJ_7i4G;#%g8doW+USV&WpjioGAzGZa<;|QjJqSh3bl6 z;cc1It>A~yW*SPy9+X7oEinj>Y7yOaOlSU#^R5*BvREYRgE{-9+Mu9inH4MOPOi~; zMP5}1=G#O*6DP+9>A64vzUr^^%aj9|95II-RuB&1s&UzOr6BHPN#C_md-NzKOjm1L zExZTRMMZ2lkaHgb(VX`;(I zsZtvSo@#FU1ziQfqftsr^7GaaiAAq9=b&#voB53olQi3A z=CD68IzErrIl78@ZR3+5TCy7Wa~3Gpu@Dxo&6yg{H|Wut)56{v(=MK4-X5A=jee%- z2CRcW)&FckIo?eCYTxhla`8so7vjX|*n^;uX8t}RRBq86`A${YPz|K<>~nq=N8yX2 z^i!~O9C!Q8vBzcR6VMN!h&mL}Bd(zx)@z>@p_x;%EVNiKWY&}?%BI0=osEG*IDUV( zFQx729{a!zoYmJa5p)z|dpl_P*b+wP3I}32)!`B6D@#Iz>(`lOi)7Z!fLie%?;-ry zWrZm_NT<%QQpTn-Zf?K&!0{QMctj-1u5rUj~`4d zU7lc`)!d{NyH8u`Q_#C{VP*8`%zj9RD7)ZwPW+(8*MO1ox=Y~?sVbIwMqR--3D2ya z3%qn(a9>$d5iNK04|0ARjE#+L^VWHEE761Z-oR>O(3q_d$PG+R{Zrwy8sgs{$rO-l z6^yYQ$~G6rUVTRtc??Cu2^|KQo;YV>{7A1x3^@GLAtN?smb^iTDSCJal`i;B;I5Z0 z_$U7gsz|T?>KAkZudS|A&rql1E74Uhp4wCNC?tt_8QXqj(P&f%T&YvPmL6O+;0AE` z)P%bb&f;7XQPWk@i}%7qA8*@*iHWQ(wY|L)H>|yQ_O$He_Sx@t7d3D{6Ct>l>AX;I z4c{PUBk8ZJGv4L&{T0u4hLsob#pc4|1(#uK=QXYH*q9<|Rjv#(aetZ=&6G+%_NS1Z zz!yFZHDqY~rKctgq%|DfnM|<^kOIGhg-v`RxXwPKbNOYVf)Kf*2IZ*V)WQ5JCfFQ^ zPRHFQ8=x%9igm za$d-nxL3~bI5G*f}Sjkz4n=N>IF_{?EpoFguyy!=Y!lg;r%R~MB_3Bbq0=bJvg!)&dVTVqU=+btuF zFg>#(2&YZp3p~2m0qk`OBl6^6Z{8v$mqFAwY$a9>r3A&j@5QMuT~|w=Vht0kGkq04 zQ~gDesgsSZrpQn={^3Y3Lc~AGMP-7!TYvL@IXRe*bJ_Y!mWhEb(ya+x><8lG$3~BI z5sQp2b?0(Q3F9ZQHE}|;oY|0(ta%5_!^Zh}#b|Hv3{Re7Wx8eoINF{=1aNcBV60>1 zN%0z4aP=dc6W}h(!`)g_%3+|B`z$z7jxqAJHrpe+sk|YwcgDWj0M` zM839v>%0nXVyMp_?(o|<9f&jU-x$ty5Z^eQk0LpA)o8dPe94F zkt|c)GB=-<=oP@#oeuEIPimV^#ts20Dc9N|8$fCL2XSh>!(0fB*V+?-x$|tbNs(_S zw;=?Z+h;5pTpU|9D@YcDQYdN1C~v+YX~;xs>f^^JhHM%6&hV_ci9c;cnMdpSY}=*$q}qT`*L z!KW>GLYo9mAX&g{nR)Js?0Lff_HOeP>~%jzI$ca|M-Vw}e(dt*2^p%OHxbRYb@n1s zGWp1k)1jC`==Rs$Xyo@8A{EkHS*lH;GRKYkUGWbYu4>!7cbVO!Gp~HPx5bg<{f(2q zWYX;tWFO@u#H}hv`2g>~6@v$iDL)|-C@#Wy5V0-fnKj;evu;Z|HbOlkf>rVROb zu^Vprp&y)|3lkY;N3#Lt89!ztETE%ERa1!6YE=L+!J6720ZzWSkBn!w$?t??g<$fv zdZ~xL>4ZBo)jRbC3&m^2^&uE85-2&5p6(;>^dz^pD%#3NSo<+OT4Tt2HxaIO)+ehU zl+Y7=e_jrtC=^AP7i$T6I>o{&B0Z2o;M;QPGQdYooh^t$~T7)4+Y4lP|)jp4&ENfz5$E@`=aLDL;;{u}N>#Hp|RRPQm%WVmwbjXthETuKbns)j!#OJ^{{^p$qvfrrVUI5eVbYE!mBg!#0&q$ zs!fSr`Nw=@aC~rLa|-K~hg5RkZKXm*Q%a8d1_H5B@O?x5xfA=hj%DMe)$#eUZ&D#? z@bDhI&E;N8_jO0phST((GkV%SiE}#|&VLNFUx#!Y+s`o$Fc#un&oLNCZ$z9`f<}Af zMW_XK-$>>=S0g#_sfsKnrx$o(upR#oCwb$1Bm2yU43URJX4E`X)5Lw48VyKQRrgxm zu+#FzU#ys5bhOy-_)7^lsW)WdWH4ALp}~n=j$pVv^C7;f@dqc2-*dSJ1JBPYF(ZZe zlry0XL6YkdL|WI?Y_>#!GY(Y4^FpxNiZgeu2`wYXxL{a)!QgENYrj;vT#cD2oN6jI zzf$&mihH`1+C}~Fm`1|0g-G@dG>6BLD95{tJ&kaM7a^8ChzQ*8DpP}MaxFQ|t%^eQ&DQV(? zL1DTq0(aGzb>?Yo*1lfH=L)D_>YA+2ASV)ax8aluG}XwJYEJz1drZsl!?Uc3umJG> zpHuE}Y9nQB*Y=)KQsBS@&lehbYa8V@9VJ&t{u!F0Vhpm7ipF5}Zxu2Ja2*Poi@Jfy z$-jlm^^jh&PH(Jx{lK*=A}X0AHO~T9+O~tMQ`@Va_W5_a1Ge%nQcl3u1!Cs~mw>kG zh1ctHa?>d(IYLyGGx@u(zSY${oz8_Xc+<6T^YE2GcC2`%8n%`DdGP;7W_jgo~c3z*M!7dIRK94H`Z{hn?m9_1upOFhZ?uAl{{wMuSu zw46p>=Zl!zYWy64aA--Z+LDq;F(mAyo`>No5V<+p?oGy3u-)(UT|sp>mOQ#rkzw_* zZLtkAqNoy6o^+Vpb_7*p{E&OYX||tE_2%~v>$^l%^`;|7gO`QfIO4WkLMvY`8s9V$ zF5EyyH0L}2em3GVH{P5yavHZ-oQcp}VYiw!gsaJQ+~(l|1#O8);zDH!M-tXL~Wh@m6h8MVTR7uQDWi>Ul7fv_<&Q{cg(r zR8O@|I&`D0y2WOPJW3?&1S`b#T&a~?)A?XyK0PhB%CtwG^*Z0!gK*8*1fDMY(NDMi zwPn_kstfOZ9{~?#$IT_hU0fzPjuYV$ZFfawnrT(kSz8UbMTOmLKj&bUrt|O^xYA^EY!29rD*SZ+sHK8e*hUS9(UuZun#)q zb(Zp*Z@>Mu({5{fIdL7Ju2)0UuU##j%R?sx04cewxSVF`vp@FB*`X*UDeu-RzkqqU zhGgP?tC2!^I~HtD{4*@uC?0?qfK5+zXQnJG$kx=7owx5md110&S)#H>Kq!gJ19 z<5#A(UutxO!}bH}&XbO9I~)3{b&xvH?uV8{^Ilu14JG_|^~)DY4zG|BdL(79oQF%6 zm>iu5oqA-Mly(8Y1+)AhC{yeG7BRK>!2~oDlauS$#RUmgd*~vL_?M|%Va4KRKEKEqpE!F(bqSsSl;$X!>(zM5BiT$odtKVJmURf zh`@v@*s_^iE^14x&W!93sa!=?wK9~GH+7uh9PQ3^9RhFvW3d8*pt>P1%tRN|m|g-G z-H>n>M8Ooh$esKC%k=y_-xCc{_fvK{QO`kdS^(xTHM#=V25Mcec=eo>))N2)XRFia?yr;he|_uTzBG#Nc*1MSZA= z&!syuQ#kq=4Vr&_W}xdD!f5m4>$1>7!TIwN?Oq2RApn-L1M<#<5Ki#>3cl*{lg5pE zoJ%B{xTvo2u|j$JlbUYnHLw44u-2^3-l3sf(OvDLWJP^JMJP=0wZ*;34Sj=zcO3E z{qtq;-!Z$jMZ8~62%p3pz67@kCnik29`YM4O}L(?zPt3Phyd?QyWZe-)p7Tv6Fik{ zP4Feq-4+&_>iE68(KS>X0iY449&_>9q6F!i{C-h+750j$_?ByW1uQSfM9^;8*xeog z(F;RPHYac4v7Szvma_tm1Bkt8Q8vv&AK>aSE3n@xpxUsvP*9|__0_jJa`Jk!K9KFi z0hDu)vzRxQJF-qiIQnuP-%;J)kCmDe5)KSCFXto*6XV^AHxAP!Iz&3mqJP-gQ#*^- zvckbuc=^Ks$Ras5IFmE@*uzHt&pZzq@Fzqhg&+a$Th>YcuCa#Nf+}-b_?xShklK@= zSpB)5DVC1+&?!)jiMcH z%{QYxTEIqJ7iCKC*QvYFh#Df{4E++%yl<b_BnW;>-oCi&%{9!v2zNu*-z zV`G|3zl+yek@XoMW-4-^nFH>-HS+|Ri(p&T38QBEqttPrz&jx(G@F5JG zHqjUNpXMO%PiU(k3Xzg(u3u>M`Nv~ZMd||D&9&qS*xcKA*_B`|T3Gc#-5q`e_n~=W ztbKFmZAR;|{iu27wxg?x&IjJ&urv|^4?*QPUgc#eke`SGXPcl4(3(2=;=DR7yk>q$ zw+=(fRp&he5w0;Y;B!?5k^+4MIRN}-DI>*`jNU3vY;-=Aw^r?Kq`m^8o8pLgbIiwI z1vgb%)g_EBl=qV}&Cg#DSI6a1usozMjxsCQrPVqG=^OJxvR%GQyzfIdMi<-ELD4sf zc(;~RHPXQ+t8)C_IINmxnFjj#H`0PcqWrkh;p^)Yt8`H=l$&5f2i!GVl$2k9xbg9^ zq;sPe)Zc_Xx2V4PS_g)YvvOOC;CXZ?c=-GCc5(}R*-UE&-kf&3)G`VgerZ0Bv+nO% zcla{#peWcbGouw&8lh%{{>eeXc`<-NI3Snz(M-hU3=KbXBsv2}i{bib>s|{dT_xRvpULBr;Ci zuOO=e>OEn}3?at15w74xB{UjQ4{Ex`kT~UMv5OL)aUG;40+3!VcxaQvzHcH&2jC1^ z+P&|wLm4(BX2ad0ohdtouUFgep5x3UG2YuN+MCPK;kSvG8bG-8G zTa>L;?MH&)ueAdIngln=0Im#o-C5lN4ab!*j}}DpMxvRF@b_GXA-L^waDt3K@ZLY< zYZ?K@+_inMFD_`MED{|-*NC4*J5lm`n69DFrg;n+YZus*`Q5&;fCEP!2@SIs+a(E>B*OuV${M&VCwSJw+zmt&M zl(3)CxF9`lGZ=-n$E@)vek})~ynL@(p8;4p2Uw?UUF(^wfd+e7MZ=tp;g^}%okzI@ zW&&6FhrjXm(b{z~-bRiCO{Y-_zh>JC-D&&Dk9Az#_pv}mpzb)!5|4<0djVo+zL#|bX3KPtHT|H z;ol}+3FRcS5&xB_srX4hjj{iiO92G-xkT252wZkHtU`dqV3L+XoktlCrYmmq=-GFA zWskE1s8p3lk%wlc`r96dzUO-`5>cx!oH!%A(4xYn{S1^SBW+zce0~+hd3StSTLOB( zfSFjKyNA32GeC|oNM!iMg^bhA z|4pp3T1R%rbvq;$>6qjUeWBlfOPd1Z)S&zUmSsm2fiHB(NOZ>Epa*|a=FlZuLJ6<2 zW`og+tQH8qw&%Y3dc4R3S_H&n9bPwMUsOSV_bu?t-%qN_M`8&t)IShxAf0?&2T zbUl38rHcTNN$s+%v|()Rx206)aR~HJgc*F2jR<0-4*2c4bc2Q84QxmLF^m#+|)fy{pSw~2Se>*3u7O}LOs;&om zrG6IGx822NTjzG#+n#t>Opela_7&=E&B%%R)uHF*XZU9>>9ga@6HuVx3+RH8C zUQ?_f9oKbgvuUxq^Fy8*g`|m((FG18y>=yhb}haX3C%4rQtU1)gT&{x?O7TE%%5 zzo2KbC-cc~L^VHxGLygNX?vjC?F*E2dQ05hu8dxuR^`iov4%yN6 zOS#^jo&M9R!u=q{GSz04JnOefKzy^1{=!h5q4iF#;PKYnX-ER=XIzu;g>d5-UEC0A z<0S$>Eo#WZ)r)2ma2`sM|LENkZ~Jdi)UDfHea}Du~KpJ?QmFCSWEMA<~%W^oi2FQgk&ikE@E=t{40bX*E7C{qUadkgE z6l6PR_7GOgSNH%-V7$s421Lng_yYl=9-+JhW{e}2Wn+bcRbDCeUT^bV=!g`)p)Nr)Hl@lO`pdFP^>pT+)9Aksjnk)Gaw*H1gcG5rb*S5gNvZcYonD6k$L>LFDB6 zc(Mi9?#+iB;3PBj=;h2wKPU;%Q3sxiveI<&XS136mr>Qlw~xyOJKqne+G-5Fjk6o z(fa1D5%DYNVlFenjBKp$5$1_c3b@JKhp7obeuFxgP%IItZ+E+UwMyZCLqgD25hw`)@xue z7Gh)|?a-?RP2B_s9<-vgA)S9io%8_k2$YN(YXQ+)qr=?&cXDE$S6Af{;fC;|ULoSz zAoC4lG6oZ#z*USAD@5!&0S)20ad^N)db@0U!-WM|*lze}ywXCEZ3GF>{DnDn za;8*u4^~is#EvU1W%V1r|!| zxIk?!rt{P6DGpR;m@eD0>t7hbUT+5l&^keUIJWbg$W3PXhejx`$XZU{P>#uO;pz;8 z7c-^4;-=#iyc{bk7U(h6|Cd2S@D1N#!+(A1Q{(B`b0Vk0?^NOx>UEbLC!6fw8qyY; zq%LgVYT*CelzZbq2mSMZ>whLvEDFn3>j~v#B05os0jd>K&^KDo@DSyRKV_8lh{9g0 z-9PlN!c5)~lP=h1RPYVMVLM=@%T-^zsb}ApWozV8p>H;wQR=w9WYc&}7LB~C zrdy#~SncDh6*3JLa5A(>Tq{2ixpFP`G|`F@GsHn+%ORU$2@8!U?{*CzJ;)hq%498p z)~)_Z#m=@2=7|3lp9|%sZBtrmZYShO{wJo{{OB*dT_Fw;Ko;gM?y6@LnOTtT5gY}e zZ`J_5Uq{*l+BQ8OZcK9x3}zZL7s@A`#zfSbTl7fIurWb3oaR>R-Wl5skbVOgnS~3ZNY*0}{IbXh{$_1Qx zcj^ySdg94}R}qhK@8_2!bPi;%IMB<8AAHRgtoWIs5eNHC7wRARb2%f}FDPQ5Jab5D zZKVC;qc-$M5-E}C`LR(Nb-^On(%nkoZ$*zL-ZusHjfTt()KoV3B92;BvLcHL?2*c= zyrve-F1nx4b+#{7E%QUSR({M#Rp8@OM<>+CU!aTl8b)RUi2h4KPMO>nwLZ1*BOs`b zPTy}-S2+41PBKoo+dojvpKXtjVYw|tFe2=|x+pl(rop|T_RPdswEg!hN=afqv&{0& z4pwNe4hKZzWjOw-Q6ED`9YeLVG7PAx$(ctOY83A+)RZoVi1Ue)AeLMK1dHnc82>og zt7yCq(~R}+KGUTJx|Ed->rbYq8~AT@?SiJ^@o#gr4K}1u#f#Hv-+9cMVmsfR046qt z-yjD^u`>r=ufB`K7ZB3HR6RpeM}CERM;XT1N)&X}5(*iJj@{l{F$&DWh9^HAYj zF_|)k_8tCj9uPU0t0U-xe)VgWX6Ux;ml@S`;J3y@R=LmG*CWg>p9Fa1v<6jw*E8DG z@!zLwH;g`)=DGXIA$v?`J`}jy2;#Fa;SkmedJE^t+|4KHWCj@+d94s&h|3!%QoNX}uOx|%_r!;=WW}t_raD2rgvw^=Fu^32;5^h<|PUb~0+E8xFR%#DmJEdf?VT?pB{f5Gq`} zH$O?=C;C15V!bwbV|=CEfDK#Rq;l3?e|B@dvF@azc)p%NFzE6wbCwZ%E>K*9_;>L- z@=wM7us&QsHsYX@o}Wl&vh>bgPsU%+j2C7>X=R`*-AS2ZSw4PvAYPNR-?-`M@OFLk zq7L{ZckTQ4s6Oa6f!=lgeAdzALrW0h-dPgCTAc3Cq3`35I<94Ss=Z9LlT(P=CS)%g zPr+4Wyc#zjMFhLGIN9IU_DiGF)S)bPpD)kHiaCT276hmD<3IK@rlccKdM z)yoiS0KNVNdS{u!m0jQA#I@1HOIA0mWnhu_4;A!gH=NX4||Ri5=L9A#}>7Y}!Cw9;pKHXdh+u}1+Ftj=!AttVB@ae}MQs``gm z2QAA?VCdfj5`})6)IuAf>mrF+p8GQjsD*1*BR}s=tmqE|X$ZE&lcOhX#L5s^LID{- zm74Rkds)~t^Ldvc!>v9-O;@7T33An>k@ke0;)>fr^Eai6Dh)J}mtS56G+E8My0P=o zQMhdxT!ycm)s~l@cKVC58@P}xA zV$LUShiXaG&0C8N!L_)}J`k)vBV4D|aVs9s(oWf(Is10BKuEh)io@VvR^}#p65#fF zb9#jYkwHsU3F1?m8=Py2|M=Tf#U<0qX;I$DifH zyVS^eHB{r*+nt~jgPCdJSTV7Bu{BE7NU?Ui?mh+sUDWf~nzUi*Yi#K(JKV|(=MMSz8 z-I7u&B^`p&Luz!(XryCw4K})A#B=$4e-D4a?smENea?B+0Sox4dGD?!NohKEnv{#Jy zWK6SN%fNu@p9u#>-b-kV?a8D|&qWKL25shqNcZjr^FS%f;u}iH$z0&MvD1if;SlPe zVf`YiQ)17pwYVt#d;5dKe-q00Dk?qZBGfSUA^14dN=deIz?|61RDAkVTPX5bHFHD- z;d-xLf1(1=sw^Z#3qF=5^C7OWycuy5cgMwt`ThIy=~$g z_Ze)hcFtq;lTC9u%!PY-GR(H+>-%t{UGW7GD8jG%n58(z4PTHXX#=-ve7?zR307;P z&Gw$nB~BBi8}7XPXF!uI}MVT-{_DdVtm}TSWZF!hFfW2pY-?+K*rg z`kJ71S}57b{;_U$JggHMUL&6H_{?j_A}COOzOS8?C0jT52bL2TE8E8Osvn@;FhU)O zJgW#i{yddpEa*Ajo!J4f3#G3Z^^-7v<)iy)66T^rzxx6MlbCNHYz0zk+S2hvt84+_ zrGCXx2WNeC&<*w@x+gbhAt@LjRI9OC{Kx5`&otkOk%6~`BV$aaxPmOSRX*wR!VIH3 zOePp|%yT;|iA~<;9k?G56%u%r&PBANI5~dWqEfh1slxVAuy}EZ2wQ^%Ky|PoS?xr% zvQrX{Ydd_o_9~{tyE?I*yXvNX?ZWs^G=zwojFa}2PoDJ$PuX4V74pHQkkQyzH|oW3 zW0S8cZ0FZUfA2$?r%>iA0{S@f0e(r~qG@T+>yft8b-Xpol>qTNr>_;u(JjVRFWIsU zF^##7X2a*OZ+00tz+1C|m)Rh#<4oCAv;MY6)_;5MX(eBOFRL?-ac(=MlM(*~FgY@3LOiCLZiK z+cx(jfeeW4W{w|Dig>e$Nsp#VzRuy>uG)QPDJik zVBI*T_qWHt|J3^?(ajf9w>{6|M*;DbiRLS$*5RM3&x!Q(&w^~7DVuUs;7MiJq!t(N zTR6Hq^Kr;~u9w6tnZ>Pj;g9orKfR|@?Ei)>yngFh z(2LG{hG7S^>=K>%1?-@j@!i)E2@j)L7&*(!hbBhv#_E<(m(#m*GMaR*s5o6qHsHZJ zA<(xxs+Lor4bw;i+1`=$uYFJL4gVb0R;f!Em@1Yhk=^L-2cCaZ=ugY~tczDnFB|Ht zd-BzIYf%xT8d>tE#E56Tn@3%{8b{BeHhEFPG5%_VBfO$CVmQE6e#9-_A7j))GThzo z3#cBA&5&{P9fBSBX3wp=_OlCs``twrXB!zKm*;R+0&SVxKXsWa&rn%cSteeXwK9GK zT3;%;Vy12ggEOcDp2B`yH{x|WwubgAaRSA%g5+C=`O7w}!kOL-?IP6r#L`*c4pQ8V zWCV}RSXX?%c2zk~Jh5Q)r7B1OAk7pvf#8Fv(07XWmbETiWkmE%oLWE7-1Ax<&5twC z*HG*#XyBF_^!mYnVudeXHK~|(|EZx-(PO&v7NC{W{wnN+c8;(Y+Yr<*g9`je*FC;H zaDvfLftmo?^@(!tMb+{dW4MD-^@K;p1R=MrY#D${9B&MyPN{@UYPR(et`A@yAqExnU&G`M_+0~!{;{# z^9{Up=7X_tVKqvS2h&<~Asl(++J_G_XJbJ+Okb^I{GrSMxazUd4Hz$D0pC!lA%_4@ zl49Tdqr7FC$zFsy-C)<|umKAv}fnFri7 zvy~@N-^cz>twIhWG=HLia0%jd7VvO1%Ob7L>X_H#SG~6^p>tJy(#c%=jb+_fV2&nq z>b6}!Hv0Z81W@Yej}H>z>TypXnMd5uFTAT7#XHZ1S~87>Ykzw_5r?9|@fg(X$+)%o z!&SeSu&_;0GwttoGbkey?i8q0nut#S{%zVeBz{$ECy? z!FSyg`&5fq;>7d>j^M7PxavJ6kISjHw~Bz*Hu~X$EF6G`m{y z2S&Kw?_&r5^zhaPqkS2PHPcG~Q&(r47vCL92F-51ICvW?4;>lGit0Pv&ZPt_KJK0Y2K}P% zms|N&K7W-hyy|>bXYU8z_WaDX;d5L+J6Qk8|G!~6@z4Ptui3+8=uY8pXS9Vv+uQGp z5oLo_dDB^}iRV5B`_7Zh)Bz_r;06Yb4~({49poUs^0Bjc1~o+8cfHY=JzEqeuAzH> z?Wi!g>>Z_ov^U+E7AYmp64lo^^#9E z;FMKMg9wL`kEX=!L*F4hX1D0pJcr?JCdsvKSu>l&wg~fgd_r8A356DV-UX*vSXd}Q zMXb-CyZr_2Hr@g$emXGj!QNR^bvBH)A!OR zt6Hj}ZY=ebdaTonCEG>!ga{k-r$9#Jw(e~K=wpP!X2%GH4iA8<4wRc5AD?;XQV!HV z{}FM(0rTfi@d#XBR?R~5s&r>6n@GKaKQ}Y^`|neYX-1?nsSsqKp`)e`e1>$}e=oVC z8+h?4+*ye5@xbp?j+`SA1YoVQzG=GPx0`%hJW6wt4pbCdz`T%4k%U6&UBzE`X3dz6 zOz0;j!&Q1z{>~6XRw}-Lm?m|YkmQF91U>R6jmh<|iQ9i{#zJOVfz`{SmCDzDf6I)nNuPc|&wMBR72hRRlj zIZdem`s|Q0w>)jPiwaiX&_IEE02tNA@s?{=+=LxNyoUD{Ol*V|V)^!Q0Q5>NvAD!2 zNmQbKY%}%D`Z)89bl_R3W#322ZXP1LB4L#h1bK!qsLSl%P7faycd^C|SbzX`OqOF` z;&z4b&AugFfK~CRGdJ07JsQd*^4Kd8;C%@nY+x9BB96FE0xqtHGsV+4JUkURLXAWs zzOE0s?_IC>w_v-_OQfv6H+^%jKj0+Y=h?k;An!!R>Mj~VMd_P;LX`u8qWYbQW!a+$ zm+}sY(*-7Jcjps#;uU6k+KDb%=K081#Q*4kTZlph*GAduu#0r1SGiyH0w&4Nf%_W0 zwp%qTT89pcet^{Jq7&r_p$D$enI*kh_-a9x?5}LD?vZS}B-oGgN1#`!eh71haFBYP zPq+)A_Y*5NYFz857Y98UHmN5limUhHakcjT9cj6hZ1h;n68? zJ~iC!;rcpcebsgwDS2oWuT_)LF4m=+lTPl*L6OTeRM(mMDlX|E=;VYShfT!gJ~y|l z>iHF1Ec|Y&CXqN7uzgN^<9Dx(C2ZHN{Y%9kTvQG)%DmwX!a-RzMc+8If7*d)sZ;%@#rU}K7b?AbS*Ah04U+yHL z9l{{FH&2SoqCbZG*Bm6REE*pfM<8Nwsk>(~J+I>+wC9cM!&3VoZ@_rL5wb?~2&+cV zWa^Ke6*8wMm~44Ya*|ZyV78?2`p`zRD0#Q~fjJ#0F@pU)@TPZ&J$fEWnmzTy0iNw= zE4njRA06`PbUO?7EU=xhO$dl+$>jwCh~~fNA&Sz+gjx>RxQrSSQS74pA0G1Y33@Hm z#iN4PmqA&Z)<4(s@!$BuBg36IC8XaKs6D#G0|kXJCd^HTzfI<55Dm^1&wYMllJ!r# zL}S|7ZI~-KCC+I6{|>k(zI1+oFC%wU+-l+V$x&wBk0qCvtw#f=TC!H>Ul3_l5#j7^ zH+e3M_r&4UZ5IJu#ksyp6h7LxAY95G-|_7EN3V!iW#Q_~iJyPRotdd|CAh8rb=x{` zK3h;=b`wme&dOB#ttms?0^klBTUmT5aJ5)_9yFM)TO`pAE@r(G9C57q9VMa96{GwP z8N_u6le4qi?Jihw;Bw)(;9fVU?3yA21w~gRe&=&E{hLeI)<@l4p9a>~Cn>4bd)?UD zDya%EPVpKbq6&SJb^m>mmN$UqSmn_Jx_4m&P`dX;ZXZU_pWZXxruT+HDCc6QjwXmN zL@EI!fJmuc{ zdJTAKzs>o$O=9BbcHmh{E{oUx5gVi2LK+vnyhNJ_F!o(Fp>yuT;+|uM5Uj#`B(TZ{ zy5sk9jLkV%tO{F*-%@oOOoQFVq>NnmDZ|CFtaE_FFOeajYjOEsj!i!Mlnd=_G?tY7 zVU5jw#s`Cmo7S+CUqpiu5sxRr4ge>2CqwtlxSWbF&%JYOfOdazDvgy(SKP)rDwOvH z3>trrwa&dAc0b}EuEYumH&H4C1@2OeBXtrW>(oO-K*pD`rL4>xaK55a6#c5vV>gfOtDN|hF&{Jnt^xUO@fMCGdUgVpV1=pUKnW z<=^cm@u)9%$oQk|Kh39IfUPC;3!WyV;mveWId-7yMKN1-N=WzS&jY3f1rSK0pCqX+ zTPFN7O@u2@ng~W-J4zF~{uV_qM`Ucv%8I7;>{VF7C5Rl2^rcU5`}^$gnu zWSyb=Xq0g2lZ`h36NPMYz;xy~lnYj4O3Hp~6&3xj^`rWxs7|uar#qeg zKxlZ0d4RO*UQX_zs=1z~A~k)>U|nh6E8OKa=?puOw@s(TmCAq1vJe)eR_;_LP9(Pr;l&9;tmV4{1?zM}6gv*s z%a%kd#{I#J`XP3N48mSt^WJFH{@=&(3JQ*o2WK3_kD?}EW6fqwBo6(npJmVW`jW!U z@*HXZ*?~dWs@I~`Nv>3Qvauyl_3bRn#2-I7eCx((x>Pl(cL$V6=cPabfJep-ZnU0pS7H+r{jZ|Lh}=8$Fp(So>u;} zxNDd!d5rmYWmjEx!X{OIYu)voSn=R0zNfNTA{pX7YotC;L+=pFO(2V>zul5c`X25P zkVBCUNEND8Z-QKz{gCBWHhWpfnAW%(&}c|k_cMh{7&%C)M~*8|dtrJB2O_FY4M~`J zDShqidy`z02_%!)s&vfHoiC?9MMS9Gn@{X z89FrFR!ICO0)EHV# zbjphad?kHhN4e&!5{VHiEh1j5tVN&&ks{{iIk#*PbqVVETr+u@QjtRf+g9llpkOBg zlVW2!-19lx)*V+;R@~)xke7~k^>+d(?8PWC_UX!heQ=}_t1e}rUdZNrJy7f3^`hYM zZU16Ki!2Msnwuk$M<-C2xq$6K9fz-nbto^Ar`S1Q1Sm>7B6M{WbZw%uv0D3b3ah?V z@vaca=eu~K)%&74KoX=((OvA&IMi|t`cH@)@b0}btF>q6`XL#g!#np={Or(YzfBr^ zaSEcR^_R?4GgU3qpM+xR5^qEeaSDogE@H^~?lI};u&EaTfZ>bWxhPo?eY;_tEyc}hqP%9VKnl|DPZj242^4YWyAb}qC zCy+nztk4qz(X3keC;m!U5toF4Kjf^fEr+b*g2yaVy;}VjKB3-7D9OT`JO^?C4a3Mu z7T?`QUR4l?IWNR}%)Qz+Ilup{AmeC6EHa;9SJOISXxZ>NMg42UgxNDM*6)c+OJxkW z^eqs_-Fg;c*(M3U!s-SzX_JK!C(5cIf?%&5~0YfVMq+h1-#ol>tJ6MO^Q_w?xS|&IA=x1LCI{4 zk(VltPhU#y(Y3P5g2PVj5iQ=_Gw3Pr1=ZhPJM`E6+Vc_-${QLR?c* zH~<0x)e|x(aO6{|wfh1O8}|$Vb7VAx7)nSb$H*tk+UGOW8tDYG0eR0~{lB=lZp#g? zRB!q&mfFsb#1@y9mb^%zxjP1kB%yz6X6N@=Sk2VTgMeIA^F(Mzi}XAo=cYMu!k~s1 z7$Qbpuw4tOffvs3ETbM?*b4>lO6Q{UuCUf}<-bl`z6>I+S=|fb_QyYlWK$0;7$#$) zYJ1-ls(YBKagA+g^cPI&n9XuqqZcsc9r2=|P-5l&b`s4!gL%M9W~+Pq=OM_JxoZ_Q zC0S{aCnL-v3e71mpw+R?(snf@o|lDQQ4lfSlEt>%@D*cw;!Sz1N5r(2>FfLx$;e-b zzgaG^%D%lWnWO+oMdC5n7HcdhuyI9jILuti*>?yBF#?27Zt~t-tV%DCm`!5%%fuq| zKudSL3b~L^$Ri=&$q{3v%LdhzNlJzp*MFUb-UvgCF)EgWpHXNK=_epHD5DezXQrcB85gQAxr1O*P%l^O>gQN_VE}o|2M?}r%`8?9b5j+n7({Db> zqFNL=)dL-y@$cei&8u(i%|qEO!qj>;fBPYH{msh$Z8^b) z!P&_#Zja|MQs4+?{_&YO;$R}X`7^-yD7rlV2*ip1hmHxm<_DHAp`I0%2sFdS&M;X8 z{*wN2EjK3-G`tKKm6j@7Mu@DOXAzj#)&OWi=XoNz`PEemtMxu^pz)NJ3y&XJkV-#K z)7ogSYO)@8z-A4@eITS-LOfT0Kwb2g4VLc-@Yjis<3=Nd?IZ!=QccF ztv6o^=!4=UsxCc>sfZVWq2o(n6AU=Rc>mcM&(-rbL?A__cF)#mCV?V=H zz4h{P&Fy%h9C!13(qe@;w7h#!8W0hYzWy&tF?IXNnQL^K7oBvc|#Hfy=@8 zQ&*$m_>4`1Zs$ru&{m;Ob1k=r@~bXZz9ABR5YfR@unc31YfO2%0Hy96Z73qt4R5jD zjf!4udJkdE_Kn3R5cmV|cHngXmfZUgs{9;r0rvR<>S=V(5Ot*uxX5N#u0vhQbF;u& zc$CEF>Wvn|XEtXjK{8Rdv0$OgU970dD0DIYisOTbsyD*7Ee*GU2{|KEfl~8a(2?qB zo{_7IBkT4MZ+^FpmxejJvX;WmjN6im{mI+{yLWj;V6P>nOkwXnHXNr*(C+h?PSTuD zKqfX?b5m({{Qe0SXiIm z>^p`tj9e#^e!%??V|f}c>MhHLJL&T`!q{we)MZ}dgJv6$5ALwr*6*7kHZIB5y}d%3`U=q?)SSli1Z)2v|IL1XLNped znu<%}L;VI0T%8e~64EuNwdHC7RC#VfAUv9s7=7|?k)Zfy-yh*)l3IcBPgGqw+H1n< zTECu_NNQFhJ-FGOw8x0V8l{a4i8Wp;VaA|Mq02*ULco(FTCb7S@H*9gF^+j8EkfVQ zQ4bzyU=cdtAtDxyM=H>37G0ZqA7%b=H2(Ux#1N%NsPzu%QYqBpXF14mMQVg)n| zBTUGC)p7BhvVo#lZjLCWRQ+OI(xt3}SOcFK8&K=(0~b=6!!%r0dZgACbulz`J%5FRSWw75j-k;ochph)YQ`f#}Yp=Ii^vxC6a2fOC>9!V?K@!TO zQZe-6bFIPHWvpxtOS(H_hbssjA*uyt$;p`w%I?KTg(p_C2?k2y(TqOg^1$AN>hoL+ zcIc}imX$dVOy=!@LBsi|c1wf{C-KId-jzvBc`5u~@+UT=gaW9TS<(JEC>xkTw&}(F ztlb2keJW|RxvxKylFja;)^b%%FnB_^He(?gm9cCjo(#SI%JD5j5PnhvJPR7eKQie= zEUTV1V}t%leJ5|k8PS=y^J6|9I31>CuKy9HYG8&9G1m%cFPt|9wp*l)|;?ONsJNYX!frLEpy4ERVdYDFBOPaa#||s5cO}6 ztE>A<4kd6UCg5k*q~t4ZnTodV;e#>ri+mj}r00uQ!6vj~7~*A(1xWt`a$~`1EsWojyoMno>VFUh?O;U3aBf5B>mF( zGP}hl2xhbn7MToV(o6ybZl0^^2Ig*5 zF#OpWYCoZ5G#hdB1gPr=Krd4x4wwDq4}c8~#OdAW>bS6>|EM2JI}1Bj{{Np3M-OCf zrV;B4^?m9h2e60FB5xe{_EGY}>4T?0=QLk4M;7*KNZ8(2z-Waq!<0TmFAsJWmxpX< zXs8~>gsH4$nrCns)h4!?0lI%50A2glr8^x@zqLpC9EfmCW2!V1pN)sd>ZdE{%9yrR zNq|6oDRKQPadRC{x(&)NFR`*zQ|cbg#}}hbOfo6O_acBhp?55%qmaqzD35TtbEsI` z-c1Fag(1&lIJ0d+dX)H;wuCup4hOhT4xo%iiXaf=DZ2rG%;t2Xf(&&x0LS<*;Rdc; zf~P9d_NA*EALwsQP697dZaEOW#U><1Q~XCkyK+qQE4%>gYeYT40e?fmi4V$g{20G8 z0vtHg7of2Do&!c2i=@WoV)Q12-o38a=fBd00thUo;nMCQ*?i_73JOJS^eN=W9`SKe zZ=W(d0zDb{-$`k}asewATD4hA>_r3ZZuG~M*j6{>5ZTSz`X_}1OI?g+S0 z0Wq*MAaS?Cm-($DAj>Tsf2pL0n8;>pL|y-_mE*YwI=4QMg`Nnjz=v=7eL8JTG!Wa9 z?X)T1e{umrX9qhT`IwI8`yIa0$$4t?U(?G;?^XKl65wW%=X&gwQeR64eeJ9 zXG{_$L&8Ox$hQ-bN_C{MpQGrxsOu7MAtsx5kJ z;atgZ{e`pEV|0kdyTTiB&Fnp8w7EcOhu5S9+n-mB`zzWUUQk};uFUiLwQ7;XlT8ru z2ersp1!BfoX%G?6vuK3frTdL%x9Hd|gn#_*lmFFD1dohgr@nc`HD_Hbo-IpC?Iw&z zBkUJ(4Q&6JOk3-ygXtIv`&S{ zj;^W*@en*=U##PaCA`mZMGHmBwhjO*CCrVVzxpg8(-H`tP2il!HE%qB^mi24GqdXk z=r>p$6UL9M$a>O&Fgh_5@jZTEmxUBjX~70Z#&2?^dbN2ZM<;v8Wl4@LGmJ=#F_$>< z9lWMhXQINPm_H>#68-b*E36s=0*7#$)F;|39Z^LbUM3Eq+}tjD!3`Q|fVhCkdExPr zade1fF1Bzs4y1khFx2^_`nySUf7N$-Oric^8_{_cT5xb?uHM2qAojqpuPIxUINv|h)lW2E)0Y`GFy~KvS?}$}yf`gL zxup9}NX9pp@vFOL#c+hrx3?LppDF=iqzfW^~NC$7b6Kq2WTs>?DJ=SM#w zU7qGyp5H)PS|2*gmMK_lM9XaWIE3=H`77agYN@~ZjPbYPvg2{Rd`^BNCb~csGRqcj zWikC;3oBBO5(RGMs{#%N-)2U%g+Y6@PWxf=ZaUh1;Y@3&a-M;9&SAVrMh zHS}7UQlXpM$v&t)!wJWP=75(}EA`JMRBWDgm0-S?jHp~Nuyh%G`?ke~bCoRV2Sn-t{8Tj(Jft> zz8_w2lL1qVEFKVcIzGb*ZK}>bEJ!jg%S2?9P-KYaC(;eQ{^U+%$epP@a!luX@%$yh z1Xl?+{cxj9hOx^Ey7lUMd-?~#BmAFfb(#XkN$>k#Mm+qv_DYwnSrEZZD<=`8vFzgV z#5K86xu5stFr_M5PZ#mbS){hCZq|pWpF4V^Ic)-3;3mF-p1jC_8i^D)_md+Gs(I-8 z*~C0df^HxPR~1!#TXDxdgo6)s{cC?ftzIf?zl*+Yb3vSC{7K?TKe8C35o*XewFM{s=ul!$Y21O({igygy^^3nJ z(&|XenlO2eSx>@qEt^y9 zg-RCbsxI6?MBbV=`$WV%+iWenihBy24PmHs{9MucJoD(Cpwzo$3qt!*2D&iI02}=ir!2XM$mp)Z@Xg*ml{o=JR?`&rR*}|~lXWyrs=XpG_M4sDc zRb82I2K`nQcH|N73x|>m|Bu7XMfBjYO^4s)NneyTYMPpK<)DK{jcgvb2AFNAB~L?Re|v_PD*` zaP_NwsCHQvvNJ;cs_dQ;)sMGBUsoRzy@1_U%=I=w{c^!3U!KNO4FGt<_o{WZNpq-V z2MJ_`+M@`~c@LGr+O&R7pCL=?Fws2Webgk{xctc5+$`VUP?Nvp^gfQrLi8@5r@v&J zg)*!)dQ$q5kY{LXF3VNar)xykhWCI2E9)I!b321N3>dN{YF7)iWeJ_nSqL zw>#Xe&x|w0`Q8Q8oNWKeO!T{DjeODMbfu)LWil+qy$D3)*hxNbM+?N7*QuJg$bq*{`hnU{l0i-fBy?aHgK6xY&n-^pMC zq~Ab~Y}o(0d?PtHMI9L1_4~?e!dccFIULC4e{$g6o}&|gG{?xHvA5A<#CGB(l4qGuYgSr!Crr)PD{VpBZEljt|! zfAzep;(mIz73@u%rUgh~F8KQwmZWq&bk>80X;2^e&?6cwipP=VM!yhe9XkT67hz#>DD1`l6B)_8 zo8e%8M*mmW8hZKeDkn#ag*o23txj%R`-2Gt9WyB{sn6t;xv*t7plII+9OS5)x>MDdUAr8P-Ah9semTltAX~8)qK9dy z#91aAN+ex0Kxm-OTa;b$Nn>7N!bgyK2{)r`gvGqyhMAQxr$D@;Z`ddQkU2@G`D@n= z_7j?KH+ib{@Gpqdx5P4P47Lp18wt-&-|1_3gT#C@s_ba{#TEK zBje3ZY=~S8w-~dUDJIW-jGWEr%Hl7T+cBZ2 zh(?=7+^MZ{N&jGGXDT`*zintta-!m_I2Exv3aTp#$BKDXwnASFG*X_{Lu~cl#X0IS zpk4iW;@~=BQAnTCv1l!fUgCvu)KnM(Yq?T*nb$iCl2VoJfPTCR)u#nJgmrTx#3h0) z{L_Y~?Wj8{2QAI4$+Jj$Ax2z*{SMMOWs3a_9Rg=?8ilm3Is2Gwkoo z@p$2a=mnMBOYWH|2fJPLv{|iX`mjM~?!N(*%YWsBJssfeU;dTuLyD)cmAMD#n=1c} zp|j=b-Mr|hX*L;XL6|yNLVE{^did|DWcCw)8}eCxmu$IeFFRuZ7N>}_RD>Tmc=#y9 z`7dvam{A20!c#wCG7u)`VwtMq8Ssz|z8c5R|NJFFj;VS={Tn&XZ_Y;GJt`T>aVklt z(H^&fRypOP_{_<4B6F?z|H(DTg4O0hGUYV_d;$r7YxsWq=%sJhouRN zgjyuKDM$kl_eppXFMUeYCf17O==y30*8KEv2RQe|*B@gI;;b2*=(dQ*L1Wg;mSI$z zUOHyCkPfNO_s&jMox+u`RCn?<)46Im`4IPy3*lg97{`PBu~`dJK3$I_hv(Kq-G>v_ zuiu^JI(j#J*7I!wKZ>(+onajM3vRX2ImGPEkF!MZu$g+fh{~IMs5}ds@-cgbv*>(s z98qNo#W4_Xv&|;@s52Vhe@w)3m}51rv18f(=e|6=U`W$OLI%GC%Gy!TN!$MkVlH-reFow)Te`scufAg#_!*;DK@gLv`>{1j&)pCpd`sS9Ys&# zFF5paf$tWa{hRj}L~YMw5zLk3)iTaIm*^vzH?ZEQYPN;>mbU(_{}^1b;9H-a?MSP# z^9*`Y2b?WFg&`0!-P;Rv@~Sb6vELJ8-+xicVGvM&*qGza>x(;DSr=oa(h@oEc)Iw; zu1=AfpLn&vCx)aGk1i*SiTDpd%8|NiX?@9ww064sCu*!JkxGL6wY`+iQHTr?$(}oK zwvQsMfet{n1*2XR-y*h@hvq^u5!FK%*pv|(Fl1(6n1zo?&Iv(J!w1=U-w{=`afD<2 z_v1YSp|Ycv-9HG7J3{dAU5dN+kR9#Z{i-RSCJCyemXo7XaB|ZE%yAK=$l-6_$B|-& zI!e}Auv(v!?65F|U6dZ7l3B%*&4w0?}(cz)MvJ+u8FeNk5>2>BtI z)%$QqiZntPFv$lgDu;f2X-vFmPOt=a>a|HE|HL$v8HoOmKHh*NgEbTS0N=eXb zK@Dyoe4w*Y$uXn9j=i8`?dB9nY)%Z(BOM=u4!im|xG4sHY1+S@L=D+ff0s4Y%p+ZpRUyVQ zccv~6FZxGk#Eltn5bb*>KVktp;}G8%6Hi^tPD+eRf5FoboflbBl7cX&?S4uUu1Uj9 zj;=~wo&gr37)HDzcDb{{|4YDI(?~Ebnu_NdUK^e+6Zb+ZKP*$X*+cH(!SIjb!|2Q$ zMv6=Oa}IXMlD8nVmI#l2pL~n!%9t}739C%~cN^;$_WijB5PZa!!z07mUOyh0>BSU> zlMwsP%5O)nzj1v9n{f^}%?Fql_1e!X@JqyA1Qb}%5BZ~vVfFTQ@hhVT44JvZGZ?RB zZ+O0z@Gr{b;gD^_Z_Xdwv+5fMGCre+5`+kcnKww}iU9 zeP7aNhgJLSg<53WNMiDYOpcqqS_V#6^)ww+B$lyY$>Lm7-F^Sku}|R4#`Lj^3J7Ow zL4aywPH8})s`j$HQ|{DPIW$iFHW!x~wQCj_*;ubV4|E#_bk z3>8SL9}po@kdi0prx^~ zJix(%G9YWvqjaJjmlBo-_X!a4A8Bm|{7jB?nWvbq3(ud%xzjDqF7IT-XTqO|v~W)P zBbzLIvGOrDj9;g;1YXRaqum8%f-^*IIe$0!nEU9aNzjbgUW_n}qW<|AU(223KB7yb zygNh1G26Gi<>Ys<`2ew#bLWr#-zF92d|8n=YTZc_t!TkS5v=$l$Y`r0;fqQyks%0P z%KG%!sm^5rN?}pM&F#pYOlGnno9jkFk)fO*=lF>WDI*|Ui1pJVcIkBvJ;np#=3?} zpgo_6G-SWXm-p1;_rEWjeKGVB-^nhw>_1(S_1)q-vOn+J#a3(WXGS~R=z0d70}i|J zS8sf=KBM-ezwiNBqp4$+$8{Zl2ii1tj`O})j`z_-+L^qmIZAFI)f~Et{bb@Kl5JE2 z6*|10@VU|xRb@e!AP+f@w2}%|e-$Qvchfz&qijaRdU+9PpMO`$JU^Tm;c=9Qxc|3B z4G#@i%mEgh*HO(lPeNE&id8Ku|1Jf13A8AgberzWZ4YF**j()Z%X@Y`As)qN(@L2p ztMOJt8S=<=?8|v8JPshDi}xUIo!ZI^B2g=`*97InpVYx{iNv4$ai0;Kw{tX)?-Bop zH+YzF)@w;!aGEqF!QtuMP&`)Pwc|VQ%aY>oog3=ij0-yVHF2EFwyEi!e8~lyH9je%ldFGHa^J`n*e@v3&fg}S1S=Czo}4o%2+0+uEG?-+P@`039_bUA*&GqtQg z#VBC)gqw0H*TePrey@EvFl~`XbzkxM8Mg2Qnr2Cgz`{t(hsnz2lAx&xc&fo!|9F%M z;1=_87pr4lmQxOHn3owxs5oY%Scj!Z zo|l0(WdVq5ly_jiYUZbPyy!%1=cR^GIHNK$3jOn)Oc>V+P0E^^DQ%m zS4M6J|E={S<^v{GHyvO zjr>L+K3b*>jx08MHv%4vrcYjf=j+4s&}Cz(rg>-e-W_PZ>oG<9nwu@$(`VbHBkzXkmYj z_UhDFt1P+)`L8DX!(KTymEXVox7Gddx102aZ0kwrf^e$m3l?d4@enGR_$Pt$!Ut1{ zq=uh^Azm+@a?nT&7)Mmhk;U0K^#8F>e{|}=9m+woC`fB#kY!n4E5&LbT^*sS+0;O*-rVR<_qzA!c)HAJbTQ?r$XN ziv~Nuqblr^`!Ro#4;z~G5vK-|cA4tnWF7&`^u@(2gOP+f(#2{XcXGKW^b`Ge<4HUJ z;W+Qie$FOOIB#h`_kiqQOf)~*)9?10gIUN0ZUgKj`8PZMH`uVVPO185VpF7IJ|4&~ z7%2IqqO~^b;~!s)@m*c^j|UXAvZ`v(6R&pe(a{F3bQt_3@Nw8PdDSA~VUQA8YW?=!K?iWX(5jqxi8J3po-pHc32V8vXdma0?6M%ZVLi|~kaMAru( zW0K*uT2foa!Qy_xDe7_Fq5WWjvx4>J=oM9t0j&?&kGQ6MrqUu=>Y;Mqk#%FWmZB-^ zS9E2F_n7^c!&|kT^$f1|DQ>(e!`-z{48$@o7VHt|A8K_D2`A@}7X48%!6~JWv?O!D z=*#WN2gKX6W*2@`)wR`@%HKPm||iu{@ujkUVR!^Mg2{7FY~l=(Yz z@yv7F+F0JdBSbgMVc#+}0h%+gl#accpU8e6WOnz$M3S{tr6%#J2o<^&B=ILJ9oUS8 zeU=0U=OtTo{m?v(-Ep(_-(jLAo4KaVjyiTx*WBIUIX%mHjl?&`42@!}O(DkAM+t0B zk2Slivj_`6&e~2|xDw6`K{Rm2G^sK5F;aRXb^$}$9|D#=zU6lLIgX{cy-kBBu-SDG z#JlzTS^8V`U6_tviuX(Ixtc%YS~NR3Uj?>HI;ILn4DDRM=>+?%Y8~_fg097g?zez$ z@aLw&xDCg>ARd5&yZyS!0qEF#obSSZTO>LfB@1^tr1uB z%2ek%@e2b<^XXH|h#~DfELNOfcE4c{v}8<4q9*ajpX|ba-26H5emaG!!Wp$_HtnAp zG;(aKcp!)rR8H}pH|6v+aKsE4h8e=Cxibq;1<6K3$fa6)SA%$n#OTXK2g$7sE?t$j z29qI7!`Y_akll7o<3vK+yEVh3jX{;%2uRTE9epul7uZx8K|YgisdwD- zRxiw@rTAqxCIi^eSf9O_6}V-9x~gBt7RjWK-AnkcQb~c@@MIS`Yg&--=bjj|5#b7i z>hv5Ch;s*5IA`&EVdd$&S0Ix#by+$rl44goPszQ=zU8H=U+_b$B|h%`+GUnWJs`XUD!(Tcs6@>XCh4Xh+Xr8ufS0fr0K_zb+XgTQI;60S|t>$;1v($ z9xh^;i67qjZ`jJHcK4h-&Y?<8{V&4WB*Md_!GX?f*hM6oreJl}jMtHFAY#H{?Ic^X z24(VeH*vq7KnxTFw1z>$rh(R$w)reoT8a$@FXYsdE4AHNWj3NREkBqrhhI#4m~w8e zEH~q=J=RxK(jq0N_^sv9wm9TphddehTlEI+46zi+BKUH@>RBkhE6Ic-j>n{>(JiV{ zx2WUe)0BPN)Hwb>w zz_=|8?fxH8=N`}W`~LAtrBW$E<&=b+qa5b6basx&nIsfunDb%#ROC#~<+LI><($JD zwj$;%=fkiVmgCG}Haon3>-*2opYwR^aKEqXy081Xuj~1W=HH~xK>GY4>S^X$bB*3p zI!^er#Oji8WY%C`Mzsnu8^R_qHBdAu6W>S$qvXnL6MB|6V4QAKKcSVfi{de3M`Qmpk6%xi$V!T+M|M=aH*GkJd{*A7E zdJq}#=g!PGkqV*YsS8Njqlqi22s5>Jm9+1DCN7|0K@D=gsedbhDSGXMtDNu0{^HcG zhPuj_wsQt4p~$+{3{T{vn0p5E{t8Zm@zVxV*yH$b9#=4ii&1VPLa_R03zRH5a?bfQ zAzo{a|3<$)d-&-6Cc9tcu7cS8o!sFU()1mLSJU!`PWEdxecCu3uM-9&yozh9{a2N2 zz@jeQBjh%w;%a6a>Tcvxf~s_+iW>z&S5EXVwQ%-Eo^;ZllRLGO$u3r{lu((P4egYy zEjahRj;PE4(0K5zUcUkyFiyyPv;&&V%pMrX-x)1lR_Z&s~pMSbG!JlMuk`RGe)i`f3pGqF)OJyt&4i&>;n;?JIW9N_n>5&7~}VTNj` zVrNW-YF&<;%gusFVq;oPraaG{3{8NxRj4=G^vU|f)HrsT>#op?}@r3shizs>;271lS7aB*on3B;ydvIHrIaHbz#2iOHNig;ry=`+O7UK z;TjT;F7)3N;d#O0gB=WTBT^Ksw?S`mE*(yL@Ai&!-K01bHy)F_nxuUX_9`gD_jS%& zHF_NqsR!2f&2WG-Tgd8D(_UPQ@mTRnOKF;4h!jHE%d?T7Xnm(F8X>2VWNjJ* z$*KBvh`!wiiVT=0uM|3$GzD2RTDF1)Xyv?FE~hrat#``6;&;nY14|;e-!BOMC z?HSr)6Od}Jq&?Y z4|t8&d7# zH8~4UYK8|JbAKc~6nTB4LJ1|VJ5ge`orxDJe30xcUXP7=5houHwG9*xpC@zdPG<{r z5|dHl#Dtr7{k&ebSO$guQOYC%@7=$~_zj^e7>>l1RzE{=yZrxPEb>Zge#~`QyEVrN ztUamGQ%A}UA6FnZPMOdsyt$~tu3*l%jWa#D*T;$XhA1mv`LgyBIq$3-Gzl67`wSh# zDc%a&0Lac*I}9v*oS4flDOxrWusW4q;FX0c%~>~xmW_;>pb6);CZLm8i}`B%Zb$R8 zEhjkh!4*!ho_-0T)RL)8DTPUf?3p~>WuLsVlt?7mgc+;&!R=tXbLsWMZ4bPDW!&*``3sS#xFl&}&9|hOUA*Gj&G9{c5_Vz# zPfOJm;m}dE_Hy9;>972Wq=Q$d9Mk=y6DukdvdHL?`#`Bx;#yurn)Xcopq#eJiw*(_ zXiL;Na!BxB$Jc`sgJzYF3;(30b6NNl4T(4H-ReBZ1PB2^<47S=>i$A0@_x}LnoCyh zxg}QopxOq|7?)pi=JlkNAvCMhhnPf;hFwis``CZz2vaHPzj=KIsgzzjhRldaCT5!x3` z#m24M6I4>pSsRSIz%^aq7v)~r@=s9=tk8h@1nEF#MAFHfaNCTPnf>v7+eycJiRdH3L#`KHNkyI;Z{Zp+!x1lr~|j zm5s5v<*|G^3-e4zzDaKusggR!pwkluTn*p=>c6|`d2YO;*({RmfaI6Qg~Z+Or`GK1 zw2clKon`AW4pc`y{mLWk7j^22cIoXJta^z|PJ}7Tt|v^(q5c^oy<^E}{6xXplNghV z`*0LW=-E3YV`n&LAo#g_{Mi`|SBtqATzit1e(1i=Lr0(>Dqgg|v5D4na(9em)_&sb zT%!Aub2~ACTXksM%iNK;Wk0HFr!4|PbpE9#gj!`PXeUYu zIni{iG|Ms~vBUhu5w|!JXb4j)G}#dDkJ?J%QjXk0)jDJM^oz|Jc)s>;fnXh zQ~YkuBu0rltxU$olWMEVk$3i(qDT|&vj& zHZ+UDNY$x|(4Rti2yD#m2<=hkoERTA+0)%3rmu5m|DkpM&9yWx1T2c8OLO4|?#yWi z+n5*46k2sM*FA9oEuzXh!=2(31)J%$@y~+X!4w^`f~nY1+dE!P9352A-l_CpEq=7( zi;wur&*ZQ*dsX$}Y7td#yz^AF_07sE$UFHPyw>eeRf@gaSv#6uTwl*qS+-FJ_3{%< z#s=&y>Q;RUJp{T6j9J z6+5lg0v6P{WsDru<$Ray9uw`hve=z^>&A`SY^=pUgyiK#I>+12o%IOv!6zl758j{H z7|JjI+V@`w?vKI325zvy7g;4bxSfn5ciyhhmZ{XU;fX!f? z6@R;ue@u&E@l3cS!)O|R_o-dj7r?^{~Tg{<*Xng z;Sl7~bA3_2zEPKtj~0&4Db20`IH437QyA|5&k#k|a-MRtA5QU6d;g5qeER zI8EKDwd>azg1loYDNdTkpdUNGS*N!{f)lU2bog+k=IQf6Xmiz4dmGt}s~44U9X^2a zBDyJli+UGaSTM@SV6IbwZ53}%Dm=L0c&i!;^TJPaTlua_)r8Fvco&u9{Di<6msCi( zx13t2uDi6G1KY5+5Fmo7Hhr2}*yraN<=?FSOmJio7_ZH+ z%kYS%(U~SC^tF3$#+TZI9aVLc1|5>T&yv|wD%DQkIi+lh?@)zTMR(KF_@0!H9d;R# z)<++F-juUZM~+BvfLJY{)~fn|x{AP-Rga;X2xo0t>dttt+32uJZVqKVe1PiXSij4U z<5mNzz_igsD@)S}TGE6`zESh#n@y)OpEnqP)GZ+8Ud3#wFK=Y_i zxz#e&OodbuwA?n%r*Pr~U1`4MKLQ%DzLs1+*hE#A)_L%4Umg*s^Uw|Vs<-7nHg)6E zRXXv0$JzzL4u7KaXWRkVe;W5CNt8KI&#Vs@%fbHVVmwRsqEqE?S8}lVn{WQBGIRpx z4fLKIy{@eJz;`$Qpg}<|zYY!zL?+WhJ(>0n_sB}BTTfXI!f4=ux=y7zmuFA&}d3*&>I780eRKgL#qM_s51}i! z)MHW5Lac9e%YG6Q#B_TqbZ55y0Y-if8^dbko&HY=Uh<4_Q<`Ub3nB%IL)sVf2oQvOkS@-mpo-J;1k$pFlbxWl|efcp;9SH}k*NT=e?cjZ1X7KH^DZsHLYOsnf4%Ov{f z{>I7_uvEfE(3!H=;ADry{M0Huo$HwNxNPm1Lh*4*MR=Xx*ci%u#^x&8W1{vuC9ip< zYaZ_IYIkR@i_Op+o4|eTSKZu+De8;ANJxVbAz>-q^SDp?Z+Oai<1q;*{ydfTdE;fA zacZ$HjMM$Y#FT3W!=`@UysxEA&9FVNPv0WK)QRstc5!M z+M`d4|I=cObi3mR8_ar*JcSdXJNxh+*ww2gLF; z1Fh>lONKVJDjD88x4~k>taA<)HHiZ+RKNPkZxr7qps;@}5*Fm-| z$f{TGYw`Q7`M~pq zxJCr}6VB-zfkmP?au)@TklAq&t3h^1_ug|NU&6 zDE}T6_TT-rD#Is!EYDfR#Eumm=X@SytBV5x{X2|*aT^pOq&D8LdQGU;kL&a}`y%5F z7az&CVTnJI!r;IK8p7=O>c`01%8tLobH+)H%X9$wPV{RC;k@*NftCmG?4YrS#Y2t9 z#~r`r8Q<7k#LpD!IQQP)+G6j4s~*2Ijjo9xTUo${_`{ zL3zDEy;bp8cltv+E8r9xXP4>?`#2!V4PVy+)iWj6{cyET(OX7grE1ViK+MazKUif5%Q_=C$Pbae{`5kuTGtk{M# zuU=%oiSQdGn|pYg|F2A=qF?WYEQr@O3A1x;T%*>XHbCpc4x`Q_p7B;_cxk&cqJFn< zlgWh*nN8H3g-f4GxR)nj@x?iO@dNthY+|tgU{aEgD}ofca*rHva+rj`h2GkCVg;|U z(iO1Tph|y^7D|GDZvE1U{lU)z3+8ofC6#~~_zZuibr1%S-cwoQQ|^@@(!BG+f+zVHeW7Gi#aRGll}ZXy>Qt1n_WjbOBHW}Y~qk)G2Y&68wcR2iSA zV_c|}uiq(qk|0^oKpC9#+8q`tO7Y$FVJ5+sYJQYfMCt11e9^RN2sLyvI`;xFUP0e% zBIQ_Km(5&LK8Z)*JhC=m{EHz2Ch6t2X_IG%Js*O4$BYz<85_lZ$Pj5a1Zu-}kn|S2 z-81E|5qiPJ*ir$zk4bzmr*j8Rs9(};^gU&qS$-UGFk1` zV)*E}D-14z)c5YdzW!zm_t0RLaoKU@*dH#W2-FsXr&=0_qvW!f&K~1fZ?Tt58{%&ew zo`_(Jh}|YAY+Y5QZ6m}sW=XAk9}k;VAiN75Bu)b9>!P2tk#>}3oNphvX+ungITalK z)M2Dac)y7`ACLpeko6nXZ1@QgOY}blQTp7w-I7rrs_1|R4i@HydWFODd34j8#NXrC zdg{_=@j%+S=Um4b$Bt9t2$Y2#UsLiAfNWHxSl zElSf7re9xAe1Pn7jPFf6Yw9{GGJXFlxaEU}_4};E)<$~`Zq2Eemd5wf{YOxl0Yt9T z&v%)Y$L`7G?7uhk0-;yx%dL4{LeHLwynWUm<~dSX$a5?IPNP*3+}a?X&tahZ?R9cP znlA?j>f4hPdcA>6t4JlUbkWS(-Adt4-J-uaw>dbOmsaD;S``!L8<%GCT5845(^Izf z7Ou{YZ9@)TZXc5Y8Y!nxOG21?bGlhwbh_C9%xevrM?wUDF3;Jx?&eU5Ei^9fWuA_1 z0Y4#z6A#KxwvAoi*L>`bdHk_*<*SdwX_-BgMU9u8Q%i^GtX8sTp{Hxw z3)QmRcaDOB8g8d0UMKT@R5^nvojl5xZHyP(Krs$GXR$eUqO4-T5Wy;wsO;Fsz+V7Z66yn>&j6@R=~2+<$ODIvsBi60C2ZC|XL5wDMJQZmR~#se$&T95@gKJb1OjNsK_i)X z11K<3;79J-aTz#2MMCK7ql|z5)i8e*71EBm@rSD-1s*n1>B%$dYj^?`(^#OIx(04c zXNk+|w|otr{hMz6z7=bYjj7wbRzF(LH>S^bup@=z&De4_R=mZ&dv1>uud_5z#8%`s zU$4;Fk1;-g0&Y_FLzj?rq|FLP7HQ-r=t6>;dd`M=f@X>obJaJL9n z2C48Q28diyi5v3DztWGM2$O6YtXvF=M%q;4RS_xzT8^)P;YbKe^YWuZIkhMzWUKM zY*}@-a)_(WPLs&NT4 zK`@`@_`C;7#XYu*B#F(_p}6Dy+htT1j*?2exRU5EkfGOsD|nS%W}iv6Y-C5@BQZUo z+}|65#BbBg7gG;lB5Uyj&W{4ataN(X_B%Ejz3HdBt3?_Ht?5~=xsjwen#L5q)*JM$ z98Z?P00^aRk6or=xcmKt7Fc}e0LD2q(Ex+`j*ERu|J(7pjWB*P_krNfKq9~RccQA} z@D_+((^#}eS%H<9Hh$#`yl^UDYJO+;pkDFibZT?->^^chg-3Age2l~NXID0akB=bx z_RTMwy-KsB5cRR38uOCWL>LbaTwh;%Mka^4svpp$QBtKiW4%hKv!50{h24H+<|Ca! z5QR4IDpi`@+mJ&^4T}CPkd6c2H?DQ@EqOWF1+Js`Qe&-YKyZ=CwTl27<|P{bZ)e$rRg1 ziNjNOW4hqaCFQ#Fy(5GRh8(PLY>w|K$?vY zN>K89V3e`YmD##rO#2R7>C2g~3lyCczgTK4$#XL6hSM7#ps5%4SMjNd+7VhHu%Q*c zAGvcuGId*GzT{Uo`J9(U_q^miGFLj>B!_t5fWIFGlm*$}%(ZzxL+mQX^1-KV}u?~0phdlT%A z<`Ww-|4HE_izjMiemI(owW`188fp|7L~T%`DpxtDM1Q*6;yIlzxi6%U2i1?wV0s&)u%nkNm7<7#9;_{t8vlirvzc(hJp}y zTFU{1AD7S72L~-(W&T-;+Z`d?y`^qP8VnPP+9>Og_W#JdR+v&0Uq3%HWd^}Ih$q?- z52Cl2l@AK(10J9yG}JnZR+c+37+g*_Q)j8Z@v>jiA%>w@^dz8s9)V!jJr)}lzw9Rm zkZ5_otdaKG37{Q*hl<5n9~h}PpFe~9|yc20_tLtBy;q<_G*qeVf z%5d=B*+pJr*u7)hh$^kOBn0cDgERFz+r1o@-_V{O@n)y;$58Go5Dy8LiDc8un_AZ5 zNmwtbw)C9hm2sk7A`ZMfKx@s|2&>515KDr{24=U^55|3haiXE$$MhF*_>UQ-WmE8D z+r@%{f;Tn1Z=&75CC4 zPkz+%$39+Z_Rbz4FY^KXi50Wa+q3w<+>KM}bm(!JXuu}vAnJL;r}3L9i^uo4yMit% z(uIbXL_zZ^xf9@&CSoq&ZK;8Ys=*gIOX`Z?7Im`WX8XaksLh$z=zJoynay)@8UOb2 z!hNA1plHXIprOV=i&3_^qLsx(#ibr;`AFRNdF4vT zr8XbrQiFv$a^FfQ*l2=E0ta3!5mp_NlF!Y2g5~2Xz8|?`$ED^V%~{f*hGe9a=$*)_nt9LBM?37GtdbHxKP6C1=y8 z+d;k6((y|Qo_khjsGq1M&>c<}6Z?qV#X}#hdr($|*_8N&2iWIww^AvE zeincW-T%~Ev8uDxfZiMz9Qq}x`aYsE_p-oqk@NK&B_)T9ru2g!l?DYXUj&cV{H(4@ z_+`jTR%&D7j@L&^=)|&Cm@f0+gxZX+$+1Rrsu7?h26H7_zksgjT{K9HCk?dh& zEPC)%um8z}Ny~0}<8nICZzDiB)4HFaws8G7rzF?5qW1261_f&5STG$ngwNr=MHB$& zQHYZ8KiMtM6{Lez$_U`}pYM#JZkX*qk)f(mxNV4p25~damPJs+z~OB}0{9ZrQJqwYcMgS0R5F9}3$e zo*AXBrqzh!&f!KOuuDw3d@%Spt^07)G5J`w;0r~?L}^T9lk(b;8XPvyB^i`Z;h}_k&<6EhrV{uNdAbe2ijtmK46>o?LZvPONWy-7C~DsU}heNJDU> z_7r2+xnt@fvgnKAug23@pp$@T8q{!6I6B@Lxl8(VmMnB`#6&D$B$gZbNC)AIzAD@| zHej-O^F@3k_w6*r?b%<-l^XYLyvR9cBL4dOhE=3$IemG4;7tI^rO@$%j&NQP?y~U5 zHnlgv&dmLLNbNfVDvizQ3q!y20TIxONna3G*KUdS>*Ex?m{3m|?LQ*pBEAv=ZmE%sP zV;m`DV(QD<49&6qq0V;ihs-S8a1#`(mQLB<$8`klOv(Mq#`r6=fwU%3v1|xyi>}+4dAZH z#;Cu%u)w>1^^#J0NDA#}{V~8150o|1BXRS$eshoz9pegJ*;2)b`9OpKH<-bvMVWNo z7$Ysm2JO(v%R3pi3sPn5_9gD`mfeB}<#>kwo>!9;Ye|Z{Ucmj6j8SJvaqaA&Z-7H? zEfoLpyI5i!%^O*pdez&8Sga)`Jd1e$T_3lcFmchEh9)&GQ7E&>6rJ6DM76f}z+H@r zb-Wrz7{#X<+{_80DOAu5Dvh8Cwl`HMVLM#Nwx4DzpTG|i2?(F5wRXUD zsA=8Ke9$SzO>sJKmW0IO)3D|IVwGZ4KaJVufL zOpvXDihhBK^0|pJtoFNNzp=*QTL81jdpczM7>$2;x6WmvCA{VwX3Qa4Q&^4+jmHj= z1sxMDTZjeSyc5}PH$vg-ImZ&n3bFJ^nM^15gJ;@xc+44#UAGzpzkTDV)+xXjz#$Ht{G+9 zj)D)8dIIs~0lM(Tl{+Wqy%3P;fKX+Q3G7X#-3AG3Mbmyf(XYOb8 zsl8WWJJVuN?5T7HYSI>_0%<1uLpyrs{5+IPt<&&Ny`aLmjg2Y ze4UBk7&^^LLPb?Ij=a)7dHyUEky*_^s=I{uXaI%)D0TXXce~ zY;{3;Pp^mO)PYYqKaEeZwT#Kery-GYJ>?wUJC8G#OQ|2*bOX{y?U-;@btM6Z*yXI< z56)cR#Zuo*pi!;i2>acB#W0@1FlKMQ#qwb&VFSf`BB24-u=TP-rU6-tB_k%ckgKvC zdOf!bzoiH}@AS3xsWa9NzEy*=$luq;)eQzH^T2h*9unho=KL&zd7S;ID&^=06WCc0 zwgluDw1^MuScmd20P`&5I|8ynPct(X;ELEX*>4}fhB=|N&3nv?&Paxfc_kkTpg+rJ zoVYMp&ec&7n<;R2l38%d^Y!;>k>&Z?v&TEI}- zvIg@mw*(o6wJ?a~-|YR8oV0$@>r6t|e57w?cUj7lBm~U!q1KF~qnASGLRjb)m}x}A z|1$jyVa`(B!25@Ec0W7*%1;X&FobzB29Zq8&PP}TwD;5&_{QKr)<2%?;0@G|`at}>ERg>g zA_z-wMCFF(#%;NZ;p}Me`Ra$bL00SRnOC&QI?gnv8@AU_KWU%St@L%8qJb zrV2n`Rc1kNLe`$Qd{#rUexjfj#I$Azv!pUy1b;AGsmbC#2e4xnW052VzBj7yE6Ip| zK`duw?f%`uJMY&Ng&XVgbz>iQ=vCJE6#aCIGDBt ze&w%*DRCT!_GByavcj(Jmps%->hiih2$JXaWlVSLRZ*oC+sV-08DB4I zI`#PNgZ9d`T^`_!6*q2G%1 z4tUcz;)DUc$`QLEbL3n8y zPllNYjxbOwfNtI-tk>o|L3veq9^kMOgFX|H79%b(AdCKu--SE+#vj&9B0woTVBMLcr=hn3gaSS4uGF4 z1jG&N5BN8gj#G(6Rfv6qfUVCMe-0LVBzvGE=q@|?R4H~|ppXCoT`889dnUx89@Of5#3fWBT}tiLu^%Q6F61utUbh@L|NDSJ1DJcORs4iRSbST zjq()n3uGEWOC3I_p|$rD@Yn_n*@CR;(>s@Ae+~jF?LTjjN5GSz-GT&?Rxron&f=df z=#vEK_(d$@p(AEnJLsiv9pi?h5|B)4<_EKwmhlxj-FM6 zfLY;AXxie#y)*euk&UTO^0FfTCa3}2LEZgO;l1qD@9B0QR{W4U2Va3_x)hlS_q7b zuKGKQ#Zs)V)UrRW!bNt~Rd^NBeDLrO6&yx|3M@-Wa_!*QD=fXp?XP*;U0?xQi4tEY z&0Jz1NxpkKHQ_Ng%_;tn>H2GC6l<}U;Gm(apEac>WaP3uuQPsZT{*KUdrrVi(sp}~ zL_2fvVeYv6yJ#0l)xPzYQG)1F(xv0;7xhHCWnJF+ffr10+0b%i@T$Q^>ZG9iobB9f z&)lv`!`B83M-n67aJCXu{F?ko7sZj`|E%JYrpH?L-LJX)-z~C5ztrDrd7gOH!bS(g z5(ca;0wJdhff+?Kcf0DR_vhl-If6ME)4U@pg+RoriHg3s#kK94JZEPF)OOm6S;gK=Hkhf$O+0Bi}FAZX;2?HDLc!i;laiWNQdpefv!QPpI*dh7w?>SWW9mdBs zNiH8l{spI+b5J<;*KIkj=u;1te#Js5RQ@Xoi6}!U#dAY3C2|+cO#ZX~ukmdEiP$Lr z06!^C(|I1}kh<}1iH6kYAYpE(rHR&;GZz^rrw?C~4=Is*4!eC&^&{-4-^XF8w0aH& zF!LTgv&&+i56>%j<*O}O>N-UqJ|^{w!}0wVhoHgVD@5JSWIxL{AF@9QQNIP1arT~; ze6(Y-1w#r02N$uxO9pp6S8^f(3tZkpXlo};h|rJoJYSz>)zT-vbNOw0z=|w){tPF& z3(QKm^Dj*}BD59kn??b9bQr2NvULS^#0#~=nOaZb0$g=BsaU5@#0ftE`?eQOth}8{ zRwN!RXw3NleZ}$S#_WFH&D{%|Cr9OeY4S*^cXx~9j^9&ya&QD!kDg!V)O}8WaUuV2 zy1ETm;PgGqg0utGNvZW@6^pgC&RA#QO6u?jiGx?_(otdt^_{XccVXHfX@9k zezm?ScdVU}$yKh$0-P$rn~Ze<%g_D z^+;K_^AwYYGfce?+ZNW`iC?WErqF-I-(v2H#8hq{yv^V9mx$0#Q7?Tv_uw*cakcXi z<_BZRXN_^;syU!

(_Q`{T}=v~IOex&l8ph&v^n>D&?X;>#~(JMzsGK3s(Vh`!tm zk(Rp>8gUKsElpTCpr+BRbMRV2;~6t4BG)?au_+-~i@Z9kRznD28$5=93_R0Baipr| zA=XXpc1oAzZox+7`m!<0`oS=INbMD%-MfQPr`CEr&J5{#_w$v+_rT4*?%X0rEy3SfAbZXCdc(%o>L3Y@ z93NF3WCLz^iWT&$U(e>;v`Nu`9TSNS>&4rhrdfSbkj(J>q!kDX^;N1AGZJ}^#HOs9 z_30l&FTAJ-G5!`rtoL|s`Bwab=g{ubx<4b+UxOV5?J5X}mRVdBuv{*N-y7g2TqzEo zw5`3(R#JmsoU>&ukAS1W)_>-`M45jT%ec0&19+uykpzP1!^6P$w>xxfMH78=gQ)o9 zmCLQK&owL_H=jc+4-1Puu04lj8n@J|%e`F&T~sh2NfwQi5^Bx@9>(t{N_IZI62UDC zbM%RFVu7Ej1O!ckJ4*;?Qh1h4#>;h0_@rw+?C0obv&AfZR$}7HXdSQ<^M1_h8v!EaqT+Pl5RI&j{lM>|JvRJ>4f#t1(-F0#0VVSSxAS!0 zn&tFrIh)t;y>yM+BD}pd5Z>o&?0j~j$Csfvp^62Zuz){)hZ#h}vyj!s?g9neVP9G` zDn>@pxn-5mjpl&uiJ9k!-BesqIjMXUR&pl z5TL$JEfUtiAl4)Bo#=a4)%%UwH&z-Ah+TY_lvnRu@9KUGqz(T#HTO;Xk!FOUPCX%} z^RWB*n7sJQ&+8wZ&HOx-FPtMb{onRU=zXV5&bQZeqM0Le1|XC3m9ZS>u<i7-e4e4amy$+Df!4lGuS+aajIrOw7~Hj{X%lZ%7-g3y-p zY_kNLJNk^X?G0EK0JCpD84n33<|~-Jmf`E8oP*$#MUl~eZV7CJGallNorrmQM*}%? zs_rHEW=ieHD^6!Z-U(H_TO0AyOWEL8g<%c$sMd#2a>|Tf#*L!6-YHeN4abZ)hx0Qo zT>5G#Z+4FG;oBpGv55G}+r=2)yT6jLcO-A)1yrJah7WxqTL@f^oi!~;Ig#Nwt!vxs zW-R0SeWUHQcvQ@%$qRd?%B`+mzIBO+d&f0c&Z0tqH^Tt&UG;8ap(0Us--C;cpOIwM zsIh+aRNg_X^+?dbglg-(b2ITc5!1roWUCuyj_*KHpsdQ|*Q>r$`yt9&=C?I(6rD5A5T7?$K$t0Sv+ zxb?3GY!I7NlZ=ZX2Oa9!Q8meF)~RCI02bEldD21l^UPEh2CkWf!rk4wCtn2EJtX21~3gUDWg(F(-`}d?z)GR)akYn!{ zm<%C+5Ufwo^ks;uFw{(*VKzti2@;5nC;^)f;2jc1%Q~7h{=$?cXV!e^nKl(#k=MYr zi`mVh)Y5FFv}x&s@?<`@M4*YKL{Pm5Tu?ZAiln{=!!T9UEzbY!{z56Gj#v&Dr>qW$ z&A-qcKXv=el{%%%@~6U#jEylaNxKR0)xOQ6@8U&1G4?#VCSTNb!wnJ(Eh%Gp-tWb@ zPGLs5;^VZRAy2=muKXz2&Dma&gSoL@7$5dY%Vb9=&6k$H#QBHqUz-2(*M2OZl3Lcc z(LU-B{A6sQ1$A{!?iYrcP`N>~t}&TpCbn)zonkv-6q=pkLj=Hj+v# z2H)vma#Si^(y{}ugOY)B=a(&{xSv%;y)}_fe=#BS*WEvU$Wgrg2W@jrMlyek+g`O|{hyYnyRk1U^p<#~LDU;gH|N3;jIz?MWI2XM5BqVF( zEiWt|4pxNn%X(S95{l5d#EX)5&Zc%^PfR6y-8JcUfWWWf(kMC#8A@4@n+}_I{k(5@ zimVybkN8?mzKlH&OV;#xg15E#@Q`i(?D_=Vg24XYzpsA<3k+|uoojBU9s?Wm-)LW@ zC~8Obntj@oX`91d{!b~5DfAnpA5GonMGs+u2b2N(Z{Ep!+fKEDvbsE@u#-rV)h zz0#p7hTnZX)x#wbKlyU!;#5MA@wb`z`d*H7txNA&u;H`C-BQm{*SP3%A{QQOsT(X^ z^EBvOT2_iWy!3--o_GD(`LfHtB7Hjg#P?~F9`*mul8J~&A>czy1VQwFsUiDFaD0;O zz8NEn?zBPL*!H^<57VZliot>d$Jg;6DG#hU_=?XYAM$#}_geXCbNDB(<0;jA#|~d& zy>uj7)LPUE+YIUQD2&ZjY)u^fu^lKPGv%_%nKF3|T|+(WGw-o4J#M{%?y=NVy)=4B z^?8?F$akS%yGLbX)35(6E&kE@bD+rUuIBFq-&yujXCAPv;mF&6QT3P9{~iOlN2tPt zp!tPbw5+$T39k#&v)J?=n!^s}NV0D($lwbl z)|Hw#vV;WL>{mSBolZ*A$_)V`$P@u}21Uo;HM7DF{%m2p|A2Y%bsaf; zswlZ5RZx@kA<^A4B`nJkr0LtFPw;@qcI53GCithXpNLfTz%1_P2fqb*+Vb}oxaHAG zVgQ+c=}2bNH`V_wQRTiS3)@|>Rp}-4-bLvkO*%;E3PgIZ zLAugG1Vp+h0@6b7(juUQBAo<*03mr3e{Zett@ZIoR@NlIotbm@IeYJO?@;^OSlWp? zsbts_Y71&fAS5p9!o^RACUqxoUM~_?u;XifrW6DAt_k@dU3Q90VFkQ7(` zpI>o34POnzjxf*#u%-G_FOvPM;k<$ymsEP2A#GltUQ05d&6IfM-1qc??+|XWmM<=} zKDlFELuMWjXv|W#CeULPXcmBENAe(ydJ=ZJ&HLgm(9Zb}lceP62hi`R6FFOoQR@ z-<%~Kc~cpKJ2@X3N}JAGrCi$h()#S`QkEA8cz$KdgF8;{XXckaX@qVm9~3*b{1{)& zoo_Z5C%%NXnv)iYNtiErZ)f;s(xtmh{#{3P0~@7>=8N#Y#lt{MK;0O!C=;>jEr^uH z&LHu}cnAN9OmY@83XNw&`<*diYCjf26TOYMo|P>ckm&RreMn?F8R`|+6xRfDM7*|XF!wUJq-0rp)N2y;@mp3DuO=LmQKb*gl;v{yjPeai;;SF9o*~& zZRg&wDj%z-poX+LKPu|Eo08dH9iLJNqV+4;s2M#r5Qt%vTl(n{W41fLrWHHET$K12 z2I--a##-3|(O)#;|6h)W@R4R)FK(fwHr#RxZ{wO(&w&27u2W@CPMX%}rKp>49cu9S@E7Is&4%*bqpX@y&&SdCvEvn{l>k`*D7W+-gkiW>Yq%H8#>4~h4 zBqIDzt7fZn=v*3D6nF-qd3CE6BzGmXkyP?7KSwp+mAoIe`=S`l;pwq;E&k@Do_Cg@ z5rt_@UM6H|hfzs(O zN)b36_7?zF9im}`2%O47N!{0&x1X*(vPdqf6omFm$3Vq`!3iA>^G_6F^^r=miv!9o zyl8PPx_nP$&5ySNkIDkF&^Z-V9-0pxE4-iUtBD1l>MH71jo#)H5x`0`Jn=sv<>T;y zErbmIscjLW*+8=cTdSDfg>D1G@Brd(kc1V-3%EM6Y`CTg?iAc}<8U}o;Ze6nKP`My zQ?+@vM(FSJ^GjmiPrfyR>)B>JbK07|sSL;v8zi$;F0AlbT~BP8Rw}MnI~8}nA$tp` zG78txMRp%&l;AOtr5i!tE>7*bSge%dBt77(Ng#%UJiQSnfa(6fA2uego~M|P7$f1q znboA3^~+3A*cljORZ8pDG1H1U)0B{1Z+jvOsnuNh5LugoX@xpNR^JRm1I;h9>zCSs zN{X8_d{UbmOdgK`qQTtCsPjnEUUkJIejP<&jr=|31Jkd8y3FYl+xDwSAcoj*0qelY zi=^Q*PNO1lOX`oMu?*d~m`_ovS6@-i<0F=?7vad~Vg_Gl?&Kx656ulf6E^1QdT`fh zy&qHUSxtJafFQS@oGFCaykt+cK^dAy8t+ZDMfx{NX*|a$-QvDOMd3YqU5{|50$veV z%{KW!tA>4f>Q78u#-)jYz(96#=10qRi9mu>2);BlgvnsNnBxE9hvrtm`;VqHR@|lY zBx1#7>(S%lF6@2cb`;hbKq2rtx}#rCM1ki{(Wi#o%-GB-LR7*b_W3?Z`Hc~0eJd55 zoo2*U2B#`q^1^M$Y6&z*`R#e)sm{xu(QsQ=>T{yMR01XDE}q2nr&Dk`+H^N0mFLGV zAsga(Bqn>D4u~wVsbI1zn~s)t)e`;98Pgf+`PZBW4RzC?_gJ@=k5?Vq#a2IwXxvax z{=qBd_`n}Qbm(|2)YX+OOH_ONemna}046A(4Iqv;|NEj0_BWaof1OS5{zB(8UN2z7 zvBcqQmSEhkisX+2Syi}LX}_SWAG)Y^+xQOn-zMkrtD8!WOUYbFZL^|pBAEiqa}2cb zRqd8jfQ)=V4-}}+C;ozW0v>iHD#lB?#VHGsIPbY{3^8i9_EzRglM9xe3$zMeJl`|6 z)wXhXc)q>X{$5$qr7SxsV^l|mk4chO@?NMZrzPrNQH1;At6c@e7l91>Q-d{z5FXn4}KoBWP8n#5i^(lu!j>+g?hYj|Hz?`zCumIchb62CzlL+tK4gK87(W*TYBm0TZ z_x9>X)X!;$cYfMUG3=jovBRxu>=mu9e!Px@TfNgc>q2|-B!6Z2xO0S9-Nd$+Xlp&Z zQgN<@_bGs!#qa{7%H+6F`~%P@y!CQ@V-hb)Kh2MPIWODJfU_&{d9gqYvq_FP_8mZFr07#2!oK z>+rrEhSv?mM%fBhT0~rX7dhJZuJUt`w|344RK(a@$<=miiigKqTSDV@sg1rnnZ!fZ zuE>UU*ZQd}uWudiCt=|p&&@8~7B_&2CU~iN4HwcmM8qAv-Jix(gsIKIs~~b%soS`4 z4ExX)+VIi>KAW=Nk2B~#H^corhrb|mH88Jzm)|elnL^5+ApR=zLUd-SLm&S9s_DL7 zslr;(5d}0ySFIX4c{Lq5a%&jNp-kv(*Rn^kDO*vcO>fHWaLJygeWic4Z~7Z}P|OLE z|CtWxQCN0Z$J$Kuy|HrG%ZLt;wfCNSn7SI5-DaHZ!xAZ*H_T}{w4Rq=Zog1qcY3D< z&tQV?5N^1azL8rB^?gtKF3Xo^!@wjIO{#s{3C@?g7EwH6}+)JeJ(^#yJ#yb`i9&P z)_bhF6cx$Vj=rv{VUWg0RmwgrEwCy}tupl^WoRP+=D3}4g)hR^Ge7%dU`5&T@!|In z<)N^ytX*{6r-)-hd|myH6=(fUVGdb8<%&6!46<(va`a*J>Wl2KNp`IICQd0~tffC7 zy+GHZoE-Oym#^*Bm#FLqVQbTWC6fqvASN|$Tvg?&Pg}oOD)cRB)7{*k=b90Fw0pR> z*=fS{Pz|Z;RoOQ;%S9WL`P}f$x|cvdN0}DH?1AiEvUm5q)wr;9NP-GtYLF4CgPVRZ zN7RAVpi*6h;|YYCn}(g> z>jf_-%^T*Lu^FcTxxp_w{7M(8U zson+6Z@5Oot@it->Tk;J1!02^^~T|SeiG=+i}5Y8MsjgPaP8zJ8&g^d2TCT*PvY+F zYcJ=@5FEn3Vv^|AS(e{=Xa+7hCxJA0>|LH?=6-6i?6r1$8id>h{;1!7F$jTyfRqT# zN;cf_uc9UReErLjYWQK->suT>geFalFefp^go%Un4kb%-hhL}tY6i^Ql(`3RsYnv- zqE%ugv{OT8uHm#%ceQTv`xjzXev*|3XJ3DIQOn#`PNP@uQ_1bBwzcRJ*f}H|PP|dW zP)pq?7Eeg663X%V(*v?sP7yc7H6}OJv`Li3UN44ahfTRpXj%K&NWD_(Z%1@b6pez7JR z0cssWPLxXnH`b28<{M2CxQEdAl{0J3-9pcUL{_aj2SSpC=0s+OTl6>dxE01yZzN)C zMb%DKllL>dm!?|8ICB0Dp##9ddK5Apu2$E^lViGH9g>PT(SOlbAd>#Dn-8p`JSShM z+km!m)n#mmFVp(pJRBERLpI^1= zrFW+JRR;cziR_c~w|l_y=7M?qPtwL-k!{=`M5h)m|CYGFFJXDJZ@4$Q zA6n5ciDOPnJhVAw)0ZD>-dS+Aqf{e&N^4-Hsv#2H@pqo5by-QVy2Wd3#@b%%Dp5#; z(C2}hSPn{SJ0%=Kyo?Lk8$3h4kLJ;o_R;rcc4SGPDRY_3;-4FUXReAh2#tLWt*kWu zkarsZ%2lLY>#Y|UVmuzrZvpo{?VoV-3DKi$E5KiyvF;#mkmXiPYE)Ux01|$!mQ>L>VfX9_TZ?$Su#qBFYG)xm~$GFWlQ)_)Q3zX~zrUjAA*tSe8IfpSMj#$F$A zHOHaB*lkU|g98J4D6NT7c4e?GksZ-2dDDaI0*c^;&S8%hf;J+UDyA{XIKf=)_8Be--Cw74dMuFbDg8L)RYB3 z%dhbKi_pGF`H2o2p-~SAWNuDMr-5o}-lOnZ;Yt3Cc2=fn7^K!YPgolS+RDvyQ$T@ourIcx=MH&Wyz2*HK} zx?%A8snVw9JeTuP13u*Wza!bxWQWm3liS}6ul~x^W~AEp`y*#S0fC@NoaKlQ@3}vm zXtTCRT-$n5>a>MSCM2NxPTIC7*)`!cVjj|z`7!5-UIoa)`Vp|UB~ z#_Mtbdo+9RwgMZsVE|ptv^m^rZoGEBQr~g7dG!f$_$Xd~Wbd+0k<$Kx{{s_^pu91A zgLavlItMeFslSV8`@#kOtz4RVPO!!3PZs(&Rq9~m(=v@>2h5dIBz58hz(WaY2H0KQ$oIiAiSL2rtq$p)0 zL9Xup(`|$G}5Y>&O zOH)vP_)+lS_hg^VY_>9CN`)ougoiWy4o+h}W=eg}6ucSN=p%Dk?#(zY@VO1bs?9v} zX*QI!%BkRCMB*{`Ra~wfvR9RbcvI{@vnv$ zTqaNev@{6wcy#NZd;#>2)&4*hT_Di&0dv2)LfDp`z=8o zajfR1l7`wD6S-_{VR|FEL!%xIyO3x*!1d>mAPsb8FdHsE_W=}O_BaX|Y)mK&@-!Q` zlptH+qunFivYc6}o!=qoa_8{bwdUE?bVK&FSUEp=Cr_!qF2aO!)CTAK>2$Xrm+pxi z_t!VjM8nSt<^shp(TZwv3kxR7Gn0sc1zk*i2Nyi3Yp_kB|#i+EOCh0tkE zL9fEFZ(kLK`vks~6B+XeQJGmyv0E(QQx4MYOSe=m*E{pk@=;S-TsQho+_xcUu>HL= zxL~BpH8PUZF15a5fl6N^$m+&(BNOHef^*){DZuwgHPJX%3Sa#4onzSHLBt6vigZ2EQ| zwdT+ji&`;AX3JVdvOMr82WWHfH_4}@F9;ADtlbZ2N{|6#RF5oL-S7l?{&E97-|TUL zXAFQ*+5-~)wZmZ7Ho6KG*~$+10uDqS9(cwDjVcmf@(_M60jYIpoyNBeJk}VtlUF%J zsB7`*eEj3@rTl_om0Nu-qgi>FmyeTK#=M}NH<8O*Xmf5bD-Lcr)TR7er$e1ta|ee& zI2Irjg;Lw)6E-YEsME)lhe33VLiKCb#af-ss!M&`0~@X}(QO{G*Du!=DC8}?QStiIc#_iua^lsr7pyCLwPP8{-X?=RFT|tSTm1ku>|p#R z|G{_KgijnTT`Z&rZx4p7%%a7o7%B2F)tBELhSMuw*=BCrl)>hTzFrA<1&|I43M_{ z_ET}edMTJficVnS?lU1ab4I-Pm}-ZR>_m~ zM^Gk(jHag(tdi<}qV@Q0uZhx7UZ&RwT=5{%t{#}v>~`AMfwts(V9fk3km_J&nS|0< zGwo>p2FPB(NHFN!p{*45*<+T@_&SZ<9}9M9=%a^z68rRGw5wJ1ulN-?tF z@7KFU!x$`Q^}~E5Fp<*oK4i8S*;ku2wETx^($DCF?m)S(PB063Z%0dm+iA%&m7QHv z*Ym1T^@6B})+dMJ8!iMHcgHNesabJ)-aOL)q8rlTwWfJl0>*|phnhcrcv3J`IT{0C zRMDUxhF{X~&$^RPD5Y+3JHt8y=>_Q z1?ls=ep0}kZLHBy{81J;RK8fx79S0I#N#csXxu{;N@J)bfBsGH6HmFc_oI^rLjx>> zY)o|dy`$10#GvEth`9cTs zxf8ciVo$sG2cDTJU6?0@AISb!mlug08-g)gYa96Z2O^8*zaA7S7A&#BVc3Psop5?) zdrEhoC##FA1d|12(XMp~oBBy?!D?~Q4f9x@4qUMfIPh!kci@3ZD3KO-Gw&{31X8U4NW zZtWqH?;uL-?a&LiwoOe@bjyOS%%89%PcHAObVCg>t@S~3_mIBp#}0z$&1*keNlR{S zFT9Ifgf8f0?-PK7Z(I9D0Yk4x;tQtGEa2_LB>_N}KtB-ZqHtMkK)BGU3FQkVv>kfx zWLS#|5RlH^ey4of6n$+LI_5*-!f6>ZYRM+Ey!*-HF0;pcX}G65t4SlOwGh{$C@giy z(YGDgp%`bfstg#T_*EZ(RH++A3RuNSthkXW1X|>TjYkG6^r0I^YIyZ+V)SJ8#F!>` z`2+Tslb;!*k!j;_Uhw*L+bO^x&W{s^c7ROCY_qjs6M#j4Dmafen$pZ9a9RWtb7fR~7aoW}|4<2k5yYJ7`AnfZ4 zpDvwIbksd&QY*sD4vZ+KNL5K)_m1ED6sr)-;VSLeYx2gH& z0n}#DPvE%2MEbeH~rJ{M3UB72{+6)*UbS_gZXkV90vJ` zuN&qU@UI>(0e6(*9|f*I&fZTL*qZ@_^>CajqcW^UCa5PWswcJi#-=>yjDe2a>Q)3$ z6{oQ8?b;F3I52&m{ozTw#;~#BPw~Y;arnsixs~p{v8QzF#iF*uH+nQ=BwHcOrAv_< z0mNU@+Jko`V@hj{K8>KBAZS=^^50+7N{-!WuUjNoZ!kldl`&s|;YgqD#PffdxNG^~ zf9J?+ylG2p6^Gkq+n};1d9vK7*e)CXywpeP?V}q8+R^uvG&;0BOr5*`Y+cB_t~%`4 zUG*XRW|SW4ZhwpMva)zE!Xb%LRQ%d*D<9Xz^{0CNl_hTjJ+4HiC{M0x-C=%p3f)J;uLWNAck4lnoZKV@)`DRi zn%aAL26@L3BN@l_ODZq-ci(=G%*s;}GY%`+jSvGKsdRCV>eD0ay{%~qYTr=sOV`OC z+g@j?JP)yI`F_jK*Q?x|zD)Qv!zpWpp2#1OsD?)Ce-MrHR1^n@-xHvegh2)d{qgP` z=-=fB-Nr){%W`a990`uIa9J*BOWV}MS6R{O_u;9=V04Dp68{Zbd%xzfEi=?L_2*Kt z>EYV0ky;J>94!TxcZ>{Z$(Xb@T=+#lfkpy_J}w0wPz^}e=tB$ok{ZMLWy^(A3{fvK z#mHl=8R0hLFTQTD#wCA~VSCt6=`GAsI+lO?V-ugE)1O(iGpo>YDo%FzS2vPMPKu{! z{r5UL4Gw_938PX2AT>R%)Q9e(+X6=W^1rlu#!Gq_d>+q7OaK2Lk1qwCi6{i|-xnxw zXd-P_SRmU^+0eL-9Ac_64|(J#?{D#lk+mN}YRLXqfQmGq{$!mV<rZd3hz7_;R-=0+O5%7b|t9I_Tf?o6?WrAv1D zQ)vouXuFdvnw+wxKKx?La3OTsZ2Pw6H)g6aQqC&)+-71{#FD%;77+-zwn9=&I>G^R z8LQ+znTP*Q<)6iWt|VZW90BA8_JAJb#06LQvjjBA;?*1ZuNbQTO zpQn4LTj2ada01n1RPtboO`&gxA5TQYO1DzKU|9r^(^MS{^bloy}ki8PKU(_<#Bo> zmc5@XggPPPEn0VSfBER{*!4w&VMSaPb|{ym59`)Ipo?M6ZAPp7esggy$<*=m!CE96 zZC;_>0H=%8gcUbmMs0IC2~;XYU-Yt8@}pU=j(2K$h9-HJ#91n?10*g&mI~1at+s*} zfZE>oTPkGb0KHX&51Jg+SbY;S;i~o@;Jc6B7M4ZR1I-oea1MA~NE^lv;};G;2>4xO zur__%U$fpWxbCuhv)jBeQ;gqAcRcf;&{Lc6q?5$iil|QG&XZ>6Zs?JPqu;SP;WSr_ zo|Sf+dPT>~l8!pjkBj)L0@RSAg|z$0?deEMzjO-*pn<{`*bHkP&WZ~FI$2U7KxY$s znsVhBvdbEbfp-8fUJvk)xRR3KH`X@kRAw-@gXa98S;lyw4-ebSM5_3V?^LL-Z^tBM z)t#TXqCC1A_N0Zh$>`WjGg3lI%NDwdt2nP)Ew)P3oME6q~hC{iH zp{b-5tQ>2a%P2lem?(K#5r+ztoPXvSs(Tg$j>@2Je?4|_sksUj=c5SZ;TvUEVO-~V z*u2b01db6t_E#8#9Y_b$zc znxH=Mmq@*6SCO)4Y-e?A%#bst&^;a=yOpS*6VCmoaWpEq8DFyIhy&|zJcTv$J=aqa z?6UX__ZnfBL7(CWI8bS!@@ha*BTdCA1$7s@{#~gG4`hJ3`Y;!C(@Ngc`5ON26PRM{ z%G)X_Zb`|(YKdzv!&`mKhW5VKAbR1(jsqrbeM^_t`(jAlyvu_ zT3u5=g9_m>1D#p^79P<8)1q1B$z#Gi$#umbin{S#ft8-Xgg7%WmXGJfY|jd$Mo0J5mHJJ~YFfhU53e z>^!dW{(7cOmRO(8-n(tjT0~+j&E+C+S~)M2d99~y08PN#`H&3*fAlfx`S?t74u9)j zTBI!yLuVDq`+XE1P}-L71VWgc0IN=YdFlo|)Mu=lmWO2%a3FaG>P2`b@=j`t7O% z?2v27B*H``TqSrhfZ^XVn4T+M7}>W+MAF^gk8mJ9({8#JTU&gjn|Vz;mtmxEQw$kM zgC*HzrYgR?4+n<_4dAuyAWTgoEACGN0noD}ja9dDdH8Syh;T#y4C-z~!5^Sodzycd z00yFaRlM-Y8*})}i+oEo^zh+f7ZcrG<%D3-+Wl$iI;z36Hm9t=;JZmdG;r7?qg4)P z)6=;Q?8c_!N_&1z_M4%O5uj&VwK6pYYOn>nXCs%Ip(me6Egeq8W zl6~De5s_l|8~Z^-oM}DEXrkvU$zbEVE$0%($?q4cRHNZ4o9N3|W@838-eqjKvH^Tw zm`L&rpm0g1At0Bu>XRx;A)t3MCw9ozwoLPwTGT=?#l=-bUM%E*O zm(IT%%2+b%6@yQTlZ6}|={;9WBJ*VZPJbk~1?ymQoYvRDdB@=u12D^T&#fTwEgruL z)4fJl360s!mjZ3~GOX`P9RZ7*Y++pk_$H+JW)YnhF#+T-a2b|^lVHH<*SpzexjUMy zy}1GwvLNpO!xKPPy{PeYXIP(s|8O&-df}E?F=N_LH*`P3Fm>WuK3yJXV-VTParX9l z{ZE?^0u91E3b;hN4xGc^{gN;Q$Kl!PFudVbl+A8ZDS4>8z~L1uURlo1Q8aRIuq{~S zdu(By(LhNLr3YoLeB1iEXVcm(XHX8V!b?9}LTWA;$p2mCFl5o0<}u+QOmD;j2B`(I z8SeWp1mJ0hgu`%I_$ie6?iLJEY;$ga+NKASS2=QmzuqCC*4R}`=UWQs2n0h9sAJV)6cm>+Wqcf60i;7 zXKHxr3E|6#H<+g@*A~t*hZ*;@0?NbkQ|&>g0&ykN@`GL-42mzk2NrU5sZzk@OU7~BM zHEU4EIOFD)Eg&e|E$?H`M8184|I9N#X;sUAuyew;%s{R#v)nd6zOz`sLaC zY-d!Q3G$XU&dreOk0@^_6frV1IsGVV)@qZUM5&rxytZL?Zd$R3Zr|E*RY~q}#HNW` zFB>pjo^zEkLub>fnO$3z!%p<%yC35DImx~4p5?dF7x4!*4dk4@e|S-1o@)2hQpf$) zKh238aSQe@4h~ez&s}c(WOp9_XR{72i<8wsVIIp^XD<^zQ}m>7KWDRfSDC$_;jWVT fY9;*tgzcBjJ$GOE`Ku?uFk|p^^>bP0l+XkKFwc^L literal 0 HcmV?d00001 diff --git a/src/img/hotIem.png b/src/img/hotIem.png new file mode 100644 index 0000000000000000000000000000000000000000..ee75b082b16fda5996bbe54668c4ecc5d8fe0d41 GIT binary patch literal 13514 zcmeIYWmJ@3^e;Xj-AahGfTV;-Bi%J9Ae}1RB?=6sq%=r})Bs9J*9;}n-8mvP99fxgERUs>aV zK*E;lO7i;eu=bY;6W9$QTSq~*=8)kSVYb+!aglr2jH%)?Laf0X!s*LK#O$Jiw9b1X zv~8cTszT;^g2((^QoHFpB(Vuze`rhHI}K-N7u_=_W)vq;Q6Lj6e9bOLM>rglp8H^U z+|GwF>$beGwx&k1^&4;P%HUPtE1sRo%*q|iMH=e*q?pagUNoy@i0?6MwDm9=+UMFU zMF;}P(FkYt{_ub!5`MaDD6BdqCnsOxNl!(!cmRLC6)RWKzDLy9AW*`cIN^2^uBKU4 zTu!lo4{==6jV6jE212F@1pIDlr5L@D!>4n7<9-5`E%_1sEgT`@WfX;vF35 zU`b-y{vjdJI7S6LkgWfm(-|czKt!bc|NHzu=z$khpkR@uJbum9Mb#eZI`)zN7U2@& z3GvqoI|B0uIfgiLLfOe)#M)RO+F^*ZJWo)K4$*BuSL+P=wjTT~ZFh8;XOP)Xw3AQ` z6ha6hF>JYZC<{1`%5`72G>AR>fW7Ll{o%g)e!UcK2l9D04hWBT#m9)p@_o&;X)AbF z-`zmqvQhI_U}DthRUdtnBtJ+cq5}sM?rE1+eASM@?@IJNzBw-$+4!};P$*TgyV3qm z0~AB{SJcZURC-gyw-77#knu;xj4niYC1orCkrIUGKKH7AdbQbux@v5*fZ!?WX2DE}6%yexkn_pwU zzC`oXaP;#gNf2J}=@%qDh(zRM@V3qbS)pDwZbYj7^#QEWOiX;+xDfKNz{m^(HN7Yt zoc~5ZB;!)E%YN~yn78Q@8wyWd-;jsx~bx3aWEc$6^zQ(LO+I!+> zv!c?*?%_<3z1;WWbZ_OoQPbOY!pH5f(!a#&0JZoUZ*P9MS+U8H9x+j#(=L58RqhAl%y`=B8FX`GzQJzx{1Sl)F*OVh-p6VLPmlYO$C1EeRlOXF{qRn z6d=GKi!X2kMSk&-PHw-Hb3)aOEU4BL5Z4-xQ!m)>?X2@5b-8seF+OIHF8Dk1)gY=sJ zl}6QQ-;se*krEB3q&Dw z6oS8C&21}Cckn8yQvYVJUkST+K(isD3yi$JzFg`&)duV5B!A3Bv>eIZ>v>_^jz%aICAyMGoyWP z^;OpHC$j_3mAedux1_9*6pjy1^M?rC?F04Mz2(Bn2k$KMPp5u5*p!+3d<8|SSYao; zuc$_UX^KcyEL7ab$LUU>Cs1$-W9JMobz1mV?Iv&V25n%`W=871`&Wnvh?)zKm z@qLzWnnd1RFYO$#rU{J1+n1nuL9S1$&&htbUcR%y zp`^9MSj;`vXkWRcVMdLJVS(KbC0*hx(0p)fc|ig7%Vj$qR55L*symKm)VoiUUDjr7%u2uljIxk<4!*;Lgj1Q|*hZpAyM| zSj|i`VP9~{nL`NWY?~vnt;=9+rlX;8%lJQI1eI~2;9=cgHy6YWkC+q;ETDy2sy)W# z%BXXwB$h*$%f2;cZ`<`bwjcxGpgj|Uin6J)-R+DxCrc!uY@8B`@O~2mo%O`>v0>n< zw|ZvWy_c4adOVGc&imUl4_GFPvA}%l*U=TavUUn|_lMP9tEz)y@Bl^L4pSL?YJJ4Y z6}A)4T7tlf3)W2)E^l*gy`OEyee*6~BpO}LUFMIa?sg}E1W;k<>+R4C zlDi=`hJ&=++60n~SDeXo!lzuHC)Fd1rG}ry1`_%vVSZRrdJ%UEHRjw&cTdzL5r+-p zf1DLN9{JW@rwMvP4=4bAiKzP~Mu9uaN`zl>xS%3UEGv1h{_Mqm&tmb}l?yh@BCrL7 zv}cvS-YlBmYj(F8Rfu;*iW1^Jc3||a7^AQLdb>%2l>nI%#OiA^u<|Sl*zH_dU{CA} zLqK|CcdJ|`K1@SjB1x^<{>xs$4DRHH#m5^!cIY$P4R^o$?oizQU?HUJJB(cu1q<%L zS;qm?I72cRyrLN1`i zVtIV^_iOO(C2-mY`bY)STkSph{aD1ri68d1L|;!FhX_O9{>)BXu_>Wp^MhoPQ+u z57$5D&cQ7${WmgeizK?)?^Ig=zN3AZ^LFw@-b4ldW$5!Cg*GDU>N1{(FLU!T_LG7QSFQJ59C;}EC;^AYM8;id1t8^b+YAvD z31~72=i!!C04bl3NXRR-bxO~(z5pPS3jb1SwCgxdYRU%1@cX5brOR=-5n)uU-`nyO-L1v zk###4^Bo+ZANemqR1@9^F9ijbiquf0*>qvbHvOPeZ|-2oG1;5m@-(-LHWN+mCLr`{ z4Kk2ue!!$&MRie~>V5_j@$zQ)fnLtGkZ%W->7Vy6Fywx1tv6fZ#6D$L{gl`&bim;% zTz}3>A=-C1d?x~X^#^HK{+S|ccf2tE6i0m?Et$0Ip|k>ucYkr#PqtB3iJIv!FjvYB zS56jiCrR0r;iYM3A*D&3>Zwi$h%KaJlF~Ihl66nMP#YX1zVoqm#8fG){5PbMPPASGy9gWmG zJbf01uTvMu50VA~h2Y07*eDv@d>Xr?b_-#>n|3FDTR*aOLhN|*0*CAYVe&E^Uy1j)5*_B6(q*^&YT`zsn}`CGYL44mFMwAX{!k{qsPrO!=k z)rG;W>g8KsCY1}>!oUoWA_{5CoP=6(Mjp0)x`KYgwv(0?#Xc)3elUJg^We(y7BZ6G z?}CA}7{?LjMlRFX{BzAFb~eUuk8ad=#?K{& z9uoF|K{wj<30m&D&UfpEtN-!1oH{U3SGKX(^KO(%xB6TlM(M_JT%ojvY@1~O! z6@qhq)zvla=`40ywD^?fFq=j_@ai#0yo^&~cxH$T?OBquZc=kgNb1m&Ql1^Q{c&fZ z@f4@}7nA$FyCVx?;vu~_h;BmiFm=okkouGpWG;wmk1A-jK1@zceMAIXF;|F`rf3RD zyvV;ZRA87lF3DW?%JPE2ci1xIc@mjrJh|fQ-_sDu!gklX^g8=sAB@_+ z7Z6Z;d&t@Od_CNveT$`Sg1LZ|yo>(kwp<48aZ}`55YEkqraog4H12ZKPo{1MQP}eO zArb=(rhXvy^Ac$G=Da&ss#zFl>Ti-`JI^G zO?T6z^xiBdQ_@LzDp;3YixY-(N8JReA=@r9C!{`anO9o2C_CPIMzFjGbbKgitX6{b zhSS@Qqm7eabIpL$)uL?4)~=KYoE8Fb6W5AphZc&l%~N#{QM zCwNyN4m8HdWae{c#9U3!n0LG~Ul+a~atCp{A)nYiJ>xUkGWYh~#CBsb#*8J_i}SC@ zK0Ita736GF-`8Jd+mBB=nD`@$COs|RX|3nQRWf}odWtQ)Bf9W3=RU2+4!p#-dAlyU zcaeNDVLhUlaq97-SU9T`f!2cw`v?yB#JaXNxcV*8@8zqMK0X~>+gXJO@$Dx__%Cl$ z`yH2x*~Ag+=L){<2U-qS1LtUJ?)<7gGHkt{&v9~}Io_>)c#HXRKlAL<(Co#hR{YOT z&oL6+@hU#?_c>w3&)aJj$+e>4tiY7dD_9MD=_$4;o23sO-(^6M&rwu3U35p7_-KE? z)^nC4ilHkzd|l`Wm#PXfQC>G6z1QsRG^&W?O;WT>l*WOQOpra7Qix&d-lbizuF?)X zdy&X_-(>cKw43`+zIUdzUWJqNk)hUHjwQ`sPM}IFx7h~vMEO-}WDw;uigY1Ihi0C7 z6LUeyo>w6~3g6$0$viyv)lo%=ae>YoeTkZigLpky9{#xOyY zMen8yX%KhZr%A;br`Z`4vUGAW9yN&fpG|uMUug-PYh`+tw{K=Cv3)yyu|4tR{IIy4 zU0}f@YR(njz&@!ACDp~$mngX|x6_3NgtQdK$q(}R+|fV$IhJe@6xSzWr^#>;J^tF8 zJF8S>kSj-4fX1xMrcTEC?YYwKGX_V6ExJ%)5}yOi2VKaC9z{fIygE(5yHV1cyoDUf zlD>__ku>6x(G=n~%7;AGZiih%@1L@Y?NdtVn!{jT?^3|XsEe#!wI6+Y!EqedXSK@w z^E|tWr*Kvm$rdG}0S;`v@Xs2LswjmUW#kp(@iM^a#^~;$q#%>>s<<0(1)bds!Y7?D zRi?ymzA!cCw|(^7{sC|i5p=rmO%9uXE5;$%F|6ci%R>#fZh~uK)X6iHZlaD~-esbd zR4gqTMZy|(OBPY(l#|3X%U@vOzz4-pi*kD*lZSq14OfRYPM2~{o`t?guIsF)mfXrS zWnMuh^&HalvA=$E>`rH&}zt()%#Egv$@i zJ_?ypGd;oe{VrC3&iyn~Zb%nP1{DB z;k%NwPZcZgZ?~@e%7+QUONng_R0{<^E|NzETz9xT37EqMrFv$0E5dv-MBNH>kD=?d z5q&)H`IyObZ#_x*9E(8>Bi%;kKXGk-TPNk&UoQqZQS;tLx{?D8TYqG3sfs!s8hu*? zDGEwIMd#<+ef<>%y*6>4g?m(d<|`J-L~CwExBU^Gf1G?lWZLX1pI{y%xDm|#X%cc2 z)t=ZcdlCGmpL+4_AhX%g+wW1}dRRBTxyEAHz9d)l;A{K4f0*}Oa;m1Kc0GRGz{GHU z4^m=?h>gi~O4c|yMGd6zS}D>!J5ut`d~bevvCS(E3!7YB#}Nm~JAbj>#xONmvlnU> z%6XiF=u+VqO?`!&g{YtrnnXlPsR*lxg4Q5u{C3kG+h2ut%dd_xGLMXH6s40LtQ{z# z2k+dBVkHJWt7*BP1MY-5mh`pHKT@~ShOTOB8*u#@5y#d85BcZ(YHHtkjL%_ntd@K* zjfsl5O*;ZclfE!?X;%uICoXPg2-(4bGWP47r;i!V{q$hS*lhC1P_-I}DlXpmE})fm z+EIj#KWDbMd0Ti>>f~`@DRZvfF1PrWF1yZlPvPu`W(*-D%%#+F0RJbsSC_}1uajfk zr8B`ou99ET{{F5B09-`y_j2&-VzS5hSc+7A7iWKY zZ{?#j7lgF}4#pSPuMwBJh=UvBFZtVNcQ8ar@|NE{0&LGaQp~`}%C45dL-7r34gTnM z-s_p=s2PNP&JunM2_1i$UsW9o?!B8?6AxkW>RPo*cwNXQJ5$U&k-VaD51Ip51hKd$ zT3DqW9yaVe-YngvaCj$K=&4~DIl)qd&z^fSLe9sSra0Jp^`ht*E_=rtvMBER1X>dE zFA6dwv3TAkm|A83<Duqk!DZq~tApbixrj-t(l zS_@VXXs(n?PJ=&7LT3dT2F)T5)D+byIf1q%!+#d}1~&OA_K(5!nR=z7)iZl>qvS(*i>TDSuwY}*#fi96p* zK>2fXz-2V`#n_kA%9GpA%$W(~hR%z8pac$VN+EftEMf5{18-8de}Bw=F~6BNI-9!w z{XB1gt8FJ{ix5;4)$wtt$$Qf*Lt4X1sK<1~zu647s~l*wGd70)b2VA>H)>pY2*_P~ zZ>Kx|cqzr7YKRJegXA)StA~olor%AZpxOOmsPB>=1D)h2*D7N?#?}*5+U82Z`^H7r zvEs2RKmaO=1;iMY3K0L)QB5uAnqZOQ1Rv=b?l%?rXW?;@>e3YmKQkBff?76ucj8&x z2dVs33!o?bsrey34%;Oak4+j^kqQ(;$qQk7YWs~7XU%67{Qw(etYoENTOG0VN1K`h z2UHW;@loqbAR#D$9k3lhv(ACdv5jA_g`U5A}=$NK3_x&XK9y-8890jcE!grIMDLY7-VfN{Wili zGoGrL$7Mg`DREiuw5J5I#{ed#i`f^WzKSIkS=&;O%B&tfRckgn?n>B=1uNeM&^4j! zp`1`0Py)lxV{7S2BKWs@>Ic-23VG`?#oZzhsGn7^)30{WwxW|tggT9#(PjcLM*@e# zXteGn+&sb-7i6qBO17KPFo1bubE1jw{E;R?4^8^tIB3N&OkW#wtJo<9Vvp~@+0D>L zSL_OGo2WZ{o!-R;snLWG&OCMaj5;qqpX-fjku$|46#`yO>XFpyh(sbMeg|)h2d!`a z$ewblcWv?@u1p!Q$;iw&@DHdkNnX%!dXL@fQ>4#LZZ>Xese|zSD#Q&6enXLN1v6HR z1}s5#*V-FNzTayS-hmC0B2PDZ9%ZCwqr3HbHR^f1dUej=eMN z9?30XG@3#O{ftFyU~oU}vTI`I82u$J@j}B}I|+}Qu{gS|%7PLk=SiSdy$~uNq4YpM zfRRj7;Ms}p`GINsW4qDp155Hae%$M;_l5%^_hIE2={AR!!`-sOCqO;7P}wSUT5Cbk zb?j)3s90h2^fEWlXvKXoDCyd()~PbDC}bzh?mDL2u&{H*6O=&Zm~K^no+-hm^?@v^ zpk6hu78#3Ov2uGj&S`@AtO1FiWp(rERt#G7%`@d9VMqj4W<>6NgQpJaA@ah%w7{zO z-{>eURbn|M^m7xnVp%Z&T4$>3dEzz-9>NFKKMpxB{*I^M?)9*7wACQ$xskUZHKNqJ zjxfwf&rLd3QU-yx0Yt{&X&JIr|FJquvMEkYHLk%$K(lt-B%RR!Is;E%c&xD+;gBaBR3Sej|i0o*U?9%6s zwHt_0=EY($23FK?%1gLZ1K7p5HkF(3B9L<9G*$@<6t4K!W0^^Ml6(!2!Ll-3T2jrD zA!lF;YD%p`>$Q0PkWGvgv1!}5MY{$%SpN!5%_`1!9$Y7>*90YCV^fyfEFg8$@#v(t zpKQ{6)4Vyi?M~ip3e1^OYW_W|g$0_Bw*t7BZ20rhIZLjp+|h$sV8~M!?S-#){TP}? zcvk()6<^p*sg*3D^&eARNw3b)lYxE$aH&&9UBr?fPzr0-rvU{^b6tejlhHRs0Oq#> zUY=TbFf-{dDa7HIyj95Tvu5QzJsV5bT3=~ti*jtA%`Vk*r60u=!ut(UPb>U1Zo=p2p<8< zmqi=si+Tx&b71|SWZ9`v`!W?MlK*4y0;p-KQ39LJS{(}{w*U+$E7Sx9*8y^J{)>Cw zz)!|hpv(jB}W;T>Wq3cElAT=OC(9b#xJxap|n3c}%yNvQi3GT3@#Z)`pt*(_F3fcmYy9p1$V*)WH2;{)hef9UM~m9a_& ziI`qC)f_J`q(^*e$49;axZ_o>l2Y5*462rF$Q4W z0(V{!p&6`P+2%=NZMW3foSWL3#nz$7WMhlE>w6(NH8X}WiWNV(^in0XSv{b9{Cr!E z-(I9Kr;|UHr?6;MHzX!s33}Izx#`aD_06^9s%zjQ3uC&SEPfrD+L(z`UypU*L>ybd%Wz#=EnFdMeMgQHLZ^%tnHjTG z0v1#`<9{1~^gH~%e0j%uw5a-QCufxNvGL=0i1I!3)2T_n3!=G*juh)@Y9et}+FJCDx_j zqqG+$9nIApui^`ZMI;_p?h+(CLQ@w4c%*g=y{&$I3oC8K4pAO=O$7WE8p&G|)sZ6K z($lv>S6GtA?Zeb}?;`rmnBg1B5bh7DG!oBUbmu&kQpXJ0BjBvS-hEIQTPJU9^2+;L z;&ehHE}Hr;(7^=UQSG-3D<yfuEOa7njRp9;XmO09 z;H=XB0SyG^s$r|AXrvu%Xhpf20;1dkDD$Bs182SpKYn~5v#+VZ4*(&hh*BZvhFYew?!DO%O2)xsKaBZLG^ z%ZeDSUob>`aC`L(=#l#euRWsMuh*MnoFl88#R6;Ti@%c4RRuaOi2NziACJwqhE)y7 zkhHRC1Hf59l^~#)mEU953VGV;7ggj8;w=6c8P@n`$B_)r-aS7<$+B?jDpd9$F*-{aXw(^S7O-r&Eiz!d&bRG}9=y_rd!Zo5zCpebOCG&Bb*Lwes26~VlmG^tQ)n8`!v$IWWJ%Yu7CEsX1k(-N zZCu#^a8up9o@qnNeV_97rq$7c=?65hkp!DDK?YKdyxS}0LDMfzyKZ7XQv{JXdIU2?)1o`3u4!rVs z3$0AB?6V!~c?JhxzVFwxcr3^8kKwD2{X&+1y3&4#=G~y}t{$Gf7|TPXj?}IFq<2FT zzY7tsb6XG_Qnspzq@m-0^d%R?yoxmU{oZi8HT&8e%PAi+3AYvnKy$dgN8wb(&tYfj z#$4H(p3CqJX8D|o=j9=1+Lz(;K-3w-J2xMsU$+gftbf`7Yf7qkPNHxLg>(l1nD)}! z#o0&1;oJJoxnBuh@lt*GX9TeKu_euN!pM|KC(DpeifVpWwxVcQBL8w^B+#O%hLp-U zvzg}mF8eh4_z#yW$4id3@DUXJRS6$E8P^+?_;|k00I4lzvuigyf=+}L&g0V0%UzC; zE%*Xykfg-ave0Dh2m9_k(R7})6R?IG7HeNrg$@_~Wf5P{Vc+1xW!mU^3N~HOt{qLS zg(X|8{9b-LB4O8ffT-ySim4=fCL;0V&?j>kss+|xhtl6JwckwLTvwcwm~36bPOev6 zdUdkVqdM8*4;z{mtGv{<>`{XBf2SS@cO<@;WlW?)o#NEUagC-xVl6CAS87mGpm|CP zv4Ieyi_7*ukhoDduaC0>wvUCI+SSKr=tGODZpgsyNAf?6hu!3|k2#Ja_F*q@rQJD? zWB+;vC?1AS`UQJTkR9t*txb)bObqgW{$}x~>tLqHfxmU{-tE=bZx(aDd2bsoF|v;^ zEB<-2od>5<%O0-vJAK%UJoboP)ytnvfPbJ~R}LtTd`6^G;LUX4R@oNxZ7zLrPDQT8 zNoF2u1)8(h?azEBWi0Ijy)$vx#}-cns30v_=LVcp-&Di6_gu#3yQbneG#Qb8-jefT z7XGn8=2BDss8*eWrZsR-x@C9^@U%KNqDk z4f>K72+kS(TI=ICINa#RxCf~*mZUDs*{L*d#W`2HWD-~q6O9IRyn|0RVC%g@z4GU$ z6H-ZxyUFKk&MqUONe_N8O)n}^J{sL|u5u}gzfZp_ZzVLhwB$|-meN_CnBoJ6uc_)t z&05~pTb}Be7y;z2hr6tzEruigl-{N9fkBk}^dA5)z6-GsF#PSBkG(;3vQW7=?_!-( zNrv0=gs*YH5PrP1TNxoPp&Ai=nh%Kw#K_}t3_7TOHC1Te%$ZwY5V(E~<>cd-9y#62 zax*_U;+(@)CRu2dutxx4C^~M+Ea%k(=H|?Q{p5Bn9{+8*ogPIrmOWy#0J3!-A5kCk zHW%fO@?X!w1SqcT=1gW}YC1ji7QfBHEN$N&4NlUD(~|8kGS#83fVg61m*ZoA5i-p_ zn}|cRF`rjsmSN_uN8!h^m~+`PH$;ukCzf`5#NYix4op--UHp}{Y9{Hz_np$t`dN!L z@{L**P53yxHtZ}10)*f&Xop&DZN!`2GreuKr(egNHGm@%P?kuLtwT8%LhQ&x`sKnx zc{g=0H4nK)K zbCJbPei+>osz30kT~9giNlc!0og3Fe2=*7jF@munZ@(-gIu>I6t`>2;53G#PGZ%7|bX}<8 z$!AYvv$P6uxsIKaKBjJ5+SQ8x@5=eFU!RAjSeKhnu-vhpWBN07$a{Ol+~bADd0J}? zEJZZ!XU}G2{HyB9Prz)^QUmRCK5W)4X+!HuVIx#*g^W8t-t^oqcfAAjaIACldh#fZ z5AtwYjiJ3jZmPIf&Qt^oM zr`GIEzLD^QI=2}5eg7*0Ew-_Fz3`qLLD!2`wGv5_I=A%DGieJPsP=JC$hMX>h2->j zKBQZ?4t4ZU&;>h(TT8j51ARE2(dF&^wYw0~?Olfg?r7n1c0{IQWv&eS z^bKDiC7(L#lEoOXAr_W< zOnRTb&-D^aoR{sLB)0n<#N(uhsdKZU*7NFS6C_kTm3uxDe&B%U;DK(2r(JgZcrHCA z!26fv3o}5{f6DpuxwN2B&oM5_9?@ad(1`Nr^RaqW%0xSKmhZnHCP=I2MW43VQN+lt zc-pbxja;d(mP!_vCw-9VVvmq}X1a)JS{D*@c*q5iU)cM9 zFZ)Yfp69afpY4g^enCLwoXzJFen#rd;9?8$yq{iI8B(ER_1c?wD!k(Pf>^ajLmkRv zaGG=74dPkkX~hL~3!8w4tUei_5-<#j8lj@i-8Rh!3blTgKg z+2~sJu|PsgUHHBOLhd3x)v4di>ec827Kj7s;v_r-{e*8esd*)Wouo*h!Wx+E1R3at zi4b+VN%yIDX@@ww^aa5FXT9$joc6DwY3=+9aw{YI!pJF|)0`Jl>@>s>Zpb4LVW7V$LA1+=-xp_I&@7VRc zni2zTK6q)(1+da#B5pS%8kt?v(~&++Ps=&DtGNLwd)uK@=$Hm@eD>ZcEl%80+Q-u~ zkD1a5_uMCO^T~IL?$hA+D%1Q9h~W30)BIV(uX%BsEd(xP>p4oo#b-Z-A)jNN#5nTA zo{^?=>ga96t(jFlP#5s^FLZgTmv@?!;*%eB*T3W0NMAG@H`v;qH1fd5}Qbbnsh?sYscH< zNmT8K(w%CTxdD?5!`CLH>kBSJfA#71X3CyC{q(7I+3$q3QoJh7cJ17v=$SG}0dE`_ ztdA4?J~cJ9*ubr?+8zBS&R3Q4Ku2;8Z;Clts7X$H;EhyY2dO;S$o?(0UkRXR OAa!N1Ql)}b=>G!Zx`^Wd literal 0 HcmV?d00001 diff --git a/src/img/instagram.png b/src/img/instagram.png new file mode 100644 index 0000000000000000000000000000000000000000..98e24ea6a98ac8c523b1ba211b2d6ed5cb72abc8 GIT binary patch literal 405 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 Ox{nMWmS{Z-`+orB5?^)z literal 0 HcmV?d00001 diff --git a/src/img/twitter.png b/src/img/twitter.png new file mode 100644 index 0000000000000000000000000000000000000000..36b751a47a0beaf36fabaed4b39f2caf0d69dc70 GIT binary patch literal 326 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy_!3HG7B;uuk6lZ})WHAE+w=f7ZGR&GI0Tg5` z4sv&5Sa(k5C6L3C?&#~tz_78O`%fY(kbm3L#WAFUap{ys!6pTfHhJF%961xDpK$a( z;K*y3{etZ#%Qi>TM&$_MKeqfPK`j^Fzq5b;;OA#%e^yrpg@^9vtY$7;EwE_Yvt>>v zgBUk2Ty}U8_v+Npvcf#IsmC`o&7U+?HtqdXwbqh~d72FQ|IOCTvk1%a{dDEZkBpOr zcC6csCHtb!MRaZZJV)AWOaJjCmix2sHI+!JJ(H=5RqsA=&;H@N>%7#zuy~ON%#B|o VjJ95Wat`QC22WQ%mvv4FO#qQkfdK#j literal 0 HcmV?d00001 diff --git a/src/img/youtube.png b/src/img/youtube.png new file mode 100644 index 0000000000000000000000000000000000000000..f51731d4091084e7f089930baa2cf5a328ba421b GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`j)FbFd;%$g$s6l5$8 za(7}_cTVOdki(Mh=6C-KhYWaJ=XO*ZJDDZ0M6_}y zFiSKFO0c>mG?g?@jEGw_}Qh)J=eKMyFFTUcim|^L8qg!Be#)azc$S;>H zy51?aNTx-GR9Ldc1Y( fJF-jW+HvW|<9Bp#OWLFZJ;31U>gTe~DWM4f3?^xf literal 0 HcmV?d00001 diff --git a/src/util/loginCheck.ts b/src/util/loginCheck.ts new file mode 100644 index 000000000..ce47255dc --- /dev/null +++ b/src/util/loginCheck.ts @@ -0,0 +1,46 @@ +import style from '@/styles/signup.module.css'; +type I = HTMLInputElement; +type D = HTMLDivElement; + +export function emailError(inputBox: I, errorBox: D) { + let email = inputBox.value.trim(); + if (!isValidEmail(email)) { + showError('잘못된 이메일입니다', inputBox, errorBox); + } else { + showError('', inputBox, errorBox); + clearError(inputBox, errorBox); + } +} +export function pwError(inputBox: I, errorBox: D) { + if (inputBox?.value?.length < 8) { + showError('비밀번호를 8자 이상 입력해주세요', inputBox, errorBox); + } else { + clearError(inputBox, errorBox); + } +} + +export function showError(message: string, inputBox: I, errorBox: D) { + inputBox.classList.add(`${style['error-border']}`); + + errorBox.textContent = message; +} + +export function clearError(inputBox: I, errorBox: D) { + inputBox.classList.remove('error-border'); + errorBox.textContent = ''; +} + +export function isValidEmail(email: string) { + // 이메일 형식을 정규표현식을 사용하여 검사 + let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); +} + +export function isPassword(inputBox: I, repeatInputBox: I, errorBox: D) { + if (inputBox.value !== repeatInputBox.value) { + showError('비밀번호가 일치하지 않습니다.', repeatInputBox, errorBox); + } else { + clearError(repeatInputBox, errorBox); + } +} + diff --git a/styles/Main.module.css b/styles/Main.module.css new file mode 100644 index 000000000..610337c2c --- /dev/null +++ b/styles/Main.module.css @@ -0,0 +1,499 @@ +/* header */ + +#home { + cursor: pointer; + margin-left: 10px; +} + +#login { + cursor: pointer; + border: none; + background-color: #3692ff; + border-radius: 8px; + padding: 12px 20px; + color: #ffffff; + font-size: 16px; + font-weight: 600; + width: 128px; + height: 48px; + margin-right: 10px; +} + +/* main */ + +.mainFrame { + background: #cfe5ff; +} + +.card { + display: flex; + justify-content: center; + align-items: flex-end; + height: 540px; + width: 100%; +} + +.card .box { + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.box h1 { + font-weight: 700; + font-size: 40px; + line-height: 56px; + color: #374151; +} + +.box a { + width: 355px; + height: 56px; + border-radius: 40px; + background-color: #3692ff; + border: none; + color: #ffffff; + font-weight: 600; + font-size: 20px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + text-decoration: none; +} + +.card img { + width: 996px; + height: 447px; +} + +.section { + background-color: #ffffff; + height: 720px; + display: flex; + justify-content: center; + align-items: center; +} + +.section .confirmBox { + top: 137.5px; + left: 360px; + display: flex; + align-items: center; +} + +.confirmBox .specific { + padding-left: 50px; + text-align: left; +} + +.specific h1 { + font-weight: 700; + font-size: 40px; + line-height: 56px; + color: #374151; +} + +.specific p { + font-size: 24px; + font-weight: 500; + line-height: 28.8px; + color: #374151; +} + +.section .searchBox { + display: flex; + align-items: center; +} + +.searchBox .specific2 { + padding-right: 50px; + text-align: right; +} + +.specific2 h1 { + font-weight: 700; + font-size: 40px; + line-height: 56px; + color: #374151; +} + +.specific2 p { + font-weight: 500; + font-size: 24px; + line-height: 28.8px; + color: #374151; +} + +.card4 { + background-color: #ffffff; + height: 720px; + display: flex; + justify-content: center; + align-items: center; +} + +.section .registerBox { + display: flex; + align-items: center; +} + +.registerBox .specific3 { + padding-left: 50px; +} + +.specific3 h1 { + font-weight: 700; + font-size: 40px; + line-height: 56px; + color: #374151; +} + +.specific3 p { + font-weight: 500; + font-size: 24px; + line-height: 28.8px; + color: #374151; +} + +.bottomCard { + height: 540px; + display: flex; + justify-content: center; + align-items: center; +} + +.bottomCard h2 { + font-weight: 700; + font-size: 40px; + line-height: 56px; + color: #374151; +} + +.bottomCard img { + height: 540px; +} + +.footerFrame { + height: 160px; + background-color: #111827; +} + +.footerFrame .tag { + height: 50%; + display: flex; + align-items: center; + justify-content: center; +} +.footerFrame .tag .mark { + flex-grow: 1; + display: flex; + justify-content: space-between; +} + +.footerFrame .tag .mark .privacy-container { + margin-right: 50px; + display: flex; +} + +.tag .codeit { + margin-left: 50px; + color: #9ca3af; + font-weight: 400; + font-size: 16px; + text-align: center; +} + +.tag .privacy { + font-weight: 400; + font-size: 14px; + text-align: center; + color: #e5e7eb; +} +.tag .faq { + margin-left: 30px; + font-weight: 400; + font-size: 14px; + text-align: center; + color: #e5e7eb; +} + +.social { + margin-right: 40px; + flex-grow: 1; + display: flex; + justify-content: flex-end; + align-items: center; +} +.social a { + padding-right: 10px; +} + +@media (max-width: 1199px) { + .card { + height: 771px; + display: block; + } + + .card .box { + display: flex; + justify-content: center; + gap: 20px; + width: 100%; + height: 320px; + } + + .box h1 { + font-weight: 700; + font-size: 40px; + line-height: 56px; + color: #374151; + } + .box h1 > br { + display: none; + } + + .box a { + width: 355px; + height: 56px; + border-radius: 40px; + background-color: #3692ff; + border: none; + color: #ffffff; + font-weight: 600; + font-size: 20px; + text-align: center; + cursor: pointer; + } + + .card img { + width: 100%; + height: 450px; + } + /* 첫번째 쎅션 */ + + .section { + background-color: #ffffff; + height: 771px; + display: block; + width: 100%; + } + .section .confirmBox { + display: flex; + flex-direction: column; + align-items: center; + } + .section .confirmBox > img { + margin-top: 20px; + height: 454px; + width: 696px; + } + + .confirmBox .specific { + margin-top: 30px; + width: 696px; + display: flex; + flex-direction: column; + } + .specific h1 > br { + display: none; + } + .specific h1 { + font-weight: 700; + font-size: 32px; + line-height: 56px; + color: #374151; + } + + .specific p { + margin-top: 10px; + font-size: 18px; + font-weight: 500; + line-height: 28.8px; + color: #374151; + } + + /* 2번쩨 섹션 */ + + .section .searchBox { + display: flex; + flex-direction: column-reverse; + align-items: center; + } + .searchBox > img { + height: 454px; + width: 696px; + } + .searchBox .specific2 { + margin-top: 30px; + width: 696px; + padding-right: 50px; + text-align: right; + } + + .specific2 h1 { + font-weight: 700; + font-size: 32px; + line-height: 56px; + color: #374151; + } + + .specific2 h1 > br { + display: none; + } + + .specific2 p { + margin-top: 10px; + font-weight: 500; + font-size: 18px; + line-height: 28.8px; + color: #374151; + } + + /* 3번째 쎅션 */ + + .section .registerBox { + display: flex; + flex-direction: column; + align-items: center; + } + .registerBox > img { + width: 696px; + } + .registerBox .specific3 { + margin-top: 30px; + width: 696px; + } + + .specific3 h1 { + font-weight: 700; + font-size: 32px; + line-height: 56px; + color: #374151; + } + + .specific3 h1 > br { + display: none; + } + + .specific3 p { + font-weight: 500; + font-size: 18px; + line-height: 28.8px; + color: #374151; + } + + .bottomCard { + height: 927px; + display: flex; + flex-direction: column; + justify-content: flex-end; + align-items: center; + text-align: center; + } + + .bottomCard h2 { + font-size: 40px; + } + + .bottomCard img { + height: 540px; + } +} + +@media (max-width: 769px) { + .card { + height: 541px; + } + .box { + text-align: center; + } + .card .box h1 { + font-size: 32px; + } + .box h1 br { + display: block; + } + .box a { + height: 48px; + width: 154px; + font-size: 16px; + } + .card img { + width: 100%; + height: 221px; + } + .section .confirmBox > img { + margin-top: 50px; + width: 344px; + height: 259px; + } + .section .confirmBox .specific { + padding-left: 350px; + } + .section .confirmBox .specific h1 { + font-size: 24px; + } + .section .confirmBox .specific p { + font-size: 16px; + } + .section .searchBox > img { + margin-top: 50px; + width: 344px; + height: 259px; + } + .section .searchBox .specific2 { + padding-right: 350px; + } + + .section .searchBox .specific2 h1 { + font-size: 24px; + } + + .section .searchBox .specific2 p { + font-size: 16px; + } + .section .registerBox > img { + margin-top: 50px; + width: 344px; + height: 259px; + } + .section .registerBox .specific3 { + padding-left: 350px; + } + .section .registerBox .specific3 h1 { + font-size: 24px; + } + .bottomCard { + height: 540px; + } + .bottomCard h2 { + font-size: 32px; + } + .bottomCard img { + width: 497.91px; + height: 269.95px; + } + .footer .tag { + display: flex; + flex-direction: row-reverse; + } + + .tag .mark { + margin-left: 50px; + + flex-direction: column-reverse; + justify-content: space-around; + align-items: flex-start; + } + .tag .privacy-container { + margin-top: 20%; + } + .tag .mark .codeit { + margin-left: 0px; + margin-top: 50px; + } +} + diff --git a/styles/signup.module.css b/styles/signup.module.css new file mode 100644 index 000000000..9a374d72e --- /dev/null +++ b/styles/signup.module.css @@ -0,0 +1,135 @@ +.section { + margin-top: 70px; + display: flex; + flex-direction: column; + align-items: center; +} + +.signUpTable { + display: flex; + flex-direction: column; + text-align: le; + gap: 24px; +} + +.emailInput { + /* 모듈 css */ +} + +.section .error-border { + border: 2px solid red; +} +.emailError { + position: relative; + left: 10px; + bottom: 10px; + font-size: 15px; + color: #f74747; +} +.signUpTable label { + display: flex; + justify-content: center; + width: 100%; + height: 56px; +} +.pwError { + position: relative; + left: 10px; + bottom: 10px; + font-size: 15px; + color: #f74747; +} +.passwordInput { + /* 모듈 css */ +} +.passwordRepeatInput { + /* 모듈 css */ +} +.pwRepeatError { + position: relative; + left: 10px; + bottom: 10px; + font-size: 15px; + color: #f74747; +} + +label .inputContainer { + padding: 0px; + width: 100%; + height: 56px; + background: #f3f4f6; + border-radius: 12px; + border: none; +} + +.inputContainer:focus { + background-color: #ffffff; + border-color: var(--inputColor); +} +.inputContainer::placeholder { + padding: 16px 24px; +} + +.signUpButton { + cursor: pointer; + background-color: #9ca3af; + height: 56px; + border: none; + border-radius: 40px; + width: 640px; + font-size: 20px; + font-weight: 600; + color: #ffffff; + text-align: center; +} + +.simpleLoginBox { + border-radius: 8px; + padding-left: 24px; + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 24px; + width: 640px; + height: 74px; + background: #e6f2ff; +} +.simpleLoginIcons { + width: 100px; + margin-right: 16px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.passwordLabel { + position: relative; + display: flex; + align-items: center; +} +.passwordLabel img { + cursor: pointer; + position: absolute; + right: 50px; +} +.login { + margin-top: 24px; +} + +@media (max-width: 769px) { + .section .logo > img { + width: 196px; + height: 66px; + } + .section .signUpTable input { + width: 343px; + } + .signUpTable .signUpButton { + width: 343px; + } + + .simpleLoginBox { + width: 343px; + } +} + From 5a7789938294e20a59c5886bed495bc951f0eba2 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Thu, 20 Jun 2024 16:57:37 +0900 Subject: [PATCH 13/17] =?UTF-8?q?feat=20signIn=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20refreshApi=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/_app.tsx | 3 +- src/api/api.ts | 124 ++++++++++++++++++++------ src/api/axios.ts | 14 +-- src/api/test.ts | 2 - src/components/Header.tsx | 26 ++++-- src/components/LoginForm.tsx | 18 ++-- src/components/LoginFormContainer.tsx | 22 +++-- src/components/SignUpContainer.tsx | 25 ++++-- src/components/SignUpForm.tsx | 17 ++-- src/util/loginCheck.ts | 4 +- styles/Header.module.css | 3 + 11 files changed, 189 insertions(+), 69 deletions(-) diff --git a/pages/_app.tsx b/pages/_app.tsx index 2a2939c28..50589edb4 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,10 +2,11 @@ import React from 'react'; import type { AppProps } from 'next/app'; import Header from '@/src/components/Header'; import '../styles/Reset.css'; +import Cookies from 'js-cookie'; export default function App({ Component, pageProps }: AppProps) { return ( -

+
); diff --git a/src/api/api.ts b/src/api/api.ts index 70d71fd04..5f8e73ec7 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -10,9 +10,6 @@ import { import Cookies from 'js-cookie'; import { formType } from '../components/AddBoardForm'; -const E_MAIL = 'leedong0225@icloud.com'; -const PASS_WORD = 'abcd1234'; - export const getBestPosts = async (params: string): Promise => { const URL = `/articles?${params}`; try { @@ -47,21 +44,6 @@ export const getTotalPosts = async (params: string): Promise => { } }; -export const tempSignIn = async () => { - const TEMP_URL = '/auth/signIn'; - try { - if (!Cookies.get('accessToken')) { - const response = await instance.post(TEMP_URL, { - email: E_MAIL, - password: PASS_WORD, - }); - const { accessToken, refreshToken } = response.data; - Cookies.set('accessToken', accessToken); - Cookies.set('refreshToken', refreshToken); - } - } catch (error) {} -}; - export const postImage = async (image: File | null) => { const URL = '/images/upload'; @@ -144,15 +126,105 @@ export const getComments = async ( export const postComment = async (articleId: string, content: string) => { const URL = `/articles/${articleId}/comments`; - await instance.post( - URL, - { content: content }, - { - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', + try { + await instance.post( + URL, + { content: content }, + { + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + } + ); + } catch (error) { + const err = error as AxiosError; + if (err.response) { + console.error('Response error:', err.response.status); + console.error('Response data:', err.response.data); + throw err; + } + console.error(error); + throw error; + } +}; + +export const postSignUp = async ( + email: string, + nickname: string, + password: string, + passwordConfirmation: string +) => { + const URL = `auth/signUp`; + + try { + await instance.post( + URL, + { + email: email, + nickname: nickname, + password: password, + passwordConfirmation: passwordConfirmation, + }, + { headers: { 'Content-Type': 'application/json' } } + ); + } catch (error) { + const err = error as AxiosError; + if (err.response) { + console.error('Response error:', err.response.status); + console.error('Response data:', err.response.data); + throw err; + } + console.error(error); + throw error; + } +}; + +export const postSignIn = async (email: string, password: string) => { + const URL = `auth/signIn`; + try { + const response = await instance.post( + URL, + { + email: email, + password: password, + }, + { headers: { 'Content-Type': 'application/json' } } + ); + Cookies.set('accessToken', response.data.accessToken); + Cookies.set('refreshToken', response.data.refreshToken); + } catch (error) { + const err = error as AxiosError; + if (err.response) { + console.error('Response error:', err.response.status); + console.error('Response data:', err.response.data); + throw err; + } + console.error(error); + throw error; + } +}; + +export const postRefreshToken = async () => { + const URL = `auth/refresh-token`; + try { + const response = await instance.post( + URL, + { + refreshToken: Cookies.get('refreshToken'), }, + { headers: { 'Content-Type': 'application/json' } } + ); + Cookies.set('accessToken', response.data.accessToken); + } catch (error) { + const err = error as AxiosError; + if (err.response) { + console.error('Response error:', err.response.status); + console.error('Response data:', err.response.data); + throw err; } - ); + console.error(error); + throw error; + } }; diff --git a/src/api/axios.ts b/src/api/axios.ts index 27899d752..bdcc4bf02 100644 --- a/src/api/axios.ts +++ b/src/api/axios.ts @@ -1,10 +1,7 @@ -import axios, { - Axios, - AxiosRequestConfig, - InternalAxiosRequestConfig, -} from 'axios'; - +import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios'; import Cookies from 'js-cookie'; +import { postRefreshToken } from './api'; + const instance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API, }); @@ -17,8 +14,11 @@ instance.interceptors.request.use( } return config; }, - (error) => { + async (error: AxiosError) => { // 요청이 실패할 경우 실행됩니다. + if (error.status === 401) { + await postRefreshToken(); + } return Promise.reject(error); } ); diff --git a/src/api/test.ts b/src/api/test.ts index e29e8de9d..4dfd29c96 100644 --- a/src/api/test.ts +++ b/src/api/test.ts @@ -1,9 +1,7 @@ // api.test.js - import axios from 'axios'; import { getBestPosts } from './api'; import instance from './axios'; - describe('Integration tests with actual server', () => { it('fetchData returns data successfully from the server', async () => { // 예제 API 엔드포인트로 요청을 보냅니다. diff --git a/src/components/Header.tsx b/src/components/Header.tsx index fe2099e7f..7b67da138 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,15 +1,29 @@ -import React, { useContext } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import style from '../../styles/Header.module.css'; import logo from '../img/panda.png'; import profile from '../img/profile.png'; import Link from 'next/link'; +import Cookies from 'js-cookie'; +import { useRouter } from 'next/router'; interface headerProps { - isLogin: boolean; children: React.ReactNode; } -const Header = ({ isLogin, children }: headerProps) => { +const Header = ({ children }: headerProps) => { + const [isLoggedIn, setIsLoggedIn] = useState(false); + const route = useRouter(); + useEffect(() => { + // 쿠키에서 토큰을 가져옴 + const token = Cookies.get('accessToken'); + + // 토큰이 있으면 로그인 상태로 설정 + if (token) { + console.log('test'); + + setIsLoggedIn(true); + } + }, [route.pathname]); return ( <>
@@ -21,12 +35,14 @@ const Header = ({ isLogin, children }: headerProps) => {

중고마켓

- {isLogin ? ( + {isLoggedIn ? ( ) : ( - + + 로그인 + )}
diff --git a/src/components/LoginForm.tsx b/src/components/LoginForm.tsx index 2d0bfef16..f1bc59dbb 100644 --- a/src/components/LoginForm.tsx +++ b/src/components/LoginForm.tsx @@ -1,30 +1,32 @@ -import React from 'react'; +import React, { ChangeEvent } from 'react'; import style from '@/styles/Login.module.css'; import bigLogo from '@/src/img/bigLogo.png'; import kakaoImage from '@/src/img/kakao.png'; import googleImage from '@/src/img/google.png'; import openPassword from '@/src/img/openPassword.png'; import hidePassword from '@/src/img/hidePassword.png'; -import { OnChange, onClick } from './LoginFormContainer'; import Link from 'next/link'; interface Login { email: string; password: string; - onChangePassword: OnChange; - onChangeEmail: OnChange; + onChangePassword: (e: ChangeEvent) => void; + onChangeEmail: (e: ChangeEvent) => void; + loginClickHandler: () => void; } interface isHide { isOpen: boolean; - onClick: onClick; + eyeButtonClickHandler: () => void; } + const LoginForm = ({ email, password, onChangeEmail, onChangePassword, isOpen, - onClick, + eyeButtonClickHandler: onClick, + loginClickHandler, }: Login & isHide) => { return ( <> @@ -65,7 +67,9 @@ const LoginForm = ({
- +

간편 로그인 하기

diff --git a/src/components/LoginFormContainer.tsx b/src/components/LoginFormContainer.tsx index be57a144a..7b62a55f7 100644 --- a/src/components/LoginFormContainer.tsx +++ b/src/components/LoginFormContainer.tsx @@ -1,30 +1,38 @@ +import { useRouter } from 'next/router'; import React, { ChangeEvent, useState } from 'react'; +import { postRefreshToken, postSignIn } from '../api/api'; import LoginForm from './LoginForm'; -export type OnChange = (e: ChangeEvent) => void; -export type onClick = () => void; const LoginFormContainer = () => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [isOpen, setIsOpen] = useState(false); - const onChangeEmail: OnChange = (e) => { + const route = useRouter(); + + const onChangeEmail = (e: ChangeEvent) => { setEmail(e.target.value); }; - const onChangePassword: OnChange = (e) => { + const onChangePassword = (e: ChangeEvent) => { setPassword(e.target.value); }; - const onClick: onClick = () => { + const eyeButtonClickHandler = () => { setIsOpen(!isOpen); }; - + const loginClickHandler = async () => { + try { + await postSignIn(email, password); + route.push('/'); + } catch (error) {} + }; return ( ); }; diff --git a/src/components/SignUpContainer.tsx b/src/components/SignUpContainer.tsx index 2a591e843..0d489992a 100644 --- a/src/components/SignUpContainer.tsx +++ b/src/components/SignUpContainer.tsx @@ -1,15 +1,16 @@ import React, { ChangeEvent, useEffect, useState } from 'react'; import SignUpForm from './SignUpForm'; import { emailError, pwError, isPassword } from '@/src/util/loginCheck'; -import style from '@/styles/signup.module.css'; +import style from '@/styles/signUp.module.css'; +import { postSignUp } from '../api/api'; +import { useRouter } from 'next/navigation'; export interface SignUp { email: string; nickName: string; password: string; - repeatPassWord: string; + repeatPassword: string; } - export interface Show { passShow: boolean; repeatShow: boolean; @@ -20,13 +21,16 @@ const SignUpContainer = () => { email: '', nickName: '', password: '', - repeatPassWord: '', + repeatPassword: '', }); + const [isShow, setIsShow] = useState({ passShow: false, repeatShow: false, }); + const route = useRouter(); + const passwordHideHandler = () => { setIsShow({ ...isShow, passShow: !isShow.passShow }); }; @@ -39,7 +43,17 @@ const SignUpContainer = () => { const { name, value } = e.target; setUserInfo((prev) => ({ ...prev, [name]: value })); }; - + const serveSignUp = async () => { + try { + await postSignUp( + userInfo.email, + userInfo.nickName, + userInfo.password, + userInfo.repeatPassword + ); + route.push('/login'); + } catch (error) {} + }; useEffect(() => { const onEmailFocus = document.querySelector( `.${style.emailInput}` @@ -93,6 +107,7 @@ const SignUpContainer = () => { isShow={isShow} passwordHideHandler={passwordHideHandler} repeatPasswordHideHandler={repeatPasswordHideHandler} + serveSignUp={serveSignUp} /> ); }; diff --git a/src/components/SignUpForm.tsx b/src/components/SignUpForm.tsx index ede9c66e0..3a7f20659 100644 --- a/src/components/SignUpForm.tsx +++ b/src/components/SignUpForm.tsx @@ -11,6 +11,7 @@ import Link from 'next/link'; interface SignUpInfo { userInfo?: SignUp; onChangeHandler: (e: ChangeEvent) => void; + serveSignUp: () => void; } interface EyesButton { isShow: Show; @@ -24,6 +25,7 @@ const SignUpForm = ({ isShow, passwordHideHandler, repeatPasswordHideHandler, + serveSignUp, }: SignUpInfo & EyesButton) => { return (
@@ -43,7 +45,7 @@ const SignUpForm = ({ type='email' /> -
+
닉네임 @@ -61,7 +64,7 @@ const SignUpForm = ({ value={userInfo?.password} name='password' onChange={onChangeHandler} - className={styles['passwordInput']} + className={`${styles['passwordInput']} ${styles['inputContainer']}`} type={isShow.passShow ? 'text' : 'password'} placeholder='비밀번호를 입력해주세요' /> @@ -72,14 +75,14 @@ const SignUpForm = ({ alt='' /> -
+
비밀번호 확인
- +

간편로그인하기

diff --git a/src/util/loginCheck.ts b/src/util/loginCheck.ts index ce47255dc..e33de75a7 100644 --- a/src/util/loginCheck.ts +++ b/src/util/loginCheck.ts @@ -7,7 +7,6 @@ export function emailError(inputBox: I, errorBox: D) { if (!isValidEmail(email)) { showError('잘못된 이메일입니다', inputBox, errorBox); } else { - showError('', inputBox, errorBox); clearError(inputBox, errorBox); } } @@ -21,12 +20,11 @@ export function pwError(inputBox: I, errorBox: D) { export function showError(message: string, inputBox: I, errorBox: D) { inputBox.classList.add(`${style['error-border']}`); - errorBox.textContent = message; } export function clearError(inputBox: I, errorBox: D) { - inputBox.classList.remove('error-border'); + inputBox.classList.remove(`${style['error-border']}`); errorBox.textContent = ''; } diff --git a/styles/Header.module.css b/styles/Header.module.css index 26376f680..bcf333a2e 100644 --- a/styles/Header.module.css +++ b/styles/Header.module.css @@ -38,7 +38,10 @@ border: 1px solid; width: 88px; height: 42px; + text-align: center; + text-decoration: none; border-radius: 8px; + line-height: 42px; background-color: #3692ff; color: #ffffff; font-size: 16px; From f2de1e976adca139a62ee128216ae2798f128093 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Fri, 12 Jul 2024 16:00:11 +0900 Subject: [PATCH 14/17] =?UTF-8?q?feat=20=ED=86=A0=ED=81=B0=EC=9D=B4=20?= =?UTF-8?q?=EC=9E=88=EC=9D=84=EC=8B=9C=20=EC=A0=91=EA=B7=BC=20=EB=B6=88?= =?UTF-8?q?=EA=B0=80=ED=95=9C=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=EC=8B=9C=20=EB=A6=AC=EB=8B=A4=EC=9D=B4=EB=A0=89?= =?UTF-8?q?=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next.config.js | 2 +- pages/_app.tsx | 1 - src/api/axios.ts | 15 +++++++++----- src/api/test.ts | 15 -------------- src/components/AddBoardContainer.tsx | 15 ++++++++++---- src/components/Header.tsx | 10 ++++----- src/components/LoginForm.tsx | 9 ++++---- src/components/LoginFormContainer.tsx | 30 +++++++++++++++++++++++---- src/components/SignUpContainer.tsx | 26 ++++++++++++++++------- styles/Header.module.css | 12 +++++++++-- 10 files changed, 85 insertions(+), 50 deletions(-) delete mode 100644 src/api/test.ts diff --git a/next.config.js b/next.config.js index 3776bb093..8794808c0 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - reactStrictMode: true, + reactStrictMode: false, }; module.exports = nextConfig; diff --git a/pages/_app.tsx b/pages/_app.tsx index 50589edb4..4c4bc53ed 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,7 +2,6 @@ import React from 'react'; import type { AppProps } from 'next/app'; import Header from '@/src/components/Header'; import '../styles/Reset.css'; -import Cookies from 'js-cookie'; export default function App({ Component, pageProps }: AppProps) { return ( diff --git a/src/api/axios.ts b/src/api/axios.ts index bdcc4bf02..ef6aaba2d 100644 --- a/src/api/axios.ts +++ b/src/api/axios.ts @@ -1,4 +1,4 @@ -import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios'; +import axios, { AxiosError } from 'axios'; import Cookies from 'js-cookie'; import { postRefreshToken } from './api'; @@ -7,18 +7,23 @@ const instance = axios.create({ }); instance.interceptors.request.use( - (config: InternalAxiosRequestConfig) => { + (config) => { const token = Cookies.get('accessToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, + async (error: AxiosError) => { - // 요청이 실패할 경우 실행됩니다. - if (error.status === 401) { - await postRefreshToken(); + const originalRequest = error.config; + if (typeof originalRequest !== 'undefined') { + if (error.response?.status === 401) { + await postRefreshToken(); + return instance.request(originalRequest); + } } + // 요청이 실패할 경우 실행됩니다. return Promise.reject(error); } ); diff --git a/src/api/test.ts b/src/api/test.ts deleted file mode 100644 index 4dfd29c96..000000000 --- a/src/api/test.ts +++ /dev/null @@ -1,15 +0,0 @@ -// api.test.js -import axios from 'axios'; -import { getBestPosts } from './api'; -import instance from './axios'; -describe('Integration tests with actual server', () => { - it('fetchData returns data successfully from the server', async () => { - // 예제 API 엔드포인트로 요청을 보냅니다. - getBestPosts('page=1&pageSize=3&orderBy=like'); - - // expect(response.status).toBe(200); - // expect(response.data).toBeDefined(); - // 실제 응답 데이터에 대한 추가 검증을 수행할 수 있습니다. - }); -}); - diff --git a/src/components/AddBoardContainer.tsx b/src/components/AddBoardContainer.tsx index deb721691..9c3d9d2ba 100644 --- a/src/components/AddBoardContainer.tsx +++ b/src/components/AddBoardContainer.tsx @@ -1,11 +1,21 @@ import { useRouter } from 'next/router'; import React, { ChangeEvent, useEffect, useState } from 'react'; -import { postArticles, postImage, tempSignIn } from '../api/api'; +import { postArticles, postImage } from '../api/api'; import AddBoardForm from './AddBoardForm'; import { formType } from './AddBoardForm'; +import Cookies from 'js-cookie'; +const ACCESS_TOKEN = Cookies.get('accessToken'); const AddBoardContainer = () => { const routes = useRouter(); + + useEffect(() => { + if (!ACCESS_TOKEN) { + alert('로그인이 필요합니다.'); + routes.replace('/boards'); + } + }, []); + const [previewImage, setPreviewImage] = useState(''); const [formData, setFormData] = useState({ title: '', @@ -41,9 +51,6 @@ const AddBoardContainer = () => { const result = await postArticles(formData, url); routes.push('/boards'); }; - useEffect(() => { - tempSignIn(); - }, []); return ( <> diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 7b67da138..efd828121 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import style from '../../styles/Header.module.css'; import logo from '../img/panda.png'; import profile from '../img/profile.png'; @@ -31,13 +31,13 @@ const Header = ({ children }: headerProps) => { 로고 -

자유게시판

-

중고마켓

+ 자유게시판 + 중고마켓
{isLoggedIn ? ( - ) : ( diff --git a/src/components/LoginForm.tsx b/src/components/LoginForm.tsx index f1bc59dbb..1b266e083 100644 --- a/src/components/LoginForm.tsx +++ b/src/components/LoginForm.tsx @@ -12,7 +12,7 @@ interface Login { password: string; onChangePassword: (e: ChangeEvent) => void; onChangeEmail: (e: ChangeEvent) => void; - loginClickHandler: () => void; + loginClickHandler: (e: React.FormEvent) => void; } interface isHide { isOpen: boolean; @@ -30,7 +30,7 @@ const LoginForm = ({ }: Login & isHide) => { return ( <> -
+
@@ -56,7 +56,6 @@ const LoginForm = ({ type={isOpen ? 'text' : 'password'} placeholder='비밀번호를 입력해주세요' /> -
-
@@ -81,7 +80,7 @@ const LoginForm = ({
-
+
판다 마켓이 처음이신가요? 회원가입
diff --git a/src/components/LoginFormContainer.tsx b/src/components/LoginFormContainer.tsx index 7b62a55f7..9e4f9bf0d 100644 --- a/src/components/LoginFormContainer.tsx +++ b/src/components/LoginFormContainer.tsx @@ -1,7 +1,12 @@ import { useRouter } from 'next/router'; -import React, { ChangeEvent, useState } from 'react'; -import { postRefreshToken, postSignIn } from '../api/api'; +import React, { ChangeEvent, useState, useEffect } from 'react'; +import { postSignIn } from '../api/api'; import LoginForm from './LoginForm'; +import { AxiosError } from 'axios'; +import Cookies from 'js-cookie'; +import { redirect } from 'next/navigation'; + +const ACCESS_TOKEN = Cookies.get('accessToken'); const LoginFormContainer = () => { const [email, setEmail] = useState(''); @@ -12,18 +17,35 @@ const LoginFormContainer = () => { const onChangeEmail = (e: ChangeEvent) => { setEmail(e.target.value); }; + const onChangePassword = (e: ChangeEvent) => { setPassword(e.target.value); }; + const eyeButtonClickHandler = () => { setIsOpen(!isOpen); }; - const loginClickHandler = async () => { + + const loginClickHandler = async (e: React.FormEvent) => { + e.preventDefault(); + try { await postSignIn(email, password); route.push('/'); - } catch (error) {} + } catch (error) { + if (error instanceof AxiosError) { + if (error.response?.status === 400) { + alert(error.response.data.message); + } + } + } }; + + useEffect(() => { + if (ACCESS_TOKEN) { + route.back(); + } + }, []); return ( { userInfo.repeatPassword ); route.push('/login'); - } catch (error) {} + } catch (error) { + if (error instanceof AxiosError) { + if (error.response?.status === 400) { + alert(error.response.data.message); + } + } + } }; + useEffect(() => { const onEmailFocus = document.querySelector( - `.${style.emailInput}` + `.${styles.emailInput}` ) as HTMLInputElement; const emailErrorBox = document.querySelector( - `.${style.emailError}` + `.${styles.emailError}` ) as HTMLDivElement; onEmailFocus.addEventListener('focusout', () => @@ -67,17 +76,17 @@ const SignUpContainer = () => { ); const onPasswordFocus = document.querySelector( - `.${style.passwordInput}` + `.${styles.passwordInput}` ) as HTMLInputElement; const passwordErrorBox = document.querySelector( - `.${style.pwError}` + `.${styles.pwError}` ) as HTMLDivElement; const passwordRepeatFocus = document.querySelector( - `.${style.passwordRepeatInput}` + `.${styles.passwordRepeatInput}` ) as HTMLInputElement; const passwordRepeatErrorBox = document.querySelector( - `.${style.pwRepeatError}` + `.${styles.pwRepeatError}` ) as HTMLInputElement; onPasswordFocus.addEventListener('focusout', () => @@ -100,6 +109,7 @@ const SignUpContainer = () => { ); }; }, []); + return ( Date: Fri, 12 Jul 2024 20:27:28 +0900 Subject: [PATCH 15/17] =?UTF-8?q?refactor-=20=EB=A6=AC=EC=95=A1=ED=8A=B8?= =?UTF-8?q?=ED=9B=85=ED=8F=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 29 ++++++++- package.json | 4 +- src/components/SignUpContainer.tsx | 89 +++++++-------------------- src/components/SignUpForm.tsx | 98 +++++++++++++++++++++--------- styles/signup.module.css | 36 ++--------- 5 files changed, 125 insertions(+), 131 deletions(-) diff --git a/package-lock.json b/package-lock.json index 18c60e601..b0a1d08cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,14 @@ "name": "fe-weekly-mission", "version": "0.1.0", "dependencies": { + "@hookform/error-message": "^2.0.1", "@types/js-cookie": "^3.0.6", "axios": "^1.7.2", "js-cookie": "^3.0.5", "next": "13.5.6", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "react-hook-form": "^7.52.1" }, "devDependencies": { "@types/jest": "^29.5.12", @@ -722,6 +724,16 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@hookform/error-message": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-2.0.1.tgz", + "integrity": "sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0", + "react-hook-form": "^7.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -5776,6 +5788,21 @@ "react": "^18.2.0" } }, + "node_modules/react-hook-form": { + "version": "7.52.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.1.tgz", + "integrity": "sha512-uNKIhaoICJ5KQALYZ4TOaOLElyM+xipord+Ha3crEFhTntdLvWZqVY49Wqd/0GiVCA/f9NjemLeiNPjG7Hpurg==", + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index cc365e685..25ce2e507 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,14 @@ "test:watch": "jest --watch" }, "dependencies": { + "@hookform/error-message": "^2.0.1", "@types/js-cookie": "^3.0.6", "axios": "^1.7.2", "js-cookie": "^3.0.5", "next": "13.5.6", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "react-hook-form": "^7.52.1" }, "devDependencies": { "@types/jest": "^29.5.12", diff --git a/src/components/SignUpContainer.tsx b/src/components/SignUpContainer.tsx index 619298ef0..9745dc0d2 100644 --- a/src/components/SignUpContainer.tsx +++ b/src/components/SignUpContainer.tsx @@ -1,11 +1,10 @@ import React, { ChangeEvent, useEffect, useState } from 'react'; import SignUpForm from './SignUpForm'; -import { emailError, pwError, isPassword } from '@/src/util/loginCheck'; -import styles from '@/styles/signup.module.css'; + import { postSignUp } from '../api/api'; import { useRouter } from 'next/navigation'; import { AxiosError } from 'axios'; - +import { useForm } from 'react-hook-form'; export interface SignUp { email: string; nickName: string; @@ -19,12 +18,14 @@ export interface Show { } const SignUpContainer = () => { - const [userInfo, setUserInfo] = useState({ - email: '', - nickName: '', - password: '', - repeatPassword: '', - }); + const { + watch, + register, + formState: { errors }, + setError, + clearErrors, + handleSubmit, + } = useForm({ mode: 'onChange' }); const [isShow, setIsShow] = useState({ passShow: false, @@ -41,17 +42,13 @@ const SignUpContainer = () => { setIsShow({ ...isShow, repeatShow: !isShow.repeatShow }); }; - const onChangeHandler = (e: ChangeEvent) => { - const { name, value } = e.target; - setUserInfo((prev) => ({ ...prev, [name]: value })); - }; - const serveSignUp = async () => { + const serveSignUp = async (data: SignUp) => { try { await postSignUp( - userInfo.email, - userInfo.nickName, - userInfo.password, - userInfo.repeatPassword + data.email, + data.nickName, + data.password, + data.repeatPassword ); route.push('/login'); } catch (error) { @@ -63,61 +60,17 @@ const SignUpContainer = () => { } }; - useEffect(() => { - const onEmailFocus = document.querySelector( - `.${styles.emailInput}` - ) as HTMLInputElement; - const emailErrorBox = document.querySelector( - `.${styles.emailError}` - ) as HTMLDivElement; - - onEmailFocus.addEventListener('focusout', () => - emailError(onEmailFocus, emailErrorBox) - ); - - const onPasswordFocus = document.querySelector( - `.${styles.passwordInput}` - ) as HTMLInputElement; - const passwordErrorBox = document.querySelector( - `.${styles.pwError}` - ) as HTMLDivElement; - - const passwordRepeatFocus = document.querySelector( - `.${styles.passwordRepeatInput}` - ) as HTMLInputElement; - const passwordRepeatErrorBox = document.querySelector( - `.${styles.pwRepeatError}` - ) as HTMLInputElement; - - onPasswordFocus.addEventListener('focusout', () => - pwError(onPasswordFocus, passwordErrorBox) - ); - - passwordRepeatFocus.addEventListener('focusout', () => - isPassword(onPasswordFocus, passwordRepeatFocus, passwordRepeatErrorBox) - ); - - return () => { - onEmailFocus.removeEventListener('focusout', () => - emailError(onEmailFocus, emailErrorBox) - ); - onPasswordFocus.removeEventListener('focusout', () => - isPassword(onPasswordFocus, passwordRepeatFocus, passwordRepeatErrorBox) - ); - passwordRepeatFocus.removeEventListener('focusout', () => - isPassword(onPasswordFocus, passwordRepeatFocus, passwordRepeatErrorBox) - ); - }; - }, []); - return ( ); }; diff --git a/src/components/SignUpForm.tsx b/src/components/SignUpForm.tsx index 3a7f20659..c4cd746ec 100644 --- a/src/components/SignUpForm.tsx +++ b/src/components/SignUpForm.tsx @@ -1,4 +1,4 @@ -import React, { ChangeEvent } from 'react'; +import React, { useEffect } from 'react'; import { Show, SignUp } from './SignUpContainer'; import styles from '@/styles/signup.module.css'; import hideEyes from '@/src/img/hidePassword.png'; @@ -7,12 +7,24 @@ import kakao from '@/src/img/kakao.png'; import google from '@/src/img/google.png'; import bigLogo from '@/src/img/bigLogo.png'; import Link from 'next/link'; +import { + UseFormRegister, + FieldErrors, + UseFormWatch, + UseFormClearErrors, + UseFormSetError, +} from 'react-hook-form'; +import { ErrorMessage } from '@hookform/error-message'; interface SignUpInfo { - userInfo?: SignUp; - onChangeHandler: (e: ChangeEvent) => void; - serveSignUp: () => void; + handleSubmit: () => void; + register: UseFormRegister; + watch: UseFormWatch; + setError: UseFormSetError; + clearErrors: UseFormClearErrors; + errors: FieldErrors; } + interface EyesButton { isShow: Show; passwordHideHandler: () => void; @@ -20,50 +32,75 @@ interface EyesButton { } const SignUpForm = ({ - userInfo, - onChangeHandler, + clearErrors, + setError, + register, + handleSubmit, + errors, isShow, passwordHideHandler, repeatPasswordHideHandler, - serveSignUp, + watch, }: SignUpInfo & EyesButton) => { + useEffect(() => { + if (watch('password') !== watch('repeatPassword')) { + setError('repeatPassword', { + type: 'password-mismatch', + message: '비밀번호가 일치하지 않습니다', + }); + } else { + // 비밀번호 일치시 오류 제거 + clearErrors('repeatPassword'); + } + }, [watch('password'), watch('repeatPassword')]); + return (
-
+ +
이메일 -
+

{message}

} + /> 닉네임 +

{message}

} + /> 비밀번호 -
비밀번호 확인 -
- -
+ +

간편로그인하기

diff --git a/styles/signup.module.css b/styles/signup.module.css index 9a374d72e..65d05ae0c 100644 --- a/styles/signup.module.css +++ b/styles/signup.module.css @@ -12,46 +12,16 @@ gap: 24px; } -.emailInput { - /* 모듈 css */ -} - -.section .error-border { - border: 2px solid red; -} -.emailError { - position: relative; - left: 10px; - bottom: 10px; - font-size: 15px; +.error { color: #f74747; } + .signUpTable label { display: flex; justify-content: center; width: 100%; height: 56px; } -.pwError { - position: relative; - left: 10px; - bottom: 10px; - font-size: 15px; - color: #f74747; -} -.passwordInput { - /* 모듈 css */ -} -.passwordRepeatInput { - /* 모듈 css */ -} -.pwRepeatError { - position: relative; - left: 10px; - bottom: 10px; - font-size: 15px; - color: #f74747; -} label .inputContainer { padding: 0px; @@ -107,11 +77,13 @@ label .inputContainer { display: flex; align-items: center; } + .passwordLabel img { cursor: pointer; position: absolute; right: 50px; } + .login { margin-top: 24px; } From 4539b041fe7862ef30b55a444dba3f45f03dc795 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Fri, 12 Jul 2024 23:19:04 +0900 Subject: [PATCH 16/17] =?UTF-8?q?feat=20=EB=AC=B4=ED=95=9C=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/boards.tsx | 6 +-- src/api/api.ts | 3 ++ src/components/Post.tsx | 1 - src/components/SelectAndSearchContainer.tsx | 15 +++++- src/components/SignUpForm.tsx | 2 +- src/components/TotalPostsContainer.tsx | 54 ++++++++++++++++----- styles/Post.module.css | 4 ++ 7 files changed, 66 insertions(+), 19 deletions(-) diff --git a/pages/boards.tsx b/pages/boards.tsx index f2e98a232..1228c7f35 100644 --- a/pages/boards.tsx +++ b/pages/boards.tsx @@ -1,6 +1,6 @@ import BestPostsContainer from '@/src/components/BestPostsContainer'; import TotalPosts from '@/src/components/TotalPosts'; -import React from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import style from '../styles/BoardFrame.module.css'; import { GetServerSideProps } from 'next'; import { AxiosError } from 'axios'; @@ -19,8 +19,8 @@ const boards: React.FC = ({ bestPosts }) => { ); }; -export const getServerSideProps: GetServerSideProps = async() => { - const URL = 'page=1&pageSize=3&orderBy=like'; +export const getServerSideProps: GetServerSideProps = async () => { + const URL = `page=1&pageSize=3&orderBy=like`; try { const bestPosts = await getBestPosts(URL); return { diff --git a/src/api/api.ts b/src/api/api.ts index 5f8e73ec7..724c9673a 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -9,6 +9,7 @@ import { } from './apiType'; import Cookies from 'js-cookie'; import { formType } from '../components/AddBoardForm'; +import { url } from 'inspector'; export const getBestPosts = async (params: string): Promise => { const URL = `/articles?${params}`; @@ -30,6 +31,8 @@ export const getBestPosts = async (params: string): Promise => { export const getTotalPosts = async (params: string): Promise => { const URL = `/articles?${params}`; try { + console.log(URL); + const response: AxiosResponse = await instance.get(URL); return response.data.list; } catch (error) { diff --git a/src/components/Post.tsx b/src/components/Post.tsx index d060b3bc7..253e872e3 100644 --- a/src/components/Post.tsx +++ b/src/components/Post.tsx @@ -3,7 +3,6 @@ import style from '@/styles/Post.module.css'; import profile from '@/src/img/profile.png'; import heart from '@/src/img/heart.png'; import { convertTime } from '../util/convertTime'; -import Link from 'next/link'; interface postItem { image: string | null; diff --git a/src/components/SelectAndSearchContainer.tsx b/src/components/SelectAndSearchContainer.tsx index 60e44d8cd..ff992a5e4 100644 --- a/src/components/SelectAndSearchContainer.tsx +++ b/src/components/SelectAndSearchContainer.tsx @@ -20,11 +20,22 @@ const SelectAndSearchContainer = () => { }; const onChangeKeyDownHandler = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { - router.push(`/boards?keyword=${ref.current?.value}`); + if (ref.current?.value !== '') { + return router.push( + `/boards?keyword=${ref.current?.value}&orderBy=${selectedOption}` + ); + } + router.push(`boards?&orderBy=${selectedOption}`); } }; useEffect(() => { - router.push(`/boards?page=1&pageSize=5&orderBy=${selectedOption}`); + if (ref.current?.value !== '') { + router.push( + `/boards?keyword=${ref.current?.value}&orderBy=${selectedOption}` + ); + } else { + router.push(`/boards?orderBy=${selectedOption}`); + } }, [selectedOption]); return ( - + diff --git a/src/components/TotalPostsContainer.tsx b/src/components/TotalPostsContainer.tsx index 47d383a5c..32599fe29 100644 --- a/src/components/TotalPostsContainer.tsx +++ b/src/components/TotalPostsContainer.tsx @@ -1,38 +1,67 @@ import { useRouter } from 'next/router'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useRef } from 'react'; import { getTotalPosts } from '../api/api'; import { writingType } from '../api/apiType'; import Post from './Post'; import { AxiosError } from 'axios'; -export const URL = `page=1&pageSize=5`; +import style from '@/styles/Post.module.css'; const TotalPostsContainer = () => { const router = useRouter(); const { orderBy, keyword } = router.query; const [posts, setPosts] = useState([]); + const target = useRef(null); + const [limit, setLimit] = useState(6); + + let preventFirst = 0; + + const callback = (entry: IntersectionObserverEntry[]) => { + if (entry[0].isIntersecting && preventFirst > 0) { + setLimit((prev) => prev + 6); + } + preventFirst++; + }; + + useEffect(() => { + const observer = new IntersectionObserver(callback, { threshold: 1 }); + if (target.current !== null) { + observer.observe(target.current); + } + return () => { + observer.disconnect(); + }; + }, []); + const getPosts = async () => { - if (orderBy) { + if (keyword && orderBy) { try { - const result = await getTotalPosts(`${URL}&orderBy=${orderBy}`); - setPosts(result); - } catch (error) { - const err = error as AxiosError; - } - } else if (keyword) { - try { - const result = await getTotalPosts(`${URL}&keyword=${keyword}`); + const result = await getTotalPosts( + `page=1&pageSize=${limit}&orderBy=${orderBy}&keyword=${keyword}` + ); setPosts(result); } catch (error) { const err = error as AxiosError; } + return; + } + + try { + const result = await getTotalPosts( + `page=1&pageSize=${limit}&orderBy=${orderBy}` + ); + setPosts(result); + } catch (error) { + const err = error as AxiosError; } }; const onClickHandler = (id: number) => { router.push(`/board/${id}`); }; + useEffect(() => { getPosts(); - }, [orderBy, keyword]); + }, [router.query, limit]); + return ( <> {posts.map((element) => ( @@ -47,6 +76,7 @@ const TotalPostsContainer = () => { createdAt={element.createdAt} /> ))} +
); }; diff --git a/styles/Post.module.css b/styles/Post.module.css index 818f81d4c..7604f7636 100644 --- a/styles/Post.module.css +++ b/styles/Post.module.css @@ -61,3 +61,7 @@ align-items: center; } +.observer { + height: 50px; +} + From 7a8cbfd8cd13e738fd663c48b33e18f2730cc598 Mon Sep 17 00:00:00 2001 From: leedongkyu Date: Tue, 16 Jul 2024 18:25:49 +0900 Subject: [PATCH 17/17] =?UTF-8?q?refactor=20middleware=EB=A1=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=8B=A4=EC=9D=B4=EB=A0=89=EC=85=98=20refactor=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=ED=82=A4=20=EC=83=81=EC=88=98=ED=99=94=20?= =?UTF-8?q?=EB=AC=B4=ED=95=9C=EC=8A=A4=ED=81=AC=EB=A1=A4=20ref=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=AA=85=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- middleware.ts | 20 ++++++++++++ src/api/api.ts | 5 ++- src/api/apiType.ts | 3 ++ src/api/axios.ts | 4 ++- src/components/AddBoardContainer.tsx | 12 +------ src/components/CommentContainer.tsx | 6 ++-- src/components/TotalPostsContainer.tsx | 26 +++------------ src/hook/useInfiniteScroll.tsx | 28 ++++++++++++++++ src/util/loginCheck.ts | 44 -------------------------- 9 files changed, 65 insertions(+), 83 deletions(-) create mode 100644 middleware.ts create mode 100644 src/hook/useInfiniteScroll.tsx delete mode 100644 src/util/loginCheck.ts diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 000000000..33fc3c441 --- /dev/null +++ b/middleware.ts @@ -0,0 +1,20 @@ +import { NextResponse } from 'next/server'; +import { NextRequest } from 'next/server'; +import { ACCESS_TOKEN } from './src/api/apiType'; + +export function middleware(request: NextRequest) { + const jwt = request.cookies.get(ACCESS_TOKEN); + + if (jwt && request.nextUrl.pathname === '/login') { + return NextResponse.redirect(new URL('/', request.url)); + } + if (!jwt && request.nextUrl.pathname === '/addboard') { + return NextResponse.redirect(new URL('/login', request.url)); + } + return NextResponse.next(); +} + +export const config = { + matcher: ['/login', '/addboard'], +}; + diff --git a/src/api/api.ts b/src/api/api.ts index 724c9673a..57e82dab0 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -9,7 +9,6 @@ import { } from './apiType'; import Cookies from 'js-cookie'; import { formType } from '../components/AddBoardForm'; -import { url } from 'inspector'; export const getBestPosts = async (params: string): Promise => { const URL = `/articles?${params}`; @@ -31,8 +30,6 @@ export const getBestPosts = async (params: string): Promise => { export const getTotalPosts = async (params: string): Promise => { const URL = `/articles?${params}`; try { - console.log(URL); - const response: AxiosResponse = await instance.get(URL); return response.data.list; } catch (error) { @@ -142,6 +139,7 @@ export const postComment = async (articleId: string, content: string) => { ); } catch (error) { const err = error as AxiosError; + if (err.response) { console.error('Response error:', err.response.status); console.error('Response data:', err.response.data); @@ -194,6 +192,7 @@ export const postSignIn = async (email: string, password: string) => { }, { headers: { 'Content-Type': 'application/json' } } ); + Cookies.set('accessToken', response.data.accessToken); Cookies.set('refreshToken', response.data.refreshToken); } catch (error) { diff --git a/src/api/apiType.ts b/src/api/apiType.ts index c47cc5e19..a545b34d8 100644 --- a/src/api/apiType.ts +++ b/src/api/apiType.ts @@ -1,3 +1,6 @@ +export const ACCESS_TOKEN = 'accessToken'; +export const REFRESH_TOKEN = 'refreshToken'; + export interface articlesType extends articleType { totalCount?: number; list: articleType[]; diff --git a/src/api/axios.ts b/src/api/axios.ts index ef6aaba2d..cdd7b40c5 100644 --- a/src/api/axios.ts +++ b/src/api/axios.ts @@ -1,14 +1,16 @@ import axios, { AxiosError } from 'axios'; import Cookies from 'js-cookie'; import { postRefreshToken } from './api'; +import { ACCESS_TOKEN } from './apiType'; const instance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API, + headers: { 'Content-Type': 'application/json' }, }); instance.interceptors.request.use( (config) => { - const token = Cookies.get('accessToken'); + const token = Cookies.get(ACCESS_TOKEN); if (token) { config.headers.Authorization = `Bearer ${token}`; } diff --git a/src/components/AddBoardContainer.tsx b/src/components/AddBoardContainer.tsx index 9c3d9d2ba..d2512286d 100644 --- a/src/components/AddBoardContainer.tsx +++ b/src/components/AddBoardContainer.tsx @@ -1,21 +1,11 @@ import { useRouter } from 'next/router'; -import React, { ChangeEvent, useEffect, useState } from 'react'; +import React, { ChangeEvent, useState } from 'react'; import { postArticles, postImage } from '../api/api'; import AddBoardForm from './AddBoardForm'; import { formType } from './AddBoardForm'; -import Cookies from 'js-cookie'; -const ACCESS_TOKEN = Cookies.get('accessToken'); const AddBoardContainer = () => { const routes = useRouter(); - - useEffect(() => { - if (!ACCESS_TOKEN) { - alert('로그인이 필요합니다.'); - routes.replace('/boards'); - } - }, []); - const [previewImage, setPreviewImage] = useState(''); const [formData, setFormData] = useState({ title: '', diff --git a/src/components/CommentContainer.tsx b/src/components/CommentContainer.tsx index a5a73f0b7..058e3731b 100644 --- a/src/components/CommentContainer.tsx +++ b/src/components/CommentContainer.tsx @@ -14,8 +14,10 @@ const CommentContainer = () => { const saveComment = async () => { try { - const result = await getComments(id as string, 5); - setComments(result); + if (typeof id === 'string') { + const result = await getComments(id as string, 5); + setComments(result); + } } catch (error) {} }; diff --git a/src/components/TotalPostsContainer.tsx b/src/components/TotalPostsContainer.tsx index 32599fe29..1124c4234 100644 --- a/src/components/TotalPostsContainer.tsx +++ b/src/components/TotalPostsContainer.tsx @@ -5,31 +5,13 @@ import { writingType } from '../api/apiType'; import Post from './Post'; import { AxiosError } from 'axios'; import style from '@/styles/Post.module.css'; +import useInfiniteScroll from '../hook/useInfiniteScroll'; + const TotalPostsContainer = () => { const router = useRouter(); const { orderBy, keyword } = router.query; const [posts, setPosts] = useState([]); - const target = useRef(null); - const [limit, setLimit] = useState(6); - - let preventFirst = 0; - - const callback = (entry: IntersectionObserverEntry[]) => { - if (entry[0].isIntersecting && preventFirst > 0) { - setLimit((prev) => prev + 6); - } - preventFirst++; - }; - - useEffect(() => { - const observer = new IntersectionObserver(callback, { threshold: 1 }); - if (target.current !== null) { - observer.observe(target.current); - } - return () => { - observer.disconnect(); - }; - }, []); + const { scrollRef, limit } = useInfiniteScroll(); const getPosts = async () => { if (keyword && orderBy) { @@ -76,7 +58,7 @@ const TotalPostsContainer = () => { createdAt={element.createdAt} /> ))} -
+
); }; diff --git a/src/hook/useInfiniteScroll.tsx b/src/hook/useInfiniteScroll.tsx new file mode 100644 index 000000000..283c46978 --- /dev/null +++ b/src/hook/useInfiniteScroll.tsx @@ -0,0 +1,28 @@ +import React, { useRef, useState, useEffect } from 'react'; + +const useInfiniteScroll = () => { + const scrollRef = useRef(null); + const [limit, setLimit] = useState(6); + let preventFirst = 0; + + const callback = (entry: IntersectionObserverEntry[]) => { + if (entry[0].isIntersecting && preventFirst > 0) { + setLimit((prev) => prev + 6); + } + preventFirst++; + }; + + useEffect(() => { + const observer = new IntersectionObserver(callback, { threshold: 1 }); + if (scrollRef.current !== null) { + observer.observe(scrollRef.current); + } + return () => { + observer.disconnect(); + }; + }, []); + return { scrollRef, limit }; +}; + +export default useInfiniteScroll; + diff --git a/src/util/loginCheck.ts b/src/util/loginCheck.ts deleted file mode 100644 index e33de75a7..000000000 --- a/src/util/loginCheck.ts +++ /dev/null @@ -1,44 +0,0 @@ -import style from '@/styles/signup.module.css'; -type I = HTMLInputElement; -type D = HTMLDivElement; - -export function emailError(inputBox: I, errorBox: D) { - let email = inputBox.value.trim(); - if (!isValidEmail(email)) { - showError('잘못된 이메일입니다', inputBox, errorBox); - } else { - clearError(inputBox, errorBox); - } -} -export function pwError(inputBox: I, errorBox: D) { - if (inputBox?.value?.length < 8) { - showError('비밀번호를 8자 이상 입력해주세요', inputBox, errorBox); - } else { - clearError(inputBox, errorBox); - } -} - -export function showError(message: string, inputBox: I, errorBox: D) { - inputBox.classList.add(`${style['error-border']}`); - errorBox.textContent = message; -} - -export function clearError(inputBox: I, errorBox: D) { - inputBox.classList.remove(`${style['error-border']}`); - errorBox.textContent = ''; -} - -export function isValidEmail(email: string) { - // 이메일 형식을 정규표현식을 사용하여 검사 - let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - return emailRegex.test(email); -} - -export function isPassword(inputBox: I, repeatInputBox: I, errorBox: D) { - if (inputBox.value !== repeatInputBox.value) { - showError('비밀번호가 일치하지 않습니다.', repeatInputBox, errorBox); - } else { - clearError(repeatInputBox, errorBox); - } -} -