update character
This commit is contained in:
@@ -38,7 +38,7 @@ public class CharacterController(
|
|||||||
{
|
{
|
||||||
return BadRequest(ex.Message);
|
return BadRequest(ex.Message);
|
||||||
}
|
}
|
||||||
var id = await persistenceService.StoreNewCharacter(model);
|
var id = await persistenceService.StoreNewCharacter(model, isPublic);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +54,32 @@ public class CharacterController(
|
|||||||
return dbModelToDtoService.Convert(entity);
|
return dbModelToDtoService.Convert(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("{id:guid}")]
|
||||||
|
public async Task<ActionResult<Guid>> UpdateCharacter([FromRoute] Guid id, [FromBody] CharacterDto dto, bool isPublic = true)
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return BadRequest(ModelState);
|
||||||
|
}
|
||||||
|
var errors = validationService.Validate(dto);
|
||||||
|
if (errors != null)
|
||||||
|
{
|
||||||
|
return BadRequest(errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
var original = await persistenceService.GetCharacterById(id, tracking: true);
|
||||||
|
if (original is null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
dtoToDbModelService.Update(original, dto);
|
||||||
|
|
||||||
|
await persistenceService.UpdateCharacter(original, isPublic);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public async Task<List<CharacterListItemDto>> GetAllCharacters()
|
public async Task<List<CharacterListItemDto>> GetAllCharacters()
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace Kemkas.Web.Services.Character;
|
|||||||
public interface ICharacterDtoToDbModelService
|
public interface ICharacterDtoToDbModelService
|
||||||
{
|
{
|
||||||
public V1Karakter Convert(CharacterDto dto);
|
public V1Karakter Convert(CharacterDto dto);
|
||||||
|
|
||||||
|
public void Update(V1Karakter original, CharacterDto dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CharacterDtoToDbModelService : ICharacterDtoToDbModelService
|
public class CharacterDtoToDbModelService : ICharacterDtoToDbModelService
|
||||||
@@ -45,6 +47,34 @@ public class CharacterDtoToDbModelService : ICharacterDtoToDbModelService
|
|||||||
return karakter;
|
return karakter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Update(V1Karakter original, CharacterDto dto)
|
||||||
|
{
|
||||||
|
original.Nev = dto.Name;
|
||||||
|
original.Nem = dto.Nem;
|
||||||
|
original.Kor = dto.Kor;
|
||||||
|
original.Jellem = JellemExtensions.Convert(dto.Jellem);
|
||||||
|
original.Isten = dto.Isten;
|
||||||
|
original.Faj = FajExtensions.Convert(dto.Faj);
|
||||||
|
original.Osztaly = OsztalyExtensions.Convert(dto.Osztaly);
|
||||||
|
original.Ero = dto.Tulajdonsagok.Ero;
|
||||||
|
original.Ugyesseg = dto.Tulajdonsagok.Ugy;
|
||||||
|
original.Egeszseg = dto.Tulajdonsagok.Egs;
|
||||||
|
original.Intelligencia = dto.Tulajdonsagok.Int;
|
||||||
|
original.Bolcsesseg = dto.Tulajdonsagok.Bol;
|
||||||
|
original.Karizma = dto.Tulajdonsagok.Kar;
|
||||||
|
original.Szint = dto.Szint;
|
||||||
|
original.Pajzs = dto.Felszereles.PajzsId;
|
||||||
|
original.Pancel = dto.Felszereles.PancelId;
|
||||||
|
original.KarakterKepzettsegek = ConvertKepzettsegek(dto, original);
|
||||||
|
original.Felszereles = dto.Felszereles.FegyverIds.Select(x => new V1Felszereles
|
||||||
|
{
|
||||||
|
Karakter = original,
|
||||||
|
IsFegyver = true,
|
||||||
|
Name = x,
|
||||||
|
}).ToList();
|
||||||
|
original.Szintlepesek = ConvertSzintLepes(dto, original);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: this is unnecessary duplication of business logic!!
|
// TODO: this is unnecessary duplication of business logic!!
|
||||||
private static List<V1Szintlepes> ConvertSzintLepes(CharacterDto dto, V1Karakter karakter)
|
private static List<V1Szintlepes> ConvertSzintLepes(CharacterDto dto, V1Karakter karakter)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,9 +11,11 @@ public interface ICharacterPersistenceService
|
|||||||
{
|
{
|
||||||
public Task<Guid> StoreNewCharacter(V1Karakter karakter, bool isPublic = false);
|
public Task<Guid> StoreNewCharacter(V1Karakter karakter, bool isPublic = false);
|
||||||
|
|
||||||
public Task<V1Karakter?> GetCharacterById(Guid id);
|
public Task<V1Karakter?> GetCharacterById(Guid id, bool tracking = false);
|
||||||
|
|
||||||
public Task<List<CharacterListItemDto>> GetAllCharactersOfUser();
|
public Task<List<CharacterListItemDto>> GetAllCharactersOfUser();
|
||||||
|
|
||||||
|
public Task UpdateCharacter(V1Karakter karakter, bool isPublic = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CharacterPersistenceService(
|
public class CharacterPersistenceService(
|
||||||
@@ -33,12 +35,15 @@ public class CharacterPersistenceService(
|
|||||||
return karakter.Id;
|
return karakter.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<V1Karakter?> GetCharacterById(Guid id)
|
public async Task<V1Karakter?> GetCharacterById(Guid id, bool tracking = false)
|
||||||
{
|
{
|
||||||
var entity = await dbContext.Karakterek
|
IQueryable<V1Karakter> queriable = dbContext.Karakterek.Include(x => x.KarakterKepzettsegek)
|
||||||
.Include(x => x.KarakterKepzettsegek)
|
|
||||||
.Include(x => x.Szintlepesek)
|
.Include(x => x.Szintlepesek)
|
||||||
.Include(x => x.Felszereles)
|
.Include(x => x.Felszereles);
|
||||||
|
|
||||||
|
queriable = tracking ? queriable.AsTracking() : queriable.AsNoTracking();
|
||||||
|
|
||||||
|
var entity = await queriable
|
||||||
.FirstOrDefaultAsync(x => x.Id == id);
|
.FirstOrDefaultAsync(x => x.Id == id);
|
||||||
|
|
||||||
if (entity?.OwnerUserId is null || entity.IsPublic)
|
if (entity?.OwnerUserId is null || entity.IsPublic)
|
||||||
@@ -72,4 +77,11 @@ public class CharacterPersistenceService(
|
|||||||
|
|
||||||
return characters;
|
return characters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task UpdateCharacter(V1Karakter karakter, bool isPublic = false)
|
||||||
|
{
|
||||||
|
karakter.IsPublic = isPublic;
|
||||||
|
dbContext.Karakterek.Attach(karakter);
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import React, {useEffect, useState} from 'react';
|
import * as React from 'react';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import {Faro} from "@grafana/faro-web-sdk";
|
import {Faro} from "@grafana/faro-web-sdk";
|
||||||
import {createBrowserRouter, RouterProvider} from "react-router-dom";
|
import {createBrowserRouter, RouterProvider} from "react-router-dom";
|
||||||
import CreateCharacter from "./first-edition/pages/CreateCharacter";
|
import CreateCharacter from "./first-edition/pages/CreateCharacter";
|
||||||
import CharacterList from "./first-edition/pages/CharacterList";
|
import CharacterList from "./first-edition/pages/CharacterList";
|
||||||
import ErrorBoundary from "./shared/ErrorBoundary";
|
import ErrorBoundary from "./shared/ErrorBoundary";
|
||||||
|
import Header from "./shared/Header";
|
||||||
type LoadingState = "not-started" | "loading" | "finished"
|
import Footer from "./shared/Footer";
|
||||||
|
|
||||||
function App(props: {faro?: Faro}) {
|
function App(props: {faro?: Faro}) {
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
@@ -23,95 +23,20 @@ function App(props: {faro?: Faro}) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/:id",
|
path: "/:id",
|
||||||
element: <CreateCharacter faro={props.faro} />,
|
element: <CreateCharacter faro={props.faro}/>,
|
||||||
loader: args => fetch(`api/Character/${args.params.id}`),
|
loader: args => fetch(`api/Character/${args.params.id}`),
|
||||||
ErrorBoundary: ErrorBoundary,
|
ErrorBoundary: ErrorBoundary,
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let [loading, setLoading] = useState("not-started" as LoadingState);
|
|
||||||
let [userName, setUserName] = useState(null as string | null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let ignore = false;
|
|
||||||
if (loading === "not-started") {
|
|
||||||
setLoading("loading");
|
|
||||||
fetch('api/User/me')
|
|
||||||
.then(response => {
|
|
||||||
if (response.ok) {
|
|
||||||
response.text()
|
|
||||||
.then((data) => data?.length > 0 ? setUserName(data) : setUserName(null))
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err)
|
|
||||||
!ignore && setUserName(null);
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
console.log(response)
|
|
||||||
!ignore && setUserName(null);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
!ignore && setUserName(null)
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setLoading("finished");
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
ignore = true
|
|
||||||
}
|
|
||||||
}, [loading, setLoading, userName, setUserName])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header>
|
<Header/>
|
||||||
<nav
|
|
||||||
className="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
|
|
||||||
<div className="container ps-4 pe-4">
|
|
||||||
<a className="navbar-brand" href={userName == null ? "/" : "/karaktereim"}>Kemkas</a>
|
|
||||||
<button className="navbar-toggler" type="button" data-bs-toggle="collapse"
|
|
||||||
data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
|
|
||||||
aria-expanded="false" aria-label="Toggle navigation">
|
|
||||||
<span className="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
{loading !== "finished" ? "Loading..." :
|
|
||||||
userName == null
|
|
||||||
? <div className="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
|
|
||||||
<ul className="navbar-nav">
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link text-dark" href="/Identity/Account/Register">Register</a>
|
|
||||||
</li>
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link text-dark" href="/Identity/Account/Login">Login</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
: <div className="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
|
|
||||||
<ul className="navbar-nav">
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link text-dark" href="/Identity/Account/Manage">Hello {userName}!</a>
|
|
||||||
</li>
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link text-dark" href="/Identity/Account/Logout">Logout</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
<div className='container'>
|
<div className='container'>
|
||||||
<RouterProvider router={router}/>
|
<RouterProvider router={router}/>
|
||||||
</div>
|
</div>
|
||||||
<footer>
|
<Footer />
|
||||||
<div className="text-center p-4" style={{backgroundColor: "rgba(0, 0, 0, 0.05)"}}>
|
|
||||||
A Kard és Mágiát Lux Gábor alkotta. A szerzői jogok őt illetik. Ez az oldal egy "rajongói
|
|
||||||
hozzájárulás", célja a Kard és Mágia népszerűsítése. Ha többet akarsz tudni a Kard és Mágiáról
|
|
||||||
látogass el a <a href="https://fomalhaut.lfg.hu/">hivatalos honlapjára</a>. A Kard és Mágia az Open
|
|
||||||
Gaming Licence 1.0a alatt lett kiadva, melynek szövege <a href="ogl.html">itt található</a>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,3 +12,16 @@ export async function StoreNewCharacter(karakter: KarakterInputs) {
|
|||||||
throw Error(response.statusText)
|
throw Error(response.statusText)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function UpdateCharacter(id: string, karakter: KarakterInputs) {
|
||||||
|
let response = await axios.post(`${window.location.origin}/api/Character/${id}`, karakter, {
|
||||||
|
withCredentials: true,
|
||||||
|
})
|
||||||
|
if (response.status < 300){
|
||||||
|
return response.data as string
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw Error(response.statusText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ function LevelUp(props: {
|
|||||||
const kritIndex = kalozKritIndex(szint)
|
const kritIndex = kalozKritIndex(szint)
|
||||||
const krit = karakter.kalozKritikus[kritIndex]
|
const krit = karakter.kalozKritikus[kritIndex]
|
||||||
|
|
||||||
return <div key={`level-up-${szint}`}>
|
return <div>
|
||||||
<div className='row mt-3'>
|
<div className='row mt-3'>
|
||||||
<h5 className='col align-self-center'>{szint}. Szint</h5>
|
<h5 className='col align-self-center'>{szint}. Szint</h5>
|
||||||
</div>
|
</div>
|
||||||
@@ -87,8 +87,10 @@ export function LevelUps(props: {karakter: KarakterInputs, changeKarakter: (inpu
|
|||||||
changeKarakter({...karakter, kalozKritikus: arraySetN(karakter.kalozKritikus, kalozKritIndex(szint), krit)})
|
changeKarakter({...karakter, kalozKritikus: arraySetN(karakter.kalozKritikus, kalozKritIndex(szint), krit)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const levels = karakter.hpRolls.map((_, i) => i+2);
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
{karakter.hpRolls.map((_, i) => i+2).map(szint => <>
|
{levels.map(szint =>
|
||||||
<LevelUp
|
<LevelUp
|
||||||
key={`level-up-${szint}`}
|
key={`level-up-${szint}`}
|
||||||
szint={szint}
|
szint={szint}
|
||||||
@@ -98,7 +100,6 @@ export function LevelUps(props: {karakter: KarakterInputs, changeKarakter: (inpu
|
|||||||
changeHarcosSpec={changeHarcosSpecializacioAtSzint(szint)}
|
changeHarcosSpec={changeHarcosSpecializacioAtSzint(szint)}
|
||||||
changeKalozKritikus={changeKalozKritikusAtSzint(szint)}
|
changeKalozKritikus={changeKalozKritikusAtSzint(szint)}
|
||||||
/>
|
/>
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ import {CalculateMasodlagosErtekek} from "../domain-models/masodlagos_ertekek";
|
|||||||
import {KarakterInputToPdfView} from "../pdf/karakter_pdf_view";
|
import {KarakterInputToPdfView} from "../pdf/karakter_pdf_view";
|
||||||
import JellemSelector from "../components/JellemSelector";
|
import JellemSelector from "../components/JellemSelector";
|
||||||
import {CanLevelUp, LevelDown, LevelUp} from "../domain-models/level";
|
import {CanLevelUp, LevelDown, LevelUp} from "../domain-models/level";
|
||||||
import {Card, OverlayTrigger} from "react-bootstrap";
|
import {Card, OverlayTrigger, Toast, ToastContainer} from "react-bootstrap";
|
||||||
import LevelUps from "../components/LevelUps";
|
import LevelUps from "../components/LevelUps";
|
||||||
import HarcosFegyverSpecializacio from "../components/HarcosFegyverSpecializacio";
|
import HarcosFegyverSpecializacio from "../components/HarcosFegyverSpecializacio";
|
||||||
import Felszereles from '../components/Felszereles';
|
import Felszereles from '../components/Felszereles';
|
||||||
import { KarakterFelszereles } from '../domain-models/felszereles';
|
import { KarakterFelszereles } from '../domain-models/felszereles';
|
||||||
import {Faro} from "@grafana/faro-web-sdk";
|
import {Faro} from "@grafana/faro-web-sdk";
|
||||||
import {StoreNewCharacter} from "../api/character.api";
|
import {StoreNewCharacter, UpdateCharacter} from "../api/character.api";
|
||||||
import {useLoaderData} from "react-router-dom";
|
import {useLoaderData, useParams} from "react-router-dom";
|
||||||
import saveOverlayTooltip from "../components/SaveOverlayTooltip";
|
import saveOverlayTooltip from "../components/SaveOverlayTooltip";
|
||||||
|
|
||||||
function CreateCharacterPage(props: {
|
function CreateCharacterPage(props: {
|
||||||
@@ -38,6 +38,7 @@ function CreateCharacterPage(props: {
|
|||||||
const {faro} = props
|
const {faro} = props
|
||||||
|
|
||||||
const initialKarakterInputs = useLoaderData() as KarakterInputs;
|
const initialKarakterInputs = useLoaderData() as KarakterInputs;
|
||||||
|
const { id } = useParams();
|
||||||
|
|
||||||
let [karakter, changeKarakter] = useState(initialKarakterInputs ?? KarakterDefaults)
|
let [karakter, changeKarakter] = useState(initialKarakterInputs ?? KarakterDefaults)
|
||||||
|
|
||||||
@@ -55,12 +56,21 @@ function CreateCharacterPage(props: {
|
|||||||
const levelDown = () => LevelDown(karakter, changeKarakter)
|
const levelDown = () => LevelDown(karakter, changeKarakter)
|
||||||
|
|
||||||
const canLevelUp = CanLevelUp(karakter)
|
const canLevelUp = CanLevelUp(karakter)
|
||||||
|
|
||||||
|
let [showSaved, setShowSaved] = useState(false);
|
||||||
|
|
||||||
|
const hideSaved = () => setShowSaved(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='container-fluid p-5 bg-black text-white text-center'>
|
<div className='container-fluid p-5 bg-black text-white text-center'>
|
||||||
<h1>Karakter {initialKarakterInputs ? "szerkesztése*" : "létrehozása"}</h1>
|
<h1>Karakter {initialKarakterInputs ? "szerkesztése" : "létrehozása"}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
<ToastContainer className="position-fixed" position="top-end">
|
||||||
|
<Toast show={showSaved} onClose={hideSaved} bg="success">
|
||||||
|
<Toast.Header><strong>Karakter mentve!</strong></Toast.Header>
|
||||||
|
</Toast>
|
||||||
|
</ToastContainer>
|
||||||
<div className='p-3'>
|
<div className='p-3'>
|
||||||
<form onSubmit={async (event) => event.preventDefault()}>
|
<form onSubmit={async (event) => event.preventDefault()}>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
@@ -182,10 +192,18 @@ function CreateCharacterPage(props: {
|
|||||||
szint: karakter.szint.toString(),
|
szint: karakter.szint.toString(),
|
||||||
faj: karakter.faj.toString(),
|
faj: karakter.faj.toString(),
|
||||||
})
|
})
|
||||||
let newId = await StoreNewCharacter(karakter)
|
if (id == null) {
|
||||||
const win = window.open(`/${newId}`, '_blank');
|
let newId = await StoreNewCharacter(karakter);
|
||||||
if (win != null) {
|
const win = window.open(`/${newId}`, '_blank');
|
||||||
win.focus();
|
if (win != null) {
|
||||||
|
win.focus();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await UpdateCharacter(id, karakter);
|
||||||
|
setShowSaved(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
hideSaved();
|
||||||
|
}, 5000)
|
||||||
}
|
}
|
||||||
}}>Mentés
|
}}>Mentés
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -31,8 +31,3 @@ root.render(
|
|||||||
<App faro={faro} />
|
<App faro={faro} />
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
);
|
);
|
||||||
|
|
||||||
// If you want to start measuring performance in your app, pass a function
|
|
||||||
// to log results (for example: reportWebVitals(console.log))
|
|
||||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
|
||||||
reportWebVitals();
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
|
||||||
|
function Footer() {
|
||||||
|
return <footer>
|
||||||
|
<div className="text-center p-4" style={{backgroundColor: "rgba(0, 0, 0, 0.05)"}}>
|
||||||
|
A Kard és Mágiát Lux Gábor alkotta. A szerzői jogok őt illetik. Ez az oldal egy "rajongói
|
||||||
|
hozzájárulás", célja a Kard és Mágia népszerűsítése. Ha többet akarsz tudni a Kard és Mágiáról
|
||||||
|
látogass el a <a href="https://fomalhaut.lfg.hu/">hivatalos honlapjára</a>. A Kard és Mágia az Open
|
||||||
|
Gaming Licence 1.0a alatt lett kiadva, melynek szövege <a href="ogl.html">itt található</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import axios from "axios";
|
||||||
|
import {useState} from "react";
|
||||||
|
|
||||||
|
type LoadingState = "not-started" | "loading" | "finished"
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
return axios.post("/Identity/Account/Logout?returnUrl=%2F")
|
||||||
|
}
|
||||||
|
|
||||||
|
function Header(props: {}) {
|
||||||
|
|
||||||
|
let [loading, setLoading] = useState("not-started" as LoadingState);
|
||||||
|
let [userName, setUserName] = useState(null as string | null);
|
||||||
|
|
||||||
|
if (loading === "not-started") {
|
||||||
|
setLoading("loading");
|
||||||
|
fetch('api/User/me')
|
||||||
|
.then(response => {
|
||||||
|
response.ok
|
||||||
|
? response.text()
|
||||||
|
.then(userName => userName?.length > 0 ? setUserName(userName) : setUserName(null))
|
||||||
|
: console.log(response)
|
||||||
|
})
|
||||||
|
.finally(() => setLoading("finished"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return <header>
|
||||||
|
<nav
|
||||||
|
className="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
|
||||||
|
<div className="container ps-4 pe-4">
|
||||||
|
<a className="navbar-brand" href={userName == null ? "/" : "/karaktereim"}>Kemkas</a>
|
||||||
|
<button className="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||||
|
data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
|
||||||
|
aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span className="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
{loading !== "finished" ? "Loading..." :
|
||||||
|
userName == null
|
||||||
|
? <div className="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
|
||||||
|
<ul className="navbar-nav">
|
||||||
|
<li className="nav-item">
|
||||||
|
<a className="nav-link text-dark" href="/Identity/Account/Register">Register</a>
|
||||||
|
</li>
|
||||||
|
<li className="nav-item">
|
||||||
|
<a className="nav-link text-dark" href="/Identity/Account/Login">Login</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
: <div className="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
|
||||||
|
<ul className="navbar-nav">
|
||||||
|
<li className="nav-item">
|
||||||
|
<a className="nav-link text-dark" href="/Identity/Account/Manage">Hello {userName}!</a>
|
||||||
|
</li>
|
||||||
|
<li className="nav-item">
|
||||||
|
<a className="nav-link text-dark" href="/Identity/Account/Logout">Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Header;
|
||||||
Reference in New Issue
Block a user