로그인 관련 페이지 개발

This commit is contained in:
Kang Jung Kyo 2024-09-10 15:53:56 +09:00
parent 8f2b93863f
commit 7166749782
7 changed files with 511 additions and 23 deletions

View File

@ -0,0 +1,19 @@
'use client'
import { useI18n } from '@/locales/client'
export default function CompletePage() {
const t = useI18n()
return (
<>
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
<h1 className="text-center text-4xl font-bold mb-10">{t('join.complete.title')}</h1>
<div className="mt-10 mb-10 w-full text-center text-2xl">{t('join.complete.contents')}</div>
<div className="mt-10 w-full text-center">
{t('join.complete.email_comment')} :&nbsp;{t('join.complete.email')}
</div>
</div>
</>
)
}

View File

@ -0,0 +1,5 @@
import Join from '@/components/auth/Join'
export default function JoinPage() {
return <>{<Join />}</>
}

View File

@ -1,9 +1,16 @@
import Login from '@/components/auth/Login'
import { getCurrentLocale } from '@/locales/server'
export default function LoginPage() {
const currentLocale = getCurrentLocale()
const loginPageProps = {
currentLocale,
}
return (
<>
<Login />
<Login {...loginPageProps} />
</>
)
}

View File

@ -3,6 +3,7 @@
import { logout } from '@/lib/authActions'
import { useChangeLocale, useI18n } from '@/locales/client'
import { Button, Chip } from '@nextui-org/react'
import Link from 'next/link'
export default function MainPage(props) {
const { currentLocale, isLoggedIn } = props
@ -34,6 +35,13 @@ export default function MainPage(props) {
</Button>
</div>
)}
{!isLoggedIn && (
<div className="my-4">
<Link href={'/' + currentLocale + '/login'}>
<Button color="primary">로그인 페이지로 이동</Button>
</Link>
</div>
)}
<div className="font-test">font-test</div>
</>
)

View File

@ -0,0 +1,321 @@
'use client'
import { post } from '@/lib/Axios'
import { redirect } from 'next/navigation'
import { useI18n } from '@/locales/client'
export default function Join() {
const t = useI18n()
const joinProcess = async (formData) => {
const param = {
langCd: 'JA',
lastEditUser: formData.get('userId'),
storeQcastNm: formData.get('storeQcastNm'),
storeQcastNmKana: formData.get('storeQcastNmKana'),
postCd: formData.get('postCd'),
addr: formData.get('addr'),
telNo: formData.get('telNo'),
fax: formData.get('fax'),
payTermsCd: 'JB02',
kamId: 'E1101011',
qtCompNm: formData.get('qtCompNm'),
qtPostCd: formData.get('qtPostCd'),
qtAddr: formData.get('qtAddr'),
qtTelNo: formData.get('qtTelNo'),
qtFax: formData.get('qtFax'),
userInfo: {
userId: formData.get('userId'),
userNm: formData.get('userNm'),
userNmKana: formData.get('userNmKana'),
telNo: formData.get('userTelNo'),
fax: formData.get('userFax'),
email: formData.get('email'),
category: formData.get('category'),
},
}
await post({ url: '/api/login/v1.0/user/join', data: param }).then((res) => {
if (res) {
if (res.result.resultCode == 'S') {
redirect('/join/complete')
} else {
alert(res.result.resultMsg)
}
}
})
}
return (
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
<h1 className="text-center text-4xl font-bold">{t('join.title')}</h1>
<form action={joinProcess}>
<div className="mt-10">
<div>
{t('join.sub1.title')} (*{t('common.require')}) <span>{t('join.sub1.comment')}</span>
</div>
<table className="w-full">
<colgroup>
<col style={{ width: '20%' }} />
<col style={{ width: '80%' }} />
</colgroup>
<tbody>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub1.storeQcastNm')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="storeQcastNm"
name="storeQcastNm"
required
alt={t('join.sub1.storeQcastNm')}
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub1.storeQcastNm_placeholder')}
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub1.storeQcastNmKana')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="storeQcastNmKana"
name="storeQcastNmKana"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub1.storeQcastNmKana_placeholder')}
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>
{t('join.sub1.postCd')}/{t('join.sub1.addr')} *
</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="postCd"
name="postCd"
required
className="block border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub1.postCd_placeholder')}
></input>
<input
type="text"
id="addr"
name="addr"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub1.addr_placeholder')}
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub1.telNo')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="telNo"
name="telNo"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub1.telNo_placeholder')}
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub1.fax')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="fax"
name="fax"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub1.fax_placeholder')}
></input>
</td>
</tr>
</tbody>
</table>
<div className="mt-5">
{t('join.sub2.title')} (*{t('common.require')})
</div>
<table className="w-full">
<colgroup>
<col style={{ width: '20%' }} />
<col style={{ width: '80%' }} />
</colgroup>
<tbody>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub2.userNm')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="userNm"
name="userNm"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub2.userNmKana')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="userNmKana"
name="userNmKana"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub2.userId')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="userId"
name="userId"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub2.email')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="email"
id="email"
name="email"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
autoComplete="email"
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub2.telNo')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="userTelNo"
name="userTelNo"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub2.telNo_placeholder')}
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub2.fax')} *</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="userFax"
name="userFax"
required
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub1.fax_placeholder')}
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub2.category')}</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input id="category" name="category" className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"></input>
</td>
</tr>
</tbody>
</table>
<div className="mt-5">
{t('join.sub3.title')} (*{t('common.require')})
</div>
<table className="w-full">
<colgroup>
<col style={{ width: '20%' }} />
<col style={{ width: '80%' }} />
</colgroup>
<tbody>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub3.qtCompNm')}</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input type="text" id="qtCompNm" name="qtCompNm" className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>
{t('join.sub3.qtPostCd')}/{t('join.sub3.qtAddr')}
</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="qtPostCd"
name="qtPostCd"
className="block border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub3.qtPostCd_placeholder')}
></input>
<input
type="text"
id="qtAddr"
name="qtAddr"
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub3.qtAddr_placeholder')}
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub3.qtEmail')}</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="email"
id="qtEmail"
name="qtEmail"
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
autoComplete="email"
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub3.qtTelNo')}</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="qtTelNo"
name="qtTelNo"
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub3.qtTelNo_placeholder')}
></input>
</td>
</tr>
<tr>
<th style={{ border: '1px solid gray', padding: '5px' }}>{t('join.sub3.qtFax')}</th>
<td style={{ border: '1px solid gray', padding: '5px' }}>
<input
type="text"
id="qtFax"
name="qtFax"
className="block w-full border-0 py-1.5 ring-1 ring-inset ring-gray-300"
placeholder={t('join.sub3.qtFax_placeholder')}
></input>
</td>
</tr>
</tbody>
</table>
</div>
<div className="mt-10 mb-10">
<button
type="submit"
className="w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
{t('join.btn.approval_request')}
</button>
</div>
</form>
</div>
)
}

View File

@ -1,21 +1,127 @@
'use client'
import { login } from '@/lib/authActions'
import { post, patch } from '@/lib/Axios'
import { setSession } from '@/lib/authActions'
import { redirect } from 'next/navigation'
import { useI18n } from '@/locales/client'
export default function Login() {
return (
<div className="flex flex-col align-center h-screen">
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-sm">
<img alt="Your Company" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600" className="mx-auto h-10 w-auto" />
<h2 className="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">Sign in to your account</h2>
import { Button } from '@nextui-org/react'
import { useRecoilState } from 'recoil'
import { modalContent, modalState } from '@/store/modalAtom'
export default function Login(props) {
const { currentLocale } = props
const t = useI18n()
// login process
const loginProcess = async (formData) => {
const param = {
langCd: currentLocale,
lastEditUser: formData.get('id'),
loginId: formData.get('id'),
pwd: formData.get('password'),
}
await post({ url: '/api/login/v1.0/login', data: param }).then((res) => {
if (res) {
if (res.result.resultCode == 'S') {
// console.log('res.data', res.data)
//
// if (res.data.pwdInitYn != 'Y') {
// alert(' ')
// } else {
setSession(res.data)
redirect('/')
// }
} else {
alert(res.result.resultMsg)
}
}
})
}
//
const [open, setOpen] = useRecoilState(modalState)
const [contents, setContent] = useRecoilState(modalContent)
const initPasswordProcess = async (formData) => {
const param = {
langCd: currentLocale,
lastEditUser: formData.get('checkId'),
loginId: formData.get('checkId'),
email: formData.get('checkEmail'),
}
await patch({ url: '/api/login/v1.0/user/init-password', data: param }).then((res) => {
if (res) {
if (res.result.resultCode == 'S') {
alert(t('login.init_password.complete_message'))
redirect('/login')
} else {
alert(res.result.resultMsg)
}
}
})
}
const initPasswordContent = (
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
<form action={initPasswordProcess} className="space-y-6">
<h2 className="text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">{t('login.init_password.title')}</h2>
<h2 className="text-center text-1xl font-bold leading-9 tracking-tight text-gray-900">{t('login.init_password.sub_title')}</h2>
<div>
<label htmlFor="checkId" className="block text-sm font-medium leading-6 text-gray-900">
ID
</label>
<div className="mt-2">
<input
id="checkId"
name="checkId"
type="text"
required
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
<div>
<div className="flex items-center justify-between">
<label htmlFor="checkEmail" className="block text-sm font-medium leading-6 text-gray-900">
E-Mail
</label>
</div>
<div className="mt-2">
<input
id="checkEmail"
name="checkEmail"
type="email"
required
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
</div>
</div>
<p className="mt-5 text-center text-sm text-gray-500">
<Button type="submit" className="font-semibold leading-6 text-indigo-600 hover:text-indigo-500">
{t('login.init_password.btn')}
</Button>
</p>
</form>
</div>
)
return (
<div className="flex flex-col align-center">
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
<form action={login} method="POST" encType="application/json" className="space-y-6">
<h1 className="text-center text-4xl font-bold leading-9 tracking-tight text-gray-900">{t('site.name')}</h1>
<h2 className="mt-5 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">{t('site.sub_name')}</h2>
</div>
<div className="mt-5 sm:mx-auto sm:w-full sm:max-w-sm">
<form action={loginProcess} className="space-y-6">
<div>
<label htmlFor="userId" className="block text-sm font-medium leading-6 text-gray-900">
User ID
ID
</label>
<div className="mt-2">
<input
@ -34,11 +140,6 @@ export default function Login() {
<label htmlFor="password" className="block text-sm font-medium leading-6 text-gray-900">
Password
</label>
<div className="text-sm">
<a href="#" className="font-semibold text-indigo-600 hover:text-indigo-500">
Forgot password?
</a>
</div>
</div>
<div className="mt-2">
<input
@ -55,18 +156,23 @@ export default function Login() {
<div>
<button
type="submit"
className="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
className="mt-10 flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
Sign in
{t('login.login')}
</button>
</div>
</form>
<p className="mt-10 text-center text-sm text-gray-500">
Not a member?{' '}
<a href="#" className="font-semibold leading-6 text-indigo-600 hover:text-indigo-500">
Start a 14 day free trial
</a>
<p className="mt-5 text-center text-sm text-gray-500">
<Button
onClick={() => {
setContent(initPasswordContent)
setOpen(true)
}}
className="font-semibold leading-6 text-indigo-600 hover:text-indigo-500"
>
{t('login.init_password.btn')}
</Button>
</p>
</div>
</div>

View File

@ -27,6 +27,28 @@ export async function getSession() {
return session
}
export async function setSession(data) {
const session = await getSession()
session.userId = data.userId
session.name = data.name
session.saleStoreId = data.saleStoreId
session.mail = data.mail
session.tel = data.tel
session.storeId = data.storeId
session.userNm = data.userNm
session.userNmKana = data.userNmKana
session.category = data.category
session.telNo = data.telNo
session.fax = data.fax
session.email = data.email
session.pwdInitYn = data.pwdInitYn
session.isLoggedIn = true
// console.log('session:', session)
await session.save()
}
export async function login(formData) {
const session = await getSession()