Skip to content

Commit

Permalink
[feat/#58] 의견보내기 및 약관 관련 링크 연결
Browse files Browse the repository at this point in the history
  • Loading branch information
G-hoon committed Sep 26, 2024
1 parent c7e33ec commit a6c81da
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./auth"
export * from "./snapshot"
export * from "./group"
export * from "./report"
29 changes: 29 additions & 0 deletions src/api/report.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import axiosInstance from "./axiosInstance"

interface ReportResData {
data: {
id: number
uid: number
email: string
type: string
title: string
content: string
createdAt: string
modifiedAt: string
}
}

interface ReportParam {
email: string
title: string
content: string
}

export const requestSendReportAPI = async (param: ReportParam): Promise<ReportResData> => {
try {
const res = await axiosInstance.post(`/discussion`, { ...param, type: "QNA" })
return res.data
} catch (e) {
throw e
}
}
2 changes: 2 additions & 0 deletions src/components/Modal/Modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import CreateCrewModal from "./CreateCrewModal"
import GoodPostureGuidePopupModal from "./GoodPostureGuideModal"
import InviteCrewModal from "./InviteCrewModal"
import JoinCrewModal from "./JoinCrewModal"
import ReportModal from "./ReportModal"
import ToWithdrawModal from "./ToWithdrawModal"
import WithdrawCrewModal from "./WithdrawCrewModal"

Expand All @@ -15,6 +16,7 @@ export const modals = {
withdrawCrewModal: WithdrawCrewModal,
ToWithdrawModal: ToWithdrawModal,
postureGuideModal: GoodPostureGuidePopupModal,
reportModal: ReportModal,
}

const Modals = (): React.ReactNode => {
Expand Down
117 changes: 117 additions & 0 deletions src/components/Modal/ReportModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { requestSendReportAPI } from "@/api"
import { ModalProps } from "@/contexts/ModalsContext"
import ModalContainer from "@components/ModalContainer"
import { useState } from "react"

const ReportModal = (props: ModalProps): React.ReactElement => {
const { onClose, onSubmit } = props

const [title, setTitle] = useState<string>("")
const [email, setEmail] = useState<string>("")
const [isValidEmail, setIsValidEmail] = useState(false)
const [description, setDescription] = useState<string>("")

const onChangeName = (e: React.ChangeEvent<HTMLInputElement>): void => {
setTitle(e.target.value)
}

const onChangeDescription = (e: React.ChangeEvent<HTMLTextAreaElement>): void => {
if (e.target.value.length <= 500) setDescription(e.target.value)
}

const isValidForm = (): boolean => {
return Boolean(title.trim() && email.trim() && description.trim()) && isValidEmail
}

const handleSubmit = (): void => {
if (!isValidForm()) {
return
}

requestSendReportAPI({
title,
email,
content: description,
}).then(({ data }) => {
if (onSubmit && typeof onSubmit === "function") onSubmit()
})
}

const onChangeEmail = (event: any) => {
setEmail(event.target.value.trim())

const emailRegex = /^[\w-\.]+@([\w-]+)\.?([\w-]+)\.+[\w-]{2,4}$/
const validEmail = emailRegex.test(event.target.value)
setIsValidEmail(validEmail)
}

return (
<ModalContainer onClose={onClose}>
<div className="flex flex-col items-center">
{/* header */}
<div className="mb-10 flex items-center gap-4">
<div className="text-xl font-bold text-zinc-900">의견 보내기</div>
</div>

<div className="mb-6 flex w-full flex-col text-[15px]">
{/* crew owner */}
<div className="mb-4 flex flex-col gap-1">
<div className="font-semibold text-[#1A75FF]">제목</div>
<div className="mb-1 flex gap-4">
<input
type="text"
className="w-full rounded-xl border border-gray-200 border-gray-200 px-3 py-2 outline-none"
value={title}
onChange={onChangeName}
placeholder="의견 제목을 입력해주세요."
/>
</div>
</div>

<div className="mb-4 flex flex-col gap-1">
<div className="font-semibold text-[#1A75FF]">이메일</div>
<div className="mb-1 flex gap-4">
<input
type="email"
className="w-full rounded-xl border border-gray-200 border-gray-200 px-3 py-2 outline-none"
value={email}
onChange={onChangeEmail}
placeholder="이메일을 입력해주세요."
/>
</div>
{email && !isValidEmail && (
<div className="h-[24px] text-sm text-orange-400">올바른 이메일을 입력해주세요.</div>
)}
</div>

{/* crew description */}
<div className="flex flex-col gap-1">
<div className="text-[15px] font-semibold text-[#1A75FF]">상세 내용</div>
<div>
<textarea
className={`h-[140px] w-full resize-none rounded-xl border border-gray-200 p-3 outline-none`}
value={description}
onChange={onChangeDescription}
placeholder="상세 내용을 작성해주세요."
/>
<div className="text-end text-[13px] text-zinc-400">{`${description.length}/500`}</div>
</div>
</div>
</div>

{/* button */}
<button
className={`w-[256px] rounded-[40px] px-10 py-3 text-base font-semibold text-white ${
isValidForm() ? "bg-[#1A75FF]" : "bg-gray-200"
}`}
onClick={handleSubmit}
disabled={!isValidForm()}
>
의견 보내기
</button>
</div>
</ModalContainer>
)
}

export default ReportModal
23 changes: 21 additions & 2 deletions src/components/SideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import CrewIcon from "@assets/icons/side-nav-crew-icon.svg?react"
import MonitoringIcon from "@assets/icons/side-nav-monitor-icon.svg?react"
import { useMemo } from "react"
import { Link, useLocation, useNavigate } from "react-router-dom"
import { useModals } from "@/hooks/useModals"
import { modals } from "./Modal/Modals"

const navItems = [
{
Expand All @@ -31,6 +33,7 @@ export default function SideNav(): React.ReactElement {
const location = useLocation()
const logout = useAuthStore((state) => state.logout)
const navigate = useNavigate()
const { openModal } = useModals()

const logoutHandler = (): void => {
const clearUser = useAuthStore.persist.clearStorage
Expand All @@ -49,8 +52,24 @@ export default function SideNav(): React.ReactElement {

const footerLinks = useMemo(
() => [
{ label: "이용약관", link: "", onClick: () => {} },
{ label: "의견보내기", link: "", onClick: () => {} },
{
label: "이용약관",
link: "",
onClick: () => {
window.open("https://swjg3gi.notion.site/7c13aba015654e6f8e1acd300b440526?pvs=4", "_blank")
},
},
{
label: "의견보내기",
link: "",
onClick: () => {
openModal(modals.reportModal, {
onSubmit: () => {
// navigate(RoutePath.MYCREW)
},
})
},
},
{ label: "로그아웃", link: "", onClick: logoutHandler },
],
[logoutHandler]
Expand Down
8 changes: 6 additions & 2 deletions src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,12 @@ const HomePage: React.FC = () => {
<div className="flex items-center text-[#D9D9D9]">
<div className="mr-20 text-2xl font-bold">ALIGN LAB</div>
<div className="flex gap-20 text-sm">
<div>개인정보처리방침</div>
<div>이용약관</div>
<a href="https://swjg3gi.notion.site/89966f39e24a442a8eee5b1f91c4fde7" target="_blank">
<div>개인정보처리방침</div>
</a>
<a href="https://swjg3gi.notion.site/7c13aba015654e6f8e1acd300b440526?pvs=4" target="_blank">
<div>이용약관</div>
</a>
</div>
</div>
<div className="mt-10 text-xs font-normal text-[#9D9DA2]">Copyright all reserved @2024</div>
Expand Down

0 comments on commit a6c81da

Please sign in to comment.