[✨] 로그인 및 화면 구조 변경
1. 회원가입 후 자동 로그인 2. 로그인 후 페이지 처리 3. 로딩 인디케이터 동작 구조 변경
This commit is contained in:
parent
1649818434
commit
3ffec93958
|
@ -5,9 +5,10 @@
|
||||||
|
|
||||||
<!-- Top 영역 -->
|
<!-- Top 영역 -->
|
||||||
@* <TopBanner /> *@
|
@* <TopBanner /> *@
|
||||||
@if (!isHideTop)
|
|
||||||
|
@if (!isHidePrjTop)
|
||||||
{
|
{
|
||||||
<TopNav />
|
<TopProjectNav />
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- 본문 영역 -->
|
<!-- 본문 영역 -->
|
||||||
|
|
|
@ -13,11 +13,11 @@ public partial class MainLayout : LayoutComponentBase, IDisposable
|
||||||
[Inject]
|
[Inject]
|
||||||
LoadingService LoadingService { get; set; } = default!;
|
LoadingService LoadingService { get; set; } = default!;
|
||||||
|
|
||||||
// protected bool isHideTop => Navigation.Uri.Contains("/auth");
|
// 경로의 시작 부분
|
||||||
protected bool isHideTop => Navigation.ToBaseRelativePath(Navigation.Uri).Equals("auth", StringComparison.OrdinalIgnoreCase);
|
// protected bool isHidePrjTop => Navigation.ToBaseRelativePath(Navigation.Uri).StartsWith("auth", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public static bool IsLoading { get; set; }
|
// 경로의 끝 부분
|
||||||
public static IndicateType CurrentType { get; set; } = IndicateType.Page;
|
protected bool isHidePrjTop => Navigation.ToBaseRelativePath(Navigation.Uri).EndsWith("auth", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
|
@ -35,15 +35,4 @@ public partial class MainLayout : LayoutComponentBase, IDisposable
|
||||||
LoadingService.OnChange -= StateHasChanged;
|
LoadingService.OnChange -= StateHasChanged;
|
||||||
Navigation.LocationChanged -= HandleLocationChanged;
|
Navigation.LocationChanged -= HandleLocationChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowLoading(IndicateType type = IndicateType.Page)
|
|
||||||
{
|
|
||||||
IsLoading = true;
|
|
||||||
CurrentType = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void HideLoading()
|
|
||||||
{
|
|
||||||
IsLoading = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,12 +1,26 @@
|
||||||
@page "/auth"
|
@page "/auth"
|
||||||
|
@page "/academy/auth"
|
||||||
|
|
||||||
<div class="flex flex-col items-center justify-center min-h-screen bg-gray-100">
|
<div class="flex flex-col items-center justify-center min-h-screen bg-gray-100">
|
||||||
<h1 class="text-2xl font-bold mb-4">로그인</h1>
|
<h1 class="text-2xl font-bold mb-4">로그인</h1>
|
||||||
<div class="w-full max-w-xs">
|
<div class="w-full max-w-xs">
|
||||||
<button type="button" class="w-full mb-4 p-2 rounded focus:outline-none" @onclick="KakaoLogin">
|
@if (NavigationManager.Uri.Contains("/academy/auth"))
|
||||||
<img src="//k.kakaocdn.net/14/dn/btqCn0WEmI3/nijroPfbpCa4at5EIsjyf0/o.jpg"
|
{
|
||||||
alt="카카오 로그인"
|
<button type="button" class="w-full mb-4 p-2 rounded focus:outline-none"
|
||||||
class="rounded w-full transition duration-150 hover:brightness-90" />
|
@onclick="@(() => KakaoLogin("/academy"))" >
|
||||||
</button>
|
<img src="//k.kakaocdn.net/14/dn/btqCn0WEmI3/nijroPfbpCa4at5EIsjyf0/o.jpg"
|
||||||
|
alt="카카오 로그인"
|
||||||
|
class="rounded w-full transition duration-150 hover:brightness-90" />
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<button type="button" class="w-full mb-4 p-2 rounded focus:outline-none"
|
||||||
|
@onclick="@(() => KakaoLogin("/about"))" >
|
||||||
|
<img src="//k.kakaocdn.net/14/dn/btqCn0WEmI3/nijroPfbpCa4at5EIsjyf0/o.jpg"
|
||||||
|
alt="카카오 로그인"
|
||||||
|
class="rounded w-full transition duration-150 hover:brightness-90" />
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -6,24 +6,52 @@ using Microsoft.JSInterop;
|
||||||
|
|
||||||
namespace Front.Program.Views.Project;
|
namespace Front.Program.Views.Project;
|
||||||
|
|
||||||
public partial class Auth : ComponentBase
|
public partial class Auth : ComponentBase, IDisposable
|
||||||
{
|
{
|
||||||
[Inject] NavigationManager NavigationManager { get; set; } = default!;
|
[Inject] NavigationManager NavigationManager { get; set; } = default!;
|
||||||
[Inject] LoadingService LoadingService { get; set; } = default!;
|
[Inject] LoadingService LoadingService { get; set; } = default!;
|
||||||
// [Inject] IJSRuntime JS { get; set; } = default!;
|
|
||||||
// [Inject] CookieService Cookie { get; set; } = default!;
|
|
||||||
[Inject] HttpClient Http { get; set; } = default!;
|
[Inject] HttpClient Http { get; set; } = default!;
|
||||||
|
[Inject] IJSRuntime JS { get; set; } = default!;
|
||||||
|
|
||||||
public async Task KakaoLogin()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
LoadingService.ShowLoading();
|
// LocationChanged 이벤트 구독
|
||||||
var url = "/api/v1/out/user/kakao/auth";
|
NavigationManager.LocationChanged += HandleLocationChanged;
|
||||||
var response = await Http.GetFromJsonAsync<JsonElement>(url);
|
}
|
||||||
var kakaoUrl = response.GetProperty("url").GetString();
|
|
||||||
Console.WriteLine(kakaoUrl);
|
private void HandleLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)
|
||||||
if (!string.IsNullOrEmpty(kakaoUrl))
|
{
|
||||||
|
// 페이지 이동이 발생했을 때 로딩 상태 해제
|
||||||
|
Console.WriteLine($"페이지 이동 감지: {NavigationManager.Uri}");
|
||||||
|
LoadingService.HideLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// 이벤트 구독 해제
|
||||||
|
NavigationManager.LocationChanged -= HandleLocationChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task KakaoLogin(string? path = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(kakaoUrl, true);
|
LoadingService.ShowLoading();
|
||||||
|
|
||||||
|
var url = $"/api/v1/out/user/kakao/auth?redirectPath={Uri.EscapeDataString(path ?? "/about")}";
|
||||||
|
var response = await Http.GetFromJsonAsync<JsonElement>(url);
|
||||||
|
var kakaoUrl = response.GetProperty("url").GetString();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(kakaoUrl))
|
||||||
|
{
|
||||||
|
// JavaScript를 통해 페이지 이동
|
||||||
|
await JS.InvokeVoidAsync("eval", $"window.location.replace('{kakaoUrl}')");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"카카오 로그인 오류: {ex.Message}");
|
||||||
|
LoadingService.HideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@
|
||||||
<input
|
<input
|
||||||
pattern="\d{16}"
|
pattern="\d{16}"
|
||||||
maxlength="16"
|
maxlength="16"
|
||||||
placeholder="실명을 입력해주세요. 최대 16글자"
|
placeholder="실명을 입력해주세요. (최대 16글자)"
|
||||||
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"
|
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"
|
@bind-value="@name"
|
||||||
/>
|
/>
|
||||||
|
@ -31,15 +31,41 @@
|
||||||
<div class="flex w-full flex-wrap items-end gap-4 px-4 py-3">
|
<div class="flex w-full flex-wrap items-end gap-4 px-4 py-3">
|
||||||
<label class="flex flex-col w-full">
|
<label class="flex flex-col w-full">
|
||||||
<p class="text-text-title text-base font-medium leading-normal pb-2">생일</p>
|
<p class="text-text-title text-base font-medium leading-normal pb-2">생일</p>
|
||||||
<input
|
<div class="flex w-full max-w-[480px] items-center gap-2">
|
||||||
type="date"
|
<input
|
||||||
@ref="dateInputRef"
|
maxlength="4"
|
||||||
placeholder="YYYYMMDD"
|
pattern="\d{4}"
|
||||||
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"
|
placeholder="YYYY"
|
||||||
@bind-value="birth"
|
class="form-input flex-1 min-w-0 h-12 text-center rounded-xl border border-[#dde0e3] bg-white focus:border-[#dde0e3] placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
|
||||||
@onclick="OpenDatePicker"
|
@bind-value="birthYear"
|
||||||
readonly
|
inputmode="numeric"
|
||||||
/>
|
autocomplete="off"
|
||||||
|
oninput="this.value = this.value.replace(/[^0-9]/g, '')"
|
||||||
|
/>
|
||||||
|
<span class="self-center">년</span>
|
||||||
|
<input
|
||||||
|
maxlength="2"
|
||||||
|
pattern="\d{2}"
|
||||||
|
placeholder="MM"
|
||||||
|
class="form-input flex-1 min-w-0 h-12 text-center rounded-xl border border-[#dde0e3] bg-white focus:border-[#dde0e3] placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
|
||||||
|
@bind-value="birthMonth"
|
||||||
|
inputmode="numeric"
|
||||||
|
autocomplete="off"
|
||||||
|
oninput="this.value = this.value.replace(/[^0-9]/g, '')"
|
||||||
|
/>
|
||||||
|
<span class="self-center">월</span>
|
||||||
|
<input
|
||||||
|
maxlength="2"
|
||||||
|
pattern="\d{2}"
|
||||||
|
placeholder="DD"
|
||||||
|
class="form-input flex-1 min-w-0 h-12 text-center rounded-xl border border-[#dde0e3] bg-white focus:border-[#dde0e3] placeholder:text-[#6a7581] p-[15px] text-base font-normal leading-normal"
|
||||||
|
@bind-value="birthDay"
|
||||||
|
inputmode="numeric"
|
||||||
|
autocomplete="off"
|
||||||
|
oninput="this.value = this.value.replace(/[^0-9]/g, '')"
|
||||||
|
/>
|
||||||
|
<span class="self-center">일</span>
|
||||||
|
</div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -49,7 +75,7 @@
|
||||||
<span class="text-red-600">*</span>
|
<span class="text-red-600">*</span>
|
||||||
</p>
|
</p>
|
||||||
<input
|
<input
|
||||||
placeholder="Enter your email"
|
placeholder="E-mail을 입력해주세요."
|
||||||
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"
|
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"/>
|
@bind-value="email"/>
|
||||||
</label>
|
</label>
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Net.Http.Json;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using Front.Program.Layout;
|
using Front.Program.Layout;
|
||||||
|
using Front.Program.Services;
|
||||||
|
|
||||||
namespace Front.Program.Views.Project;
|
namespace Front.Program.Views.Project;
|
||||||
|
|
||||||
|
@ -14,10 +15,14 @@ public partial class Register : ComponentBase
|
||||||
[Inject] private NavigationManager NavigationManager { get; set; } = default!;
|
[Inject] private NavigationManager NavigationManager { get; set; } = default!;
|
||||||
[Inject] private HttpClient Http { get; set; } = default!;
|
[Inject] private HttpClient Http { get; set; } = default!;
|
||||||
[Inject] private IConfiguration Configuration { get; set; } = default!;
|
[Inject] private IConfiguration Configuration { get; set; } = default!;
|
||||||
|
[Inject] private LoadingService LoadingService { get; set; } = default!;
|
||||||
|
|
||||||
private ElementReference dateInputRef;
|
private ElementReference dateInputRef;
|
||||||
|
|
||||||
private string name = "";
|
private string name = "";
|
||||||
|
private string birthYear = "";
|
||||||
|
private string birthMonth = "";
|
||||||
|
private string birthDay = "";
|
||||||
private DateTime? birth;
|
private DateTime? birth;
|
||||||
private string email = "";
|
private string email = "";
|
||||||
private string phone = "";
|
private string phone = "";
|
||||||
|
@ -89,6 +94,27 @@ public partial class Register : ComponentBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateBirthDate()
|
||||||
|
{
|
||||||
|
if (int.TryParse(birthYear, out int year) &&
|
||||||
|
int.TryParse(birthMonth, out int month) &&
|
||||||
|
int.TryParse(birthDay, out int day))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
birth = new DateTime(year, month, day);
|
||||||
|
}
|
||||||
|
catch (ArgumentOutOfRangeException)
|
||||||
|
{
|
||||||
|
birth = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
birth = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ConfirmData()
|
private async Task ConfirmData()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
@ -103,6 +129,9 @@ public partial class Register : ComponentBase
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 생일 업데이트
|
||||||
|
UpdateBirthDate();
|
||||||
|
|
||||||
// 전화번호 조합
|
// 전화번호 조합
|
||||||
if (phonePart1.Length == 3 && phonePart2.Length == 4 && phonePart3.Length == 4)
|
if (phonePart1.Length == 3 && phonePart2.Length == 4 && phonePart3.Length == 4)
|
||||||
{
|
{
|
||||||
|
@ -139,7 +168,7 @@ public partial class Register : ComponentBase
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MainLayout.ShowLoading();
|
LoadingService.ShowLoading();
|
||||||
// 쿠키에서 토큰 가져오기
|
// 쿠키에서 토큰 가져오기
|
||||||
var token = await JS.InvokeAsync<string>("eval", "document.cookie.split('; ').find(row => row.startsWith('Web_AM_Connect_Key='))?.split('=')[1] || ''");
|
var token = await JS.InvokeAsync<string>("eval", "document.cookie.split('; ').find(row => row.startsWith('Web_AM_Connect_Key='))?.split('=')[1] || ''");
|
||||||
Console.WriteLine($"쿠키에서 가져온 토큰: '{token}'");
|
Console.WriteLine($"쿠키에서 가져온 토큰: '{token}'");
|
||||||
|
@ -149,7 +178,7 @@ public partial class Register : ComponentBase
|
||||||
await JS.InvokeVoidAsync("alert", "인증 정보가 없습니다.");
|
await JS.InvokeVoidAsync("alert", "인증 정보가 없습니다.");
|
||||||
NavigationManager.NavigateTo("/");
|
NavigationManager.NavigateTo("/");
|
||||||
|
|
||||||
MainLayout.HideLoading();
|
LoadingService.HideLoading();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,30 +215,27 @@ public partial class Register : ComponentBase
|
||||||
// 세션 스토리지 정리
|
// 세션 스토리지 정리
|
||||||
await JS.InvokeVoidAsync("sessionStorage.removeItem", "snsId");
|
await JS.InvokeVoidAsync("sessionStorage.removeItem", "snsId");
|
||||||
|
|
||||||
MainLayout.HideLoading();
|
LoadingService.HideLoading();
|
||||||
await JS.InvokeVoidAsync("alert", "회원가입이 완료되었습니다.");
|
await JS.InvokeVoidAsync("alert", "회원가입이 완료되었습니다.");
|
||||||
NavigationManager.NavigateTo("/");
|
NavigationManager.NavigateTo("/");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MainLayout.HideLoading();
|
LoadingService.HideLoading();
|
||||||
await JS.InvokeVoidAsync("alert", $"회원가입 실패: {message}");
|
await JS.InvokeVoidAsync("alert", $"회원가입에 실패하였습니다.\n잠시 후 다시 시도해주세요.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MainLayout.HideLoading();
|
LoadingService.HideLoading();
|
||||||
Console.WriteLine($"API 호출 실패: {response.StatusCode}");
|
await JS.InvokeVoidAsync("alert", "회원가입 중 오류가 발생했습니다.\n잠시 후 다시 시도해주세요.");
|
||||||
var errorContent = await response.Content.ReadAsStringAsync();
|
|
||||||
Console.WriteLine($"에러 내용: {errorContent}");
|
|
||||||
await JS.InvokeVoidAsync("alert", "서버 오류가 발생했습니다.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MainLayout.HideLoading();
|
LoadingService.HideLoading();
|
||||||
Console.WriteLine($"예외 발생: {ex.Message}");
|
Console.WriteLine($"예외 발생: {ex.Message}");
|
||||||
await JS.InvokeVoidAsync("alert", $"오류가 발생했습니다: {ex.Message}");
|
await JS.InvokeVoidAsync("alert", "회원가입 중 오류가 발생했습니다.\n잠시 후 다시 시도해주세요.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,8 +254,16 @@ public partial class Register : ComponentBase
|
||||||
|
|
||||||
private async Task OpenDatePicker()
|
private async Task OpenDatePicker()
|
||||||
{
|
{
|
||||||
if (birth == null) birth = DateTime.Now;
|
try
|
||||||
await JS.InvokeVoidAsync("openDatePicker", dateInputRef);
|
{
|
||||||
|
if (birth == null) birth = DateTime.Now;
|
||||||
|
// showPicker 대신 click() 이벤트를 발생시켜 달력을 표시
|
||||||
|
await JS.InvokeVoidAsync("eval", $"document.querySelector('input[type=\"date\"]').click()");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"달력 표시 오류: {ex.Message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private void OnBirthChanged(ChangeEventArgs e)
|
private void OnBirthChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,13 +11,19 @@
|
||||||
<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="/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>
|
<a class="text-text-title font-medium leading-normal hover:text-blue-600" href="/new" @onclick="() => isOpen = !isOpen">What's New</a>
|
||||||
</div>
|
</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-second-normal hover:bg-second-dark text-white text-sm font-bold leading-normal tracking-[0.015em] mr-4"
|
@if (!isLoggedIn)
|
||||||
@onclick="OnClickLogin">
|
{
|
||||||
<span class="truncate">시작하기</span>
|
<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"
|
||||||
</button>
|
@onclick="OnClickLogin">
|
||||||
|
<span class="truncate">시작하기</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<button class="md:hidden mr-4" @onclick="OnClickMenuDown">
|
<button class="md:hidden mr-4" @onclick="OnClickMenuDown">
|
||||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<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"
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
@ -32,10 +38,13 @@
|
||||||
<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="/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="/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>
|
<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]"
|
@if (!isLoggedIn)
|
||||||
@onclick="OnClickLogin">
|
{
|
||||||
<span class="truncate">시작하기</span>
|
<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]"
|
||||||
</button>
|
@onclick="OnClickLogin">
|
||||||
|
<span class="truncate">시작하기</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
|
@ -3,14 +3,23 @@ using Microsoft.JSInterop;
|
||||||
|
|
||||||
namespace Front.Program.Views.Project;
|
namespace Front.Program.Views.Project;
|
||||||
|
|
||||||
public partial class TopNav : ComponentBase
|
public partial class TopProjectNav : ComponentBase
|
||||||
{
|
{
|
||||||
//로그인버튼을 누르면 페이지를 이동할거야
|
|
||||||
[Inject]
|
[Inject]
|
||||||
NavigationManager NavigationManager { get; set; } = default!;
|
NavigationManager NavigationManager { get; set; } = default!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
IJSRuntime JS { get; set; } = default!;
|
IJSRuntime JS { get; set; } = default!;
|
||||||
|
|
||||||
protected bool isOpen = false;
|
protected bool isOpen = false;
|
||||||
|
protected bool isLoggedIn = false;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
// 쿠키에서 로그인 상태 확인
|
||||||
|
var isLoginCookie = await JS.InvokeAsync<string>("eval", "document.cookie.split('; ').find(row => row.startsWith('IsLogin='))?.split('=')[1]");
|
||||||
|
isLoggedIn = isLoginCookie == "true";
|
||||||
|
}
|
||||||
|
|
||||||
public void OnClickMenuDown()
|
public void OnClickMenuDown()
|
||||||
{
|
{
|
||||||
|
@ -28,7 +37,4 @@ public partial class TopNav : ComponentBase
|
||||||
if (isOpen) isOpen = !isOpen;
|
if (isOpen) isOpen = !isOpen;
|
||||||
NavigationManager.NavigateTo("/auth");
|
NavigationManager.NavigateTo("/auth");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
<body class="bg-gray-50 text-gray-900 font-sans">
|
<body class="bg-gray-50 text-gray-900 font-sans">
|
||||||
|
|
||||||
<!-- 로딩 오버레이 -->
|
<!-- 로딩 오버레이 -->
|
||||||
<div class="fixed inset-0 z-50 flex items-center justify-center bg-gray-100" id="loading-overlay">
|
<div class="fixed inset-0 z-50 flex items-center justify-center bg-gray-100 hidden" id="loading-overlay" data-show-on="/about">
|
||||||
<!-- 로딩 오버레이 내부 -->
|
<!-- 로딩 오버레이 내부 -->
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<div class="relative w-48 h-48 overflow-hidden">
|
<div class="relative w-48 h-48 overflow-hidden">
|
||||||
|
@ -48,12 +48,20 @@
|
||||||
Blazor.start().then(() => {
|
Blazor.start().then(() => {
|
||||||
const elapsed = performance.now() - loadingStart;
|
const elapsed = performance.now() - loadingStart;
|
||||||
const remaining = Math.max(0, MIN_LOADING_MS - elapsed);
|
const remaining = Math.max(0, MIN_LOADING_MS - elapsed);
|
||||||
setTimeout(() => {
|
|
||||||
const overlay = document.getElementById('loading-overlay');
|
const overlay = document.getElementById('loading-overlay');
|
||||||
if (overlay) overlay.remove();
|
const showOnPath = overlay?.getAttribute('data-show-on');
|
||||||
}, remaining);
|
|
||||||
|
if (overlay && showOnPath && window.location.pathname === showOnPath) {
|
||||||
|
overlay.classList.remove('hidden');
|
||||||
|
setTimeout(() => {
|
||||||
|
if (overlay) overlay.remove();
|
||||||
|
}, remaining);
|
||||||
|
} else if (overlay) {
|
||||||
|
overlay.remove();
|
||||||
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error("❌ Blazor 로딩 실패", err);
|
console.error("Blazor 로딩 실패", err);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user