mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
added page template and basic registration
This commit is contained in:
parent
b7d46473ce
commit
3c276c8fdf
8
package-lock.json
generated
8
package-lock.json
generated
@ -10,7 +10,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.17",
|
"@heroicons/react": "^2.0.17",
|
||||||
"leaflet": "^1.9.3",
|
"leaflet": "^1.9.4",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-leaflet-cluster": "^2.1.0",
|
"react-leaflet-cluster": "^2.1.0",
|
||||||
"react-router-dom": "^6.11.2",
|
"react-router-dom": "^6.11.2",
|
||||||
@ -2523,9 +2523,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/leaflet": {
|
"node_modules/leaflet": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
||||||
"integrity": "sha512-iB2cR9vAkDOu5l3HAay2obcUHZ7xwUBBjph8+PGtmW/2lYhbLizWtG7nTeYht36WfOslixQF9D/uSIzhZgGMfQ=="
|
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
|
||||||
},
|
},
|
||||||
"node_modules/leaflet.markercluster": {
|
"node_modules/leaflet.markercluster": {
|
||||||
"version": "1.5.3",
|
"version": "1.5.3",
|
||||||
|
|||||||
@ -43,7 +43,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@heroicons/react": "^2.0.17",
|
"@heroicons/react": "^2.0.17",
|
||||||
"leaflet": "^1.9.3",
|
"leaflet": "^1.9.4",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-leaflet-cluster": "^2.1.0",
|
"react-leaflet-cluster": "^2.1.0",
|
||||||
"react-router-dom": "^6.11.2",
|
"react-router-dom": "^6.11.2",
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import NavBar from './NavBar'
|
|||||||
import { BrowserRouter } from 'react-router-dom'
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
import { ToastContainer } from 'react-toastify'
|
import { ToastContainer } from 'react-toastify'
|
||||||
|
|
||||||
export function AppShell({ name, useAuth, children }) {
|
export function AppShell({ appName, useAuth, children }) {
|
||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<ToastContainer position="top-right"
|
<ToastContainer position="top-right"
|
||||||
@ -16,7 +16,7 @@ export function AppShell({ name, useAuth, children }) {
|
|||||||
draggable
|
draggable
|
||||||
pauseOnHover
|
pauseOnHover
|
||||||
theme="light" />
|
theme="light" />
|
||||||
<NavBar name={name} useAuth={useAuth}></NavBar>
|
<NavBar appName={appName} useAuth={useAuth}></NavBar>
|
||||||
<div id="app-content" className="tw-flex tw-!pl-[77px]">
|
<div id="app-content" className="tw-flex tw-!pl-[77px]">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -5,12 +5,28 @@ import { toast } from "react-toastify";
|
|||||||
import QuestionMarkIcon from '@heroicons/react/24/outline/QuestionMarkCircleIcon'
|
import QuestionMarkIcon from '@heroicons/react/24/outline/QuestionMarkCircleIcon'
|
||||||
import * as React from "react";
|
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 [email, setEmail] = useState<string>("");
|
||||||
|
const [userName, setUserName] = useState<string>("");
|
||||||
const [password, setPassword] = 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 = () => {
|
const onLogin = () => {
|
||||||
toast.promise(
|
toast.promise(
|
||||||
@ -39,7 +55,7 @@ export default function NavBar({name, useAuth} : {name: string, useAuth : any})
|
|||||||
</button>
|
</button>
|
||||||
<div className="tw-flex-1 tw-mr-2">
|
<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">
|
<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>
|
<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>
|
</div>
|
||||||
@ -49,11 +65,11 @@ export default function NavBar({name, useAuth} : {name: string, useAuth : any})
|
|||||||
|
|
||||||
{isAuthenticated && token ?
|
{isAuthenticated && token ?
|
||||||
<div className="tw-flex-none">
|
<div className="tw-flex-none">
|
||||||
<div className="tw-avatar">
|
{user.avatar ? <div className="tw-avatar">
|
||||||
<div className="tw-w-10 tw-rounded-full">
|
<div className="tw-w-10 tw-rounded-full">
|
||||||
<img src={"https://map.api.free-planet-earth.org/assets/"+user?.avatar+"?access_token="+token} />
|
<img src={"https://map.api.free-planet-earth.org/assets/"+user?.avatar+"?access_token="+token} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> : <></>}
|
||||||
<div className='tw-ml-2 tw-mr-2'>{user?.first_name}</div>
|
<div className='tw-ml-2 tw-mr-2'>{user?.first_name}</div>
|
||||||
<div className="tw-dropdown tw-dropdown-end">
|
<div className="tw-dropdown tw-dropdown-end">
|
||||||
<label tabIndex={0} className="tw-btn tw-btn-ghost tw-btn-square">
|
<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>
|
</div>
|
||||||
:
|
:
|
||||||
<div className="tw-dropdown tw-dropdown-end tw-mr-2">
|
<div>
|
||||||
<label tabIndex={0} className="tw-btn tw-btn-ghost">
|
<div className="tw-dropdown tw-dropdown-end tw-mr-2">
|
||||||
Login
|
<label tabIndex={0} className="tw-btn tw-btn-ghost">
|
||||||
</label>
|
Login
|
||||||
<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]">
|
</label>
|
||||||
<div className="tw-card-body">
|
<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]">
|
||||||
<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" />
|
<div className="tw-card-body">
|
||||||
<input type="password" placeholder="Password" onChange={e => setPassword(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" />
|
||||||
<div className="tw-card-actions">
|
<input type="password" placeholder="Password" onChange={e => setPassword(e.target.value)} className="tw-input tw-input-bordered tw-w-full tw-max-w-xs" />
|
||||||
<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 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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -28,6 +28,7 @@ type AuthContextProps = {
|
|||||||
isAuthenticated: Boolean,
|
isAuthenticated: Boolean,
|
||||||
user: MyUserItem | null;
|
user: MyUserItem | null;
|
||||||
login: (credentials: AuthCredentials) => Promise<MyUserItem | undefined>,
|
login: (credentials: AuthCredentials) => Promise<MyUserItem | undefined>,
|
||||||
|
register: (credentials: AuthCredentials, userName: string) => Promise<MyUserItem | undefined>,
|
||||||
loading: Boolean,
|
loading: Boolean,
|
||||||
logout: () => void,
|
logout: () => void,
|
||||||
updateUser: (user: MyUserItem) => any,
|
updateUser: (user: MyUserItem) => any,
|
||||||
@ -38,6 +39,7 @@ const AuthContext = createContext<AuthContextProps>({
|
|||||||
isAuthenticated: false,
|
isAuthenticated: false,
|
||||||
user: null,
|
user: null,
|
||||||
login: () => Promise.reject(),
|
login: () => Promise.reject(),
|
||||||
|
register: () => Promise.reject(),
|
||||||
loading: false,
|
loading: false,
|
||||||
logout: () => { },
|
logout: () => { },
|
||||||
updateUser: () => Promise.reject(),
|
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 () => {
|
const logout = async () => {
|
||||||
@ -96,9 +110,10 @@ export const AuthProviderDirectus = ({ directus, children }: AuthProviderProps)
|
|||||||
|
|
||||||
const updateUser = async (user: MyUserItem) => {
|
const updateUser = async (user: MyUserItem) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
const { id, ...userRest } = user;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await directus.users.updateOne(user.id!, user)
|
const res = await directus.users.updateOne(user.id!, userRest)
|
||||||
setUser(res as any);
|
setUser(res as any);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return res as any;
|
return res as any;
|
||||||
@ -115,7 +130,7 @@ export const AuthProviderDirectus = ({ directus, children }: AuthProviderProps)
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthContext.Provider
|
<AuthContext.Provider
|
||||||
value={{ isAuthenticated, user, login, loading, logout, updateUser, token }}
|
value={{ isAuthenticated, user, login, register, loading, logout, updateUser, token }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</AuthContext.Provider>
|
</AuthContext.Provider>
|
||||||
|
|||||||
@ -39,7 +39,6 @@ function MapEventListener(props: MapEventListenerProps) {
|
|||||||
// for refreshing map on resize (needs to be implemented)
|
// for refreshing map on resize (needs to be implemented)
|
||||||
const mapDivRef = React.createRef();
|
const mapDivRef = React.createRef();
|
||||||
|
|
||||||
/** This is a description of the foo function. */
|
|
||||||
function UtopiaMap({
|
function UtopiaMap({
|
||||||
height = "500px",
|
height = "500px",
|
||||||
width = "100%",
|
width = "100%",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import TitleCard from '../TitleCard'
|
import {TitleCard} from '../Templates/TitleCard'
|
||||||
import InputText from '../Input/InputText'
|
import InputText from '../Input/InputText'
|
||||||
import TextAreaInput from '../Input/TextAreaInput'
|
import TextAreaInput from '../Input/TextAreaInput'
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|||||||
27
src/Components/Templates/CardPage.tsx
Normal file
27
src/Components/Templates/CardPage.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import Subtitle from "./Typography/Subtitle"
|
import Subtitle from "../Typography/Subtitle"
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
|
||||||
interface TitleCardProps {
|
interface TitleCardProps {
|
||||||
@ -9,7 +9,7 @@ interface TitleCardProps {
|
|||||||
TopSideButtons?: any
|
TopSideButtons?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
function TitleCard({title, children, topMargin, TopSideButtons} : TitleCardProps){
|
export function TitleCard({title, children, topMargin, TopSideButtons} : TitleCardProps){
|
||||||
return(
|
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")}>
|
<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
|
|
||||||
2
src/Components/Templates/index.tsx
Normal file
2
src/Components/Templates/index.tsx
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export {CardPage} from './CardPage'
|
||||||
|
export {TitleCard} from './TitleCard'
|
||||||
@ -3,6 +3,8 @@ export {AppShell, Content, SideBar} from "./Components/AppShell"
|
|||||||
export {AuthProviderDirectus, useAuthDirectus} from "./Components/Auth"
|
export {AuthProviderDirectus, useAuthDirectus} from "./Components/Auth"
|
||||||
export {Settings} from './Components/Profile'
|
export {Settings} from './Components/Profile'
|
||||||
export {Quests, Modal} from './Components/Gaming'
|
export {Quests, Modal} from './Components/Gaming'
|
||||||
|
export {TitleCard, CardPage} from './Components/Templates'
|
||||||
|
|
||||||
import "./index.css"
|
import "./index.css"
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user