[] 회원가입 페이지

1. 주소 (카카오 주소 검색) 팝업 연동 및 데이터 받아오기
2. 생일 Date Picker 띄우고 데이터 받아오기
3. 전화번호 양식 만들기
4. TopNav 의 버튼들 색상 변경
This commit is contained in:
김선규 2025-06-02 17:58:41 +09:00
parent c178a17c04
commit f3fee47c28
8 changed files with 239 additions and 63 deletions

View File

@ -5,71 +5,119 @@
<div class="layout-container flex h-full grow flex-col">
<div class="flex flex-1 justify-center py-5 md:px-40 md:justify-center">
<div class="layout-content-container flex flex-col w-[512px] max-w-[480px] py-5 flex-1">
<h2 class="text-[#121416] tracking-light text-[28px] font-bold leading-tight px-4 text-center pb-3 pt-5">
<h2 class="text-text-title tracking-light text-[28px] font-bold leading-tight px-4 text-center pb-3 pt-5">
회원가입</h2>
<p class="text-red-600 font-normal text-xs text-right px-4">* 는 필수 사항입니다.</p>
<div class="flex max-w-[480px] flex-wrap items-end gap-4 px-4 py-3">
<label class="flex flex-col min-w-40 flex-1">
<p class="text-[#121416] text-base font-medium leading-normal pb-2">이름
<p class="text-text-title text-base font-medium leading-normal pb-2">이름
<span class="text-red-600">*</span>
</p>
<input
pattern="\d{16}"
maxlength="16"
placeholder="실명을 입력해주세요. 최대 16글자"
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-[#121416] focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-14 placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
value="@name"
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-text-title focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-14 placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
@bind-value="@name"
/>
</label>
</div>
<div class="flex max-w-[480px] flex-wrap items-end gap-4 px-4 py-3">
<label class="flex flex-col min-w-40 flex-1">
<p class="text-[#121416] text-base font-medium leading-normal pb-2">생일</p>
<p class="text-text-title text-base font-medium leading-normal pb-2">생일</p>
<input
type="date"
@ref="dateInputRef"
placeholder="YYYYMMDD"
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-[#121416] focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-14 placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-text-title focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-14 placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
@bind-value="birth"
@bind-value:event="oninput"
@onclick="OpenDatePicker"
readonly
/>
</label>
</div>
<p class="px-4 py-2 text-sm text-gray-500">선택한 생일: @birth.ToString("yyyy-MM-dd")</p>
<div class="flex max-w-[480px] flex-wrap items-end gap-4 px-4 py-3">
<label class="flex flex-col min-w-40 flex-1">
<p class="text-[#121416] text-base font-medium leading-normal pb-2">Email</p>
<p class="text-text-title text-base font-medium leading-normal pb-2">E-Mail
<span class="text-red-600">*</span>
</p>
<input
placeholder="Enter your email"
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-[#121416] focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-14 placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
value=""
/>
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-text-title focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-14 placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
@bind-value="email"/>
</label>
</div>
<div class="flex max-w-[480px] flex-wrap items-end gap-4 px-4 py-3">
<label class="flex flex-col min-w-40 flex-1">
<p class="text-[#121416] text-base font-medium leading-normal pb-2">Phone Number</p>
<p class="text-text-title text-base font-medium leading-normal pb-2">전화번호</p>
@* <input *@
@* placeholder="(XXX) XXX-XXXX" *@
@* class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-text-title focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-14 placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal" *@
@* @bind-value="phone" *@
@* /> *@
<div class="flex w-full items-center justify-center gap-2 px-4">
<input
placeholder="(XXX) XXX-XXXX"
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-[#121416] focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-14 placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
value=""
maxlength="3"
pattern="\d{3}"
placeholder="010"
class="form-input w-20 h-12 text-center border border-[#dde0e3] rounded-md"
@bind-value="phonePart1"
inputmode="numeric"
autocomplete="off"
/>
<span class="self-center">-</span>
<input
maxlength="4"
pattern="\d{4}"
placeholder="1234"
class="form-input w-20 h-12 text-center border border-[#dde0e3] rounded-md"
@bind-value="phonePart2"
inputmode="numeric"
autocomplete="off"
/>
<span class="self-center">-</span>
<input
maxlength="4"
pattern="\d{4}"
placeholder="5678"
class="form-input w-20 h-12 text-center border border-[#dde0e3] rounded-md"
@bind-value="phonePart3"
inputmode="numeric"
autocomplete="off"
/>
<button class="ml-4 h-12 px-6 bg-blue-500 text-white rounded-md font-bold" @onclick="SubmitPhone"
style="min-width: 80px;">
확인
</button>
</div>
</label>
</div>
<div class="flex max-w-[480px] flex-wrap items-end gap-4 px-4 py-3">
<label class="flex flex-col min-w-40 flex-1">
<p class="text-[#121416] text-base font-medium leading-normal pb-2">Address</p>
<input
placeholder="Enter your address"
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-[#121416] focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-14 placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
value=""
/>
<div class="flex flex-col max-w-[480px] flex-wrap items-end gap-4 px-4 py-3">
<label class="flex text-left w-full text-text-title text-base font-medium leading-normal">주소
</label>
<input
placeholder="눌러서 주소를 선택하세요."
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-text-title focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-12 placeholder:text-[#6a7581] p-[12px] text-base font-normal leading-normal"
@onclick="OnClickAddress"
@bind-value="address"
readonly
/>
@if (address != "")
{
<input
placeholder="상세주소를 입력하세요."
class="form-input flex w-full min-w-0 flex-1 resize-none overflow-hidden rounded-xl text-text-title focus:outline-0 focus:ring-0 border border-[#dde0e3] bg-white focus:border-[#dde0e3] h-12 placeholder:text-[#6a7581] p-[12px] text-base font-normal leading-normal"
@bind-value="detailAddress"
/>
}
</div>
<div class="flex px-4 py-3">
<button
class="flex min-w-[84px] max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-xl h-10 px-4 flex-1 bg-[#3f7fbf] text-white text-sm font-bold leading-normal tracking-[0.015em]"
@onclick="ConfirmData"
class="flex min-w-[84px] max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-xl h-10 px-4 flex-1 bg-second-normal hover:bg-second-dark text-white text-sm font-bold leading-normal tracking-[0.015em]"
>
<span class="truncate">Register</span>
</button>

View File

@ -1,27 +1,79 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System.Text.Json;
namespace Front.Program.Views.Project;
public partial class Register : ComponentBase
{
[Inject] IJSRuntime JS { get; set; }
private string name;
private DateTime birth = DateTime.Now;
private string email;
private string phone;
private string address;
[Inject] private NavigationManager NavigationManager { get; set; } = default!;
private ElementReference dateInputRef;
private string name = "";
private DateTime? birth;
private string email = "";
private string phone = "";
private string address = "";
private string detailAddress = "";
// private async Task ClickedCalendar()
// {
// // var input = e.Value?.ToString() ?? string.Empty;
// // if (input.All(c => c >= '0' && c <= '9') && input.Length <= 8)
// // {
// // birth = new string(input.Where(char.IsDigit).Take(8).ToArray());
// // }
// await JS.InvokeVoidAsync("openDatePickerOnFocus", dateInput);
//
// Console.WriteLine($"Birth: {birth}");
// }
private string phonePart1 = "";
private string phonePart2 = "";
private string phonePart3 = "";
private void SubmitPhone()
{
if (phonePart1.Length == 3 && phonePart2.Length == 4 && phonePart3.Length == 4)
{
var fullPhone = $"{phonePart1}-{phonePart2}-{phonePart3}";
Console.WriteLine($"입력된 전화번호: {fullPhone}");
}
else
{
Console.WriteLine("전화번호를 올바르게 입력해주세요.");
}
}
private void ConfirmData()
{
if (name == "" || phone == "" || address == "" || detailAddress == "")
{
}
Console.WriteLine($"{name} - {birth.ToString()} - {email} - {phone} - {address}");
}
private async Task OpenDatePicker()
{
if (birth==null) birth = DateTime.Now;
await JS.InvokeVoidAsync("openDatePicker", dateInputRef);
}
private void OnBirthChanged(ChangeEventArgs e)
{
Console.WriteLine($"선택된 생일: {birth}");
}
private DotNetObjectReference<Register> objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
protected async Task OnClickAddress()
{
await JS.InvokeVoidAsync("openKakaoPostcodePopup", objRef);
}
[JSInvokable]
public void SetAddress(string roadAddress, string jibunAddress, string zonecode)
{
address = roadAddress;
Console.WriteLine($"SetAddress 호출됨: {roadAddress}, {jibunAddress}, {zonecode}");
StateHasChanged();
}
}

View File

@ -7,18 +7,17 @@
<div class="hidden md:flex flex-1 justify-end gap-8">
<div class="flex flex-1 justify-end gap-8">
<div class="flex items-center gap-9">
<a class="text-text-title font-medium leading-normal hover:text-blue-800" href="/about" @onclick="() => isOpen = !isOpen">About</a>
<a class="text-text-title font-medium leading-normal hover:text-blue-800" href="/join" @onclick="() => isOpen = !isOpen">Join</a>
<a class="text-text-title font-medium leading-normal hover:text-blue-800" href="/new" @onclick="() => isOpen = !isOpen">What's New</a>
<a class="text-text-title font-medium leading-normal hover:text-blue-600" href="/about" @onclick="() => isOpen = !isOpen">About</a>
<a class="text-text-title font-medium leading-normal hover:text-blue-600" href="/join" @onclick="() => isOpen = !isOpen">Join</a>
<a class="text-text-title font-medium leading-normal hover:text-blue-600" href="/new" @onclick="() => isOpen = !isOpen">What's New</a>
</div>
<button class="flex min-w-[84px] max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-lg h-10 px-4 bg-blue-500 hover:bg-blue-800 text-white text-sm font-bold leading-normal tracking-[0.015em] mr-4"
<button class="flex min-w-[84px] max-w-[480px] cursor-pointer items-center justify-center overflow-hidden rounded-lg h-10 px-4 bg-second-normal hover:bg-second-dark text-white text-sm font-bold leading-normal tracking-[0.015em] mr-4"
@onclick="OnClickLogin">
<span class="truncate">Get Started</span>
<span class="truncate">시작하기</span>
</button>
</div>
</div>
<button class="md:hidden mr-4" @onclick="OnClickMenuDown">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
@ -29,13 +28,13 @@
@if (isOpen)
{
<div class="md:hidden absolute top-16 left-0 w-full bg-white shadow z-50 transition-all duration-300">
<div class="flex flex-col items-start gap-4 p-4">
<a class="block w-full gap-y-2 text-text-title font-medium leading-normal hover:text-blue-800" href="/about" @onclick="() => isOpen = !isOpen">About</a>
<a class="block w-full gap-y-2 text-text-title font-medium leading-normal hover:text-blue-800" href="/join" @onclick="() => isOpen = !isOpen">Join</a>
<a class="block w-full gap-y-2 text-text-title font-medium leading-normal hover:text-blue-800" href="/new" @onclick="() => isOpen = !isOpen">What's New</a>
<button class="flex w-full cursor-pointer items-center justify-center rounded-lg h-10 px-4 bg-blue-500 hover:bg-blue-800 text-white text-sm font-bold leading-normal tracking-[0.015em]"
<div class="flex flex-col items-start gap-4 p-4 text-center">
<a class="block w-full gap-y-2 text-text-title font-medium leading-normal hover:text-blue-600" href="/about" @onclick="() => isOpen = !isOpen">About</a>
<a class="block w-full gap-y-2 text-text-title font-medium leading-normal hover:text-blue-600" href="/join" @onclick="() => isOpen = !isOpen">Join</a>
<a class="block w-full gap-y-2 text-text-title font-medium leading-normal hover:text-blue-600" href="/new" @onclick="() => isOpen = !isOpen">What's New</a>
<button class="flex w-full cursor-pointer items-center justify-center rounded-lg h-10 px-4 bg-second-normal hover:bg-second-dark text-white text-sm font-bold leading-normal tracking-[0.015em]"
@onclick="OnClickLogin">
<span class="truncate">Get Started</span>
<span class="truncate">시작하기</span>
</button>
</div>
</div>

File diff suppressed because one or more lines are too long

View File

@ -32,11 +32,15 @@
<button class="ml-4 text-red-600 font-bold dismiss"></button>
</div>
<!-- Blazor WASM 로딩 스크립트 -->
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script src="scripts/scroll.js"></script>
<script src="scripts/apiSender.js"></script>
<script src="scripts/jsCommonFunc.js"></script>
<script src="scripts/kakao-postcode.js"></script>
<!-- Blazor WASM 로딩 스크립트 -->
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script>
const MIN_LOADING_MS = 2700;
const loadingStart = performance.now();
@ -71,5 +75,9 @@
document.cookie = name + '=; Max-Age=-99999999;';
};
</script>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<title>주소검색</title>
<script src="https://spi.maps.daum.net/imap/map_js_init/postcode.v2.js"></script>
<script>
window.onload = function() {
var layer = document.getElementById('layer');
new daum.Postcode({
oncomplete: function(data) {
var jibunAddress = data.jibunAddress || data.autoJibunAddress || "";
var postData = {
roadAddress: data.roadAddress,
jibunAddress: jibunAddress,
zonecode: data.zonecode,
};
window.opener.postMessage({
roadAddress: data.roadAddress,
jibunAddress: data.jibunAddress,
zonecode: data.zonecode
}, window.location.origin);
window.close();
},
width: "100%",
height: "100%"
}).embed(layer);
layer.style.display = "block";
};
</script>
<style>
html, body { margin:0; padding:0; width:100vw; height:100vh; background:#fff; }
#layer { width:100vw; height:100vh; }
</style>
</head>
<body>
<div id="layer"></div>
</body>
</html>

View File

@ -1,6 +1,8 @@
window.openDatePickerOnNumber = function (element, event) {
// 숫자 키(0~9) 입력 시 date picker 강제 오픈
if (event.keyCode >= 48 && event.keyCode <= 57) {
element.showPicker && element.showPicker();
window.openDatePicker = function (element) {
if (element) {
const wasReadOnly = element.readOnly;
if (wasReadOnly) element.readOnly = false;
element.showPicker();
if (wasReadOnly) setTimeout(() => element.readOnly = true, 0);
}
};

View File

@ -0,0 +1,28 @@
window.addEventListener("message", function (event) {
if (event.origin !== window.location.origin) return;
if (event.data && event.data.roadAddress) {
if (window.kakaoPostcodeDotNetRef) {
window.kakaoPostcodeDotNetRef.invokeMethodAsync(
"SetAddress",
event.data.roadAddress,
event.data.jibunAddress,
event.data.zonecode
);
}
}
});
window.getKakaoPostcodeResult = function () {
return window.kakaoPostcodeResult;
};
window.openKakaoPostcodePopup = function (dotNetObjRef) {
window.kakaoPostcodeResult = null;
window.kakaoPostcodeDotNetRef = dotNetObjRef;
window.open(
"/kakao-postcode.html",
"kakaoPostcodePopup",
"width=500,height=600,scrollbars=no,resizable=no"
);
};