added page template and basic registration

This commit is contained in:
Anton 2023-08-06 17:09:09 +02:00
parent b7d46473ce
commit 3c276c8fdf
11 changed files with 107 additions and 32 deletions

8
package-lock.json generated
View File

@ -10,7 +10,7 @@
"license": "MIT",
"dependencies": {
"@heroicons/react": "^2.0.17",
"leaflet": "^1.9.3",
"leaflet": "^1.9.4",
"react-leaflet": "^4.2.1",
"react-leaflet-cluster": "^2.1.0",
"react-router-dom": "^6.11.2",
@ -2523,9 +2523,9 @@
}
},
"node_modules/leaflet": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.3.tgz",
"integrity": "sha512-iB2cR9vAkDOu5l3HAay2obcUHZ7xwUBBjph8+PGtmW/2lYhbLizWtG7nTeYht36WfOslixQF9D/uSIzhZgGMfQ=="
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
},
"node_modules/leaflet.markercluster": {
"version": "1.5.3",

View File

@ -43,7 +43,7 @@
},
"dependencies": {
"@heroicons/react": "^2.0.17",
"leaflet": "^1.9.3",
"leaflet": "^1.9.4",
"react-leaflet": "^4.2.1",
"react-leaflet-cluster": "^2.1.0",
"react-router-dom": "^6.11.2",

View File

@ -3,7 +3,7 @@ import NavBar from './NavBar'
import { BrowserRouter } from 'react-router-dom'
import { ToastContainer } from 'react-toastify'
export function AppShell({ name, useAuth, children }) {
export function AppShell({ appName, useAuth, children }) {
return (
<BrowserRouter>
<ToastContainer position="top-right"
@ -16,7 +16,7 @@ export function AppShell({ name, useAuth, children }) {
draggable
pauseOnHover
theme="light" />
<NavBar name={name} useAuth={useAuth}></NavBar>
<NavBar appName={appName} useAuth={useAuth}></NavBar>
<div id="app-content" className="tw-flex tw-!pl-[77px]">
{children}
</div>

View File

@ -5,12 +5,28 @@ import { toast } from "react-toastify";
import QuestionMarkIcon from '@heroicons/react/24/outline/QuestionMarkCircleIcon'
import * as React from "react";
export default function NavBar({name, useAuth} : {name: string, useAuth : any}) {
export default function NavBar({appName, useAuth} : {appName: string, useAuth : any}) {
const [email, setEmail] = useState<string>("");
const [userName, setUserName] = useState<string>("");
const [password, setPassword] = useState<string>("");
const { isAuthenticated, user, login, loading, logout, token } = useAuth();
const { isAuthenticated, user, login, register, loading, logout, token } = useAuth();
const onRegister = () => {
toast.promise(
register({ email: email, password: password}, userName),
{
success: {
render({data}){
return `Hi ${data?.first_name}`
},
// other options
icon: "✌️",
},
error: 'Error'
});
}
const onLogin = () => {
toast.promise(
@ -39,7 +55,7 @@ export default function NavBar({name, useAuth} : {name: string, useAuth : any})
</button>
<div className="tw-flex-1 tw-mr-2">
<div className="tw-flex-1 tw-truncate tw-grid tw-grid-flow-col tw-max-w-52">
<Link className="tw-btn tw-btn-ghost tw-px-2 tw-normal-case tw-text-xl tw-flex-1 tw-truncate" to={"/"}><p className="tw-truncate">{name}</p></Link>
<Link className="tw-btn tw-btn-ghost tw-px-2 tw-normal-case tw-text-xl tw-flex-1 tw-truncate" to={"/"}><p className="tw-truncate">{appName}</p></Link>
<button className="tw-btn tw-px-2 tw-btn-ghost" onClick={() => window.my_modal_3.showModal()}><QuestionMarkIcon className="tw-h-5 tw-w-5"/></button>
</div>
@ -49,11 +65,11 @@ export default function NavBar({name, useAuth} : {name: string, useAuth : any})
{isAuthenticated && token ?
<div className="tw-flex-none">
<div className="tw-avatar">
{user.avatar ? <div className="tw-avatar">
<div className="tw-w-10 tw-rounded-full">
<img src={"https://map.api.free-planet-earth.org/assets/"+user?.avatar+"?access_token="+token} />
</div>
</div>
</div> : <></>}
<div className='tw-ml-2 tw-mr-2'>{user?.first_name}</div>
<div className="tw-dropdown tw-dropdown-end">
<label tabIndex={0} className="tw-btn tw-btn-ghost tw-btn-square">
@ -68,16 +84,33 @@ export default function NavBar({name, useAuth} : {name: string, useAuth : any})
</div>
</div>
:
<div className="tw-dropdown tw-dropdown-end tw-mr-2">
<label tabIndex={0} className="tw-btn tw-btn-ghost">
Login
</label>
<div tabIndex={0} className="tw-mt-3 tw-card tw-card-compact tw-dropdown-content tw-w-72 tw-bg-base-100 tw-shadow !tw-z-[1000]">
<div className="tw-card-body">
<input type="email" placeholder="E-Mail" value={email} onChange={e => setEmail(e.target.value)} className="tw-input tw-input-bordered tw-w-full tw-max-w-xs" />
<input type="password" placeholder="Password" onChange={e => setPassword(e.target.value)} className="tw-input tw-input-bordered tw-w-full tw-max-w-xs" />
<div className="tw-card-actions">
<button className={loading ? 'tw-btn tw-loading tw-btn-disabled tw-btn-block tw-btn-primary' : 'tw-btn tw-btn-primary tw-btn-block'} onClick={() => onLogin()}>Login</button>
<div>
<div className="tw-dropdown tw-dropdown-end tw-mr-2">
<label tabIndex={0} className="tw-btn tw-btn-ghost">
Login
</label>
<div tabIndex={0} className="tw-mt-3 tw-card tw-card-compact tw-dropdown-content tw-w-72 tw-bg-base-100 tw-shadow !tw-z-[1000]">
<div className="tw-card-body">
<input type="email" placeholder="E-Mail" value={email} onChange={e => setEmail(e.target.value)} className="tw-input tw-input-bordered tw-w-full tw-max-w-xs" />
<input type="password" placeholder="Password" onChange={e => setPassword(e.target.value)} className="tw-input tw-input-bordered tw-w-full tw-max-w-xs" />
<div className="tw-card-actions">
<button className={loading ? 'tw-btn tw-btn-disabled tw-btn-block tw-btn-primary' : 'tw-btn tw-btn-primary tw-btn-block'} onClick={() => onLogin()}>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Login'}</button>
</div>
</div>
</div>
</div>
<div className="tw-dropdown tw-dropdown-end tw-mr-2">
<label tabIndex={0} className="tw-btn tw-btn-ghost">
Sign Up
</label>
<div tabIndex={0} className="tw-mt-3 tw-card tw-card-compact tw-dropdown-content tw-w-72 tw-bg-base-100 tw-shadow !tw-z-[1000]">
<div className="tw-card-body">
<input type="text" placeholder="Name" value={userName} onChange={e => setUserName(e.target.value)} className="tw-input tw-input-bordered tw-w-full tw-max-w-xs" />
<input type="email" placeholder="E-Mail" value={email} onChange={e => setEmail(e.target.value)} className="tw-input tw-input-bordered tw-w-full tw-max-w-xs" />
<input type="password" placeholder="Password" onChange={e => setPassword(e.target.value)} className="tw-input tw-input-bordered tw-w-full tw-max-w-xs" />
<div className="tw-card-actions">
<button className={loading ? 'tw-btn tw-btn-disabled tw-btn-block tw-btn-primary' : 'tw-btn tw-btn-primary tw-btn-block'} onClick={() => onRegister()}>{loading ? <span className="tw-loading tw-loading-spinner"></span> : 'Sign Up'}</button>
</div>
</div>
</div>
</div>

View File

@ -28,6 +28,7 @@ type AuthContextProps = {
isAuthenticated: Boolean,
user: MyUserItem | null;
login: (credentials: AuthCredentials) => Promise<MyUserItem | undefined>,
register: (credentials: AuthCredentials, userName: string) => Promise<MyUserItem | undefined>,
loading: Boolean,
logout: () => void,
updateUser: (user: MyUserItem) => any,
@ -38,6 +39,7 @@ const AuthContext = createContext<AuthContextProps>({
isAuthenticated: false,
user: null,
login: () => Promise.reject(),
register: () => Promise.reject(),
loading: false,
logout: () => { },
updateUser: () => Promise.reject(),
@ -87,6 +89,18 @@ export const AuthProviderDirectus = ({ directus, children }: AuthProviderProps)
};
}
const register = async (credentials: AuthCredentials, userName): Promise<MyUserItem | undefined> => {
setLoading(true);
try {
const res = await directus.users.createOne({email: credentials.email, password: credentials.password, first_name: userName});
return (await login(credentials));
} catch (error: any) {
setLoading(false);
console.log(error);
return error.response.data.error[0];
};
}
const logout = async () => {
@ -96,9 +110,10 @@ export const AuthProviderDirectus = ({ directus, children }: AuthProviderProps)
const updateUser = async (user: MyUserItem) => {
setLoading(true);
const { id, ...userRest } = user;
try {
const res = await directus.users.updateOne(user.id!, user)
const res = await directus.users.updateOne(user.id!, userRest)
setUser(res as any);
setLoading(false);
return res as any;
@ -115,7 +130,7 @@ export const AuthProviderDirectus = ({ directus, children }: AuthProviderProps)
return (
<AuthContext.Provider
value={{ isAuthenticated, user, login, loading, logout, updateUser, token }}
value={{ isAuthenticated, user, login, register, loading, logout, updateUser, token }}
>
{children}
</AuthContext.Provider>

View File

@ -39,7 +39,6 @@ function MapEventListener(props: MapEventListenerProps) {
// for refreshing map on resize (needs to be implemented)
const mapDivRef = React.createRef();
/** This is a description of the foo function. */
function UtopiaMap({
height = "500px",
width = "100%",

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'
import TitleCard from '../TitleCard'
import {TitleCard} from '../Templates/TitleCard'
import InputText from '../Input/InputText'
import TextAreaInput from '../Input/TextAreaInput'
import { toast } from 'react-toastify';

View File

@ -0,0 +1,27 @@
import { Link } from "react-router-dom"
import * as React from "react"
import {TitleCard} from "./TitleCard"
export function CardPage({title,children} : {
title: string,
children?: React.ReactNode,
}) {
return (
<main className="tw-flex-1 tw-overflow-y-auto tw-overflow-x-hidden tw-pt-2 tw-px-6 tw-bg-base-200 tw-min-w-80 tw-flex tw-justify-center" >
<div className='tw-w-full xl:tw-max-w-6xl'>
<div className="tw-text-sm tw-breadcrumbs">
<ul>
<li><Link to={'/'} >Home</Link></li>
<li>FAQ</li>
</ul>
</div>
<TitleCard title={title} topMargin="mt-2">
{children}
</TitleCard>
</div>
</main>
)
}

View File

@ -1,4 +1,4 @@
import Subtitle from "./Typography/Subtitle"
import Subtitle from "../Typography/Subtitle"
import * as React from "react"
interface TitleCardProps {
@ -9,7 +9,7 @@ interface TitleCardProps {
TopSideButtons?: any
}
function TitleCard({title, children, topMargin, TopSideButtons} : TitleCardProps){
export function TitleCard({title, children, topMargin, TopSideButtons} : TitleCardProps){
return(
<div className={"tw-card tw-w-full tw-p-6 tw-mb-16 tw-bg-base-100 tw-shadow-xl tw-h-fit " + (topMargin || "tw-mt-6")}>
@ -33,6 +33,3 @@ interface TitleCardProps {
)
}
export default TitleCard

View File

@ -0,0 +1,2 @@
export {CardPage} from './CardPage'
export {TitleCard} from './TitleCard'

View File

@ -3,6 +3,8 @@ export {AppShell, Content, SideBar} from "./Components/AppShell"
export {AuthProviderDirectus, useAuthDirectus} from "./Components/Auth"
export {Settings} from './Components/Profile'
export {Quests, Modal} from './Components/Gaming'
export {TitleCard, CardPage} from './Components/Templates'
import "./index.css"
declare global {