custom popups are basicly working 🍄

This commit is contained in:
Anton 2023-08-22 14:54:57 +02:00
parent d6e780436f
commit 6bd062c1b3
15 changed files with 157 additions and 113 deletions

View File

@ -1,7 +1,7 @@
import {useState, useRef} from 'react'
import {Link} from 'react-router-dom'
import ErrorText from '../Typography/ErrorText'
import InputText from '../Input/InputText'
import {TextInput} from '../Input/TextInput'
import * as React from 'react'
export function LoginPage(){
@ -44,9 +44,9 @@ export function LoginPage(){
<div className="tw-mb-4">
<InputText type="email" defaultValue={loginObj.emailId} containerStyle="tw-mt-4" labelTitle="E-Mail" updateFormValue={(v) => updateFormValue(v)}/>
<TextInput type="email" defaultValue={loginObj.emailId} containerStyle="tw-mt-4" labelTitle="E-Mail" updateFormValue={(v) => updateFormValue(v)}/>
<InputText defaultValue={loginObj.password} type="password" containerStyle="tw-mt-4" labelTitle="Password" updateFormValue={(v) => updateFormValue(v)}/>
<TextInput defaultValue={loginObj.password} type="password" containerStyle="tw-mt-4" labelTitle="Password" updateFormValue={(v) => updateFormValue(v)}/>
</div>

View File

@ -1,7 +1,7 @@
import { useState, useRef } from 'react'
import { Link } from 'react-router-dom'
import ErrorText from '../Typography/ErrorText'
import InputText from '../Input/InputText'
import {TextInput} from '../Input/TextInput'
import * as React from 'react'
export function SignupPage() {
@ -45,13 +45,9 @@ export function SignupPage() {
<form onSubmit={(e) => submitForm(e)}>
<div className="mb-4">
<InputText defaultValue={registerObj.name} containerStyle="tw-mt-4" labelTitle="Name" updateFormValue={updateFormValue} />
<InputText defaultValue={registerObj.emailId} containerStyle="tw-mt-4" labelTitle="E-Mail" updateFormValue={updateFormValue} />
<InputText defaultValue={registerObj.password} type="password" containerStyle="tw-mt-4" labelTitle="Password" updateFormValue={updateFormValue} />
<TextInput defaultValue={registerObj.name} containerStyle="tw-mt-4" labelTitle="Name" updateFormValue={updateFormValue} />
<TextInput defaultValue={registerObj.emailId} containerStyle="tw-mt-4" labelTitle="E-Mail" updateFormValue={updateFormValue} />
<TextInput defaultValue={registerObj.password} type="password" containerStyle="tw-mt-4" labelTitle="Password" updateFormValue={updateFormValue} />
</div>
<ErrorText styleClass="tw-mt-8">{errorMessage}</ErrorText>

View File

@ -1,44 +0,0 @@
import { useEffect, useState } from "react"
import * as React from "react"
type InputTextProps = {
labelTitle?: string;
labelStyle?: string;
type?: string;
dataField?: string;
containerStyle?: string;
defaultValue: string;
placeholder?: string;
updateFormValue?: (value: string ) => void;
}
function InputText({labelTitle, labelStyle, type, dataField, containerStyle, defaultValue, placeholder, updateFormValue} : InputTextProps){
const [value, setValue] = useState<string>(defaultValue)
useEffect(() => {
setValue(defaultValue)
}, [defaultValue])
const updateInputValue = (val : string) => {
setValue(val)
if(updateFormValue)
updateFormValue(val)
}
return(
<div className={`tw-form-control tw-w-full ${containerStyle}`}>
{labelTitle ? <label className="tw-label">
<span className={"tw-label-text tw-text-base-content " + labelStyle}>{labelTitle}</span>
</label>
: " "}
<input type={type || "text"} name={dataField} value={value} placeholder={placeholder || ""} onChange={(e) => updateInputValue(e.target.value)}className="tw-input tw-input-bordered tw-w-full " />
</div>
)
}
export default InputText

View File

@ -15,30 +15,20 @@ type TextAreaProps = {
function TextAreaInput({ labelTitle, dataField, labelStyle, containerStyle, inputStyle, defaultValue, placeholder, updateFormValue }: TextAreaProps) {
const [value, setValue] = useState<string>(defaultValue)
useEffect(() => {
setValue(defaultValue)
}, [defaultValue])
export function TextAreaInput({ labelTitle, dataField, labelStyle, containerStyle, inputStyle, defaultValue, placeholder, updateFormValue }: TextAreaProps) {
const updateInputValue = (val: string) => {
setValue(val)
if (updateFormValue)
updateFormValue(val)
}
return (
<div className={`tw-form-control tw-w-full ${containerStyle ? containerStyle : ""}`}>
{labelTitle ? <label className="tw-label">
<span className={"tw-label-text tw-text-base-content " + labelStyle}>{labelTitle}</span>
</label> : ""}
<textarea value={value} name={dataField} className={`tw-textarea tw-textarea-bordered tw-w-full tw-leading-5 ${inputStyle ? inputStyle : ""}`} placeholder={placeholder || ""} onChange={(e) => updateInputValue(e.target.value)}></textarea>
<textarea defaultValue={defaultValue} name={dataField} className={`tw-textarea tw-textarea-bordered tw-w-full tw-leading-5 ${inputStyle ? inputStyle : ""}`} placeholder={placeholder || ""} onChange={(e) => updateFormValue&& updateFormValue(e.target.value)}></textarea>
</div>
)
}
export default TextAreaInput

View File

@ -0,0 +1,29 @@
import { useEffect, useState } from "react"
import * as React from "react"
type InputTextProps = {
labelTitle?: string;
labelStyle?: string;
type?: string;
dataField?: string;
containerStyle?: string;
defaultValue?: string;
placeholder?: string;
updateFormValue?: (value: string ) => void;
}
export function TextInput({labelTitle, labelStyle, type, dataField, containerStyle, defaultValue, placeholder, updateFormValue} : InputTextProps){
return(
<div className={`tw-form-control tw-w-full ${containerStyle}`}>
{labelTitle ? <label className="tw-label">
<span className={"tw-label-text tw-text-base-content " + labelStyle}>{labelTitle}</span>
</label>
: " "}
<input type={type || "text"} name={dataField} defaultValue={defaultValue} placeholder={placeholder || ""} onChange={(e) => updateFormValue&& updateFormValue(e.target.value)}className="tw-input tw-input-bordered tw-w-full " />
</div>
)
}

View File

@ -0,0 +1,2 @@
export {TextAreaInput} from "./TextAreaInput"
export {TextInput} from "./TextInput"

View File

@ -0,0 +1,7 @@
import * as React from 'react'
export const ItemForm = ({ children }:{children?: React.ReactNode}) => {
return (
<div>{children}</div>
)
}

View File

@ -0,0 +1,7 @@
import * as React from 'react'
export const ItemView = ({ children }:{children?: React.ReactNode}) => {
return (
<div>{children}</div>
)
}

View File

@ -7,7 +7,7 @@ import { useTags } from './hooks/useTags'
import { useAddItem, useItems, useResetItems } from './hooks/useItems'
import { useEffect, useState } from 'react'
import { useAddLayer } from './hooks/useLayers'
import ItemFormPopup, { ItemFormPopupProps } from './Subcomponents/ItemFormPopup'
import { ItemFormPopupProps, ItemFormPopup } from './Subcomponents/ItemFormPopup'
export const Layer = (props: LayerProps) => {
@ -86,14 +86,38 @@ export const Layer = (props: LayerProps) => {
}
return (
<Marker icon={MarkerIconFactory(props.markerShape, color1, color2, props.markerIcon)} key={place.id} position={[place.position.coordinates[1], place.position.coordinates[0]]}>
{
(props.children && React.Children.toArray(props.children).some(e => React.isValidElement(e) && typeof e.type !== "string" && e.type.name === "ItemForm") ?
React.Children.toArray(props.children).map((child) =>
React.isValidElement(child) && typeof child.type !== "string" && child.type.name === "ItemView" ?
<ItemViewPopup key={place.id} item={place} setItemFormPopup={props.setItemFormPopup} >{child}</ItemViewPopup>
: ""
)
:
<>
<ItemViewPopup item={place} setItemFormPopup={props.setItemFormPopup} />
</>)
}
</Marker>
);
})
}
{props.children}
{props.itemFormPopup && props.itemFormPopup.layer.name == props.name &&
<ItemFormPopup position={props.itemFormPopup.position} layer={props.itemFormPopup.layer} setItemFormPopup={setItemFormPopup} item={props.itemFormPopup.item} api={props.api} />
{props.itemFormPopup && props.itemFormPopup.layer!.name == props.name &&
(props.children && React.Children.toArray(props.children).some(e => React.isValidElement(e) && typeof e.type !== "string" && e.type.name === "ItemForm") ?
React.Children.toArray(props.children).map((child) =>
React.isValidElement(child) && typeof child.type !== "string" && child.type.name === "ItemForm" ?
<ItemFormPopup key={props.setItemFormPopup?.name} position={props.itemFormPopup!.position} layer={props.itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={props.itemFormPopup!.item} api={props.api} >{child}</ItemFormPopup>
: ""
)
:
<>
<ItemFormPopup position={props.itemFormPopup!.position} layer={props.itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={props.itemFormPopup!.item} api={props.api} />
</>)
}
</>
)

View File

@ -1,21 +1,25 @@
import * as React from 'react'
import { LatLng } from 'leaflet'
import { Popup as LeafletPopup, useMap } from 'react-leaflet'
import { useEffect, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import { useAddItem, useUpdateItem } from '../hooks/useItems'
import { Geometry, LayerProps, Item, ItemsApi } from '../../../types'
import TextAreaInput from '../../Input/TextAreaInput'
import InputText from '../../Input/InputText'
import {TextAreaInput} from '../../Input/TextAreaInput'
import {TextInput} from '../../Input/TextInput'
export interface ItemFormPopupProps {
position: LatLng,
layer: LayerProps,
item?: Item,
api?: ItemsApi<any>,
children?: React.ReactNode,
setItemFormPopup: React.Dispatch<React.SetStateAction<any>>
}
export default function ItemFormPopup(props: ItemFormPopupProps) {
export function ItemFormPopup(props: ItemFormPopupProps) {
const formRef = useRef<HTMLFormElement>(null);
const [spinner, setSpinner] = useState(false);
@ -25,9 +29,8 @@ export default function ItemFormPopup(props: ItemFormPopupProps) {
const handleSubmit = async (evt: any) => {
const formItem: Item = {} as Item;
Array.from(evt.target).forEach((input: HTMLFormElement) => {
Array.from(evt.target).forEach((input: HTMLInputElement) => {
if (input.name) {
console.log(input.name + ": " + input.value);
formItem[input.name] = input.value;
}
});
@ -57,17 +60,41 @@ export default function ItemFormPopup(props: ItemFormPopupProps) {
}
const resetPopup = () => {
if (formRef.current) {
formRef.current.reset();
}
}
useEffect(() => {
resetPopup();
}, [props.position])
return (
<LeafletPopup minWidth={275} maxWidth={275} autoPanPadding={[20, 5]}
eventHandlers={{
// remove: resetPopup
remove: () => {
setTimeout(function() {
resetPopup()
}, 100);
}
}}
position={props.position}>
<form onSubmit={e => handleSubmit(e)}>
<form ref={formRef} onReset={resetPopup} onSubmit={e => handleSubmit(e)}>
<div className='tw-flex tw-justify-center'><b className="tw-text-xl tw-font-bold">New {props.layer.name}</b></div>
<InputText type="text" placeholder="Name" dataField="name" defaultValue={props.item? props.item.name : ""} />
{props.children ? props.children :
<>
<TextInput type="text" placeholder="Name" dataField="name" defaultValue={props.item ? props.item.name : ""} />
<TextAreaInput placeholder="Text" dataField="text" defaultValue={props.item ? props.item.text : ""} inputStyle='tw-h-40 tw-mt-5' />
<div className='tw-flex tw-justify-center'><button className={spinner ? 'tw-btn tw-loading tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'}>Save</button></div>
</>
}
<div className='tw-flex tw-justify-center'>
<button className={spinner ? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center' : 'tw-btn tw-mt-5 tw-place-self-center'} type='submit'>{spinner ? <span className="tw-loading tw-loading-spinner"></span> : 'Save'}</button>
</div>
</form>
</LeafletPopup>
)

View File

@ -8,6 +8,7 @@ import { TextView } from './TextView'
export interface ItemViewPopupProps {
item: Item,
children?: React.ReactNode;
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
}
@ -20,12 +21,13 @@ export const ItemViewPopup = (props: ItemViewPopupProps) => {
<LeafletPopup maxHeight={377} minWidth={275} maxWidth={275} autoPanPadding={[20, 5]}>
<div>
<HeaderView item={props.item} setItemFormPopup={props.setItemFormPopup} />
{props.children ? props.children :
<div className='tw-overflow-y-auto tw-max-h-72'>
{item.start && item.end &&
<StartEndView item={props.item} />
}
<StartEndView item={props.item} />}
<TextView item={props.item} />
</div>
}
</div>
</LeafletPopup>
)

View File

@ -1,3 +1,6 @@
export { UtopiaMap } from './UtopiaMap'
export { UtopiaMap } from './UtopiaMap';
export { Layer } from './Layer';
export { Tags } from "./Tags";
export {ItemViewPopup} from './Subcomponents/ItemViewPopup';
export {ItemForm} from './ItemForm';
export {ItemView} from './ItemView';

View File

@ -1,7 +1,7 @@
import { useEffect, useState } from 'react'
import {TitleCard} from '../Templates/TitleCard'
import InputText from '../Input/InputText'
import TextAreaInput from '../Input/TextAreaInput'
import {TextInput} from '../Input/TextInput'
import {TextAreaInput} from '../Input/TextAreaInput'
import { toast } from 'react-toastify';
import {useNavigate} from 'react-router-dom'
import * as React from 'react'
@ -62,7 +62,7 @@ export function Settings({useAuth}) {
<div className="tw-grid tw-grid-cols-1 tw-md:grid-cols-2 tw-gap-6">
<InputText placeholder="Name" defaultValue={user?.first_name ? user.first_name : ""} updateFormValue={(v) => setName(v)} />
<TextInput placeholder="Name" defaultValue={user?.first_name ? user.first_name : ""} updateFormValue={(v) => setName(v)} />
</div>
<div className="tw-grid tw-grid-cols-1 tw-md:grid-cols-1 tw-gap-6 tw-pt-6 tw-pb-6">
<TextAreaInput placeholder="About me, Contact, #Tags, ..." defaultValue={user?.description ? user.description : ""} updateFormValue={(v) => setText(v)} inputStyle='tw-h-64'/>
@ -71,8 +71,8 @@ export function Settings({useAuth}) {
<div className="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-6">
<InputText type='email' placeholder="E-Mail" defaultValue={user?.email ? user.email : ""} updateFormValue={(v) => setEmail(v)} />
<InputText type='password' placeholder="new Password" defaultValue={user?.password ? user.password : ""} updateFormValue={(v) => {
<TextInput type='email' placeholder="E-Mail" defaultValue={user?.email ? user.email : ""} updateFormValue={(v) => setEmail(v)} />
<TextInput type='password' placeholder="new Password" defaultValue={user?.password ? user.password : ""} updateFormValue={(v) => {
setPassword(v);
setPasswordChanged(true);
}} />

View File

@ -1,9 +1,10 @@
export { UtopiaMap, Layer, Tags } from './Components/Map/index';
export { UtopiaMap, Layer, Tags, ItemViewPopup, ItemForm, ItemView } from './Components/Map/index';
export {AppShell, Content, SideBar} from "./Components/AppShell"
export {AuthProvider, useAuth, LoginPage, SignupPage} from "./Components/Auth"
export {Settings} from './Components/Profile'
export {Quests, Modal} from './Components/Gaming'
export {TitleCard, CardPage} from './Components/Templates'
export {TextInput, TextAreaInput} from './Components/Input'
import "./index.css"

View File

@ -12,7 +12,7 @@ export interface UtopiaMapProps {
export interface LayerProps {
data?: Item[],
children?: React.ReactNode
children?: React.ReactNode,
name: string,
menuIcon: string,
menuColor: string,
@ -28,16 +28,16 @@ export interface LayerProps {
export class Item {
id: string | number;
date_created?: string;
date_updated?: string | null;
name: string;
text: string;
position: Geometry;
[key: string]: any;
date_created?: string;
date_updated?: string | null;
start?: string;
end?: string;
tags?: number[];
api?: ItemsApi<any>
api?: ItemsApi<any>;
[key: string]: any;
constructor(id:string|number,name:string,text:string,position:Geometry, layer?: LayerProps, api?: ItemsApi<any>){
this.id = id;
this.name = name;