-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
新規登録関連画面の実装 #73
新規登録関連画面の実装 #73
Changes from 4 commits
60252d0
729fde1
aa8d3a7
824fc4f
c445172
bde51ce
85e673c
eb9b9ed
bc2c2b4
bd036e5
eec2fcd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
VITE_API_BASE_URL = http://localhost:4010 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,9 @@ | ||
/// <reference types="vite/client" /> | ||
|
||
interface ImportMetaEnv { | ||
readonly VITE_API_BASE_URL: string; | ||
} | ||
|
||
interface ImportMeta { | ||
readonly env: ImportMetaEnv; | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<script setup lang="ts"> | ||
import { useRouter } from 'vue-router' | ||
|
||
const { | ||
disabled = false, | ||
app, | ||
mode | ||
} = defineProps<{ | ||
disabled?: boolean | ||
app: string | ||
mode: 'signup' | 'login' | ||
}>() | ||
|
||
const router = useRouter() | ||
|
||
async function onOAuthClick() { | ||
try { | ||
if (mode === 'signup') { | ||
if (app === 'Github') { | ||
const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/github-oauth2/params`) | ||
if (response.status === 200) { | ||
const responseJson = await response.json() | ||
alert(responseJson.url) | ||
router.push(responseJson.url) | ||
} else if (response.status === 500) { | ||
const responseJson = await response.json() | ||
alert('Internal Server Error: ' + responseJson.message) | ||
} | ||
else { | ||
alert(response.status) | ||
} | ||
} | ||
if (app === 'Google') { | ||
const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/google-oauth2/params`) | ||
if (response.status === 200) { | ||
const responseJson = await response.json() | ||
router.push(responseJson.url) | ||
} else if (response.status === 500) { | ||
const responseJson = await response.json() | ||
alert('Internal Server Error: ' + responseJson.message) | ||
} | ||
else { | ||
alert(response.status) | ||
} | ||
} | ||
if (app === 'traQ') { | ||
const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/traq-oauth2/params`) | ||
if (response.status === 200) { | ||
const responseJson = await response.json() | ||
router.push(responseJson.url) | ||
} else if (response.status === 500) { | ||
const responseJson = await response.json() | ||
alert('Internal Server Error: ' + responseJson.message) | ||
} | ||
else { | ||
alert(response.status) | ||
} | ||
} | ||
} | ||
} catch (error) { | ||
console.error('OAuth Error:', error) | ||
alert('OAuth Error:' + error) | ||
} | ||
} | ||
</script> | ||
|
||
<template> | ||
<button | ||
:disabled="disabled" | ||
class="fontstyle-ui-control-strong inline-block space-x-2.5 rounded-lg border border-border-secondary px-3 py-2 text-text-primary enabled:hover:bg-background-secondary disabled:opacity-50" | ||
@click="onOAuthClick" | ||
> | ||
<span v-if="app === 'Github'" class="inline-block align-middle" | ||
><img src="" class="size-5" | ||
/></span> | ||
<span v-if="app === 'Google'" class="inline-block align-middle" | ||
><img src="" class="size-5" | ||
/></span> | ||
<span v-if="app === 'traQ'" class="inline-block align-middle" | ||
><img src="" class="size-5" | ||
/></span> | ||
<span class="inline-block align-middle">{{ app }} で新規登録</span> | ||
</button> | ||
</template> | ||
|
||
<style scoped></style> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,128 @@ | ||
<script setup lang="ts"></script> | ||
<script setup lang="ts"> | ||
import { ref, onMounted } from 'vue' | ||
import { useRouter } from 'vue-router' | ||
import { jwtDecode } from 'jwt-decode' | ||
import PasswordTextbox from '@/components/Controls/Textbox/PasswordTextbox.vue' | ||
import PlainTextbox from '@/components/Controls/Textbox/PlainTextbox.vue' | ||
import PrimaryButton from '@/components/Controls/PrimaryButton.vue' | ||
|
||
const username = ref('') | ||
const emailAddress = ref('') | ||
const password = ref('') | ||
const confirmPassword = ref('') | ||
const confirmPasswordErrorMessage = ref('') | ||
|
||
onMounted(() => { | ||
try { | ||
const token = new URLSearchParams(window.location.search).get('token') | ||
if (token) { | ||
const decodedToken = jwtDecode<{ email: string }>(token) | ||
emailAddress.value = decodedToken.email | ||
} | ||
} catch (error) { | ||
console.error('Signup Register Error:', error) | ||
alert('Signup Register Error:' + error) | ||
} | ||
}) | ||
|
||
const router = useRouter() | ||
|
||
async function onSignupRegister() { | ||
try { | ||
if (password.value !== confirmPassword.value) { | ||
confirmPasswordErrorMessage.value = 'パスワードが一致しません' | ||
return | ||
} | ||
const token = new URLSearchParams(window.location.search).get('token') | ||
const response = await fetch(`${import.meta.env.VITE_API_BASE_URL}/signup`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify({ userName: username.value, password: password.value, token: token }) | ||
}) | ||
if (response.status === 201) { | ||
router.push('/login') | ||
} else if (response.status === 400) { | ||
alert('不正なリクエストです') | ||
} else if (response.status === 401) { | ||
alert('Unauthorized') | ||
} else { | ||
alert(response.status) | ||
} | ||
} catch (error) { | ||
console.error('Signup Register Error:', error) | ||
alert('Signup Register Error:' + error) | ||
} | ||
} | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<h1>Signup Register</h1> | ||
<div | ||
class="flex items-center justify-center bg-background-tertiary px-8 py-6" | ||
style="height: calc(100vh - 56px)" | ||
> | ||
<div class="max-w-3xl space-y-5 rounded-2xl bg-white px-14 py-10"> | ||
<div class="fontstyle-ui-title text-left">新規登録</div> | ||
<div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. このようなformのタイトル?を表すようなものは全てlabel要素で書き換え,それぞれのformと |
||
<span class="fontstyle-ui-body text-status-error">*</span> | ||
<span class="fontstyle-ui-body text-text-primary">がついた項目は必須です。</span> | ||
</div> | ||
<div class="space-y-5 p-2.5"> | ||
<div class="flex gap-6"> | ||
<div class="w-50 text-right"> | ||
<span class="fontstyle-ui-body-strong text-text-primary">ユーザー名</span> | ||
<span class="fontstyle-ui-body-strong text-status-error">*</span> | ||
</div> | ||
<div class="flex-1"> | ||
<PlainTextbox v-model="username" /> | ||
<div class="fontstyle-ui-caption-strong pt-1 text-text-secondary"> | ||
文字数は〇以上〇以下で、半角英数字とアンダースコアのみが使用できます。 | ||
</div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pタグとかで適当に囲ってあげた方が良いと思います。それから,僕の画面だとこの文字列が改行されてしまっているので,常に一行に収まることを保証したいです。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 正規表現を使ったvalidateを実装してもらえると助かります!字数制限は仮に5以上10以下などにしてください。 |
||
</div> | ||
</div> | ||
<div class="flex gap-6"> | ||
<div class="w-50 text-right"> | ||
<span class="fontstyle-ui-body-strong text-text-primary">メールアドレス</span> | ||
</div> | ||
<div class="flex-1"> | ||
<span class="fontstyle-ui-body w-full px-1 text-text-primary"> | ||
{{ emailAddress }} | ||
</span> | ||
</div> | ||
</div> | ||
<div class="flex gap-6"> | ||
<div class="w-50 text-right"> | ||
<span class="fontstyle-ui-body-strong text-text-primary">パスワード</span> | ||
<span class="fontstyle-ui-body-strong text-status-error">*</span> | ||
</div> | ||
<div class="flex-1"> | ||
<PasswordTextbox v-model="password" /> | ||
<div class="fontstyle-ui-caption-strong pt-1 text-text-secondary"> | ||
文字数は〇以上〇以下で、半角英数字と記号が使用できます。 | ||
</div> | ||
<div class="fontstyle-ui-caption-strong pt-1 text-text-secondary"> | ||
英字、数字、記号がそれぞれ1文字以上含まれている必要があります。 | ||
</div> | ||
</div> | ||
</div> | ||
<div class="flex gap-6"> | ||
<div class="w-50 text-right"> | ||
<span class="fontstyle-ui-body-strong text-text-primary">パスワード(確認)</span> | ||
<span class="fontstyle-ui-body-strong text-status-error">*</span> | ||
</div> | ||
<div class="flex-1"> | ||
<PasswordTextbox | ||
v-model="confirmPassword" | ||
:error-message="confirmPasswordErrorMessage" | ||
/> | ||
</div> | ||
</div> | ||
<div class="flex justify-center"> | ||
<PrimaryButton text="次へ" @click="onSignupRegister" /> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
以下の各種ラベルとフォームもgridで整列すると良さそうです。