Tabs and rich Text Editor in Profile Settings

This commit is contained in:
Anton Tranelis 2024-02-08 10:23:59 +01:00
parent a7b0be3c79
commit 31b131cea0
7 changed files with 963 additions and 7 deletions

876
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@
"@heroicons/react": "^2.0.17",
"@tanstack/react-query": "^5.17.8",
"@types/offscreencanvas": "^2019.7.1",
"@uiw/react-md-editor": "^4.0.3",
"axios": "^1.6.5",
"leaflet": "^1.9.4",
"leaflet.locatecontrol": "^0.79.0",
@ -57,6 +58,7 @@
"react-router-dom": "^6.16.0",
"react-string-replace": "^1.1.1",
"react-toastify": "^9.1.3",
"rehype-sanitize": "^6.0.0",
"rehype-video": "^2.0.2",
"remark-breaks": "^4.0.0",
"tributejs": "^5.1.3",

View File

@ -0,0 +1,42 @@
import * as React from "react";
import MDEditor from '@uiw/react-md-editor';
import rehypeSanitize from "rehype-sanitize";
import { useEffect } from "react";
export function TextEditor({ value, updateFormValue }: { value: string, updateFormValue: (string) => void }) {
useEffect(() => {
setHeightFromSourceToTarget("wmde-markdown-color","w-md-editor-text-input");
}, [value])
return (
<div className="container">
<MDEditor
value={value}
onChange={(val) => updateFormValue(val)}
preview="edit"
height="100%"
previewOptions={{
rehypePlugins: [[rehypeSanitize]],
}}
/>
</div>
);
}
// TypeScript
const setHeightFromSourceToTarget = (sourceClassName: string, targetClassName: string): void => {
// Select the source element and get its height
const sourceElement = document.querySelector(`.${sourceClassName}`) as HTMLElement;
const height = sourceElement ? (sourceElement.clientHeight +10) + 'px' : '0'; // Convert to string to use in style
// Select all target elements
const targetElements = document.querySelectorAll(`.${targetClassName}`);
// Set the height of all target elements to match the source element's height
targetElements.forEach((element) => {
(element as HTMLElement).style.height = height;
});
}

View File

@ -15,6 +15,8 @@ import { randomColor } from '../../Utils/RandomColor';
import { useNavigate } from 'react-router-dom';
import { UserItem } from '../../types';
import { MapOverlayPage } from '../Templates';
import {TextEditor} from './Editor';
export function OverlayProfileSettings() {
@ -26,6 +28,8 @@ export function OverlayProfileSettings() {
const [avatar, setAvatar] = useState<string>("");
const [color, setColor] = useState<string>("");
const [activeTab, setActiveTab] = useState<number>(1);
const [crop, setCrop] = useState<Crop>();
const [image, setImage] = useState<string>("");
@ -45,7 +49,7 @@ export function OverlayProfileSettings() {
setName(user?.first_name ? user.first_name : "");
setText(user?.description ? user.description : "");
setAvatar(user?.avatar ? user?.avatar : ""),
setColor(user?.color ? user.color : "#aabbcc")
setColor(user?.color ? user.color : "#aabbcc")
}, [user])
const imgRef = React.useRef<HTMLImageElement>(null)
@ -208,9 +212,33 @@ export function OverlayProfileSettings() {
<TextInput placeholder="Name" defaultValue={user?.first_name ? user.first_name : ""} updateFormValue={(v) => setName(v)} containerStyle='tw-grow tw-ml-6 tw-my-auto ' />
</div>
<div className="tw-grid tw-grid-cols-1 tw-md:grid-cols-1 tw-gap-6 tw-pt-6 tw-pb-6 tw-grow">
<TextAreaInput placeholder="About me, Contact, #Tags, ..." defaultValue={user?.description ? user.description : ""} updateFormValue={(v) => setText(v)} containerStyle='tw-h-full' inputStyle='tw-h-full'/>
<div role="tablist" className="tw-tabs tw-tabs-lifted tw-mt-4">
<input type="radio" name="my_tabs_2" role="tab" className={`tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]`} aria-label="Text" checked={activeTab == 1 && true} onChange={() => setActiveTab(1)} />
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-border-[var(--fallback-bc,oklch(var(--bc)/0.2))] tw-rounded-box tw-h-[calc(100dvh-332px)]">
<TextEditor value={text} updateFormValue={(v) => setText(v)} ></TextEditor>
</div>
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab tw-min-w-[10em] [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Offers & Needs" checked={activeTab == 2 && true} onChange={() => setActiveTab(2)} />
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-pt-6 tw-h-[calc(100dvh-332px)]">
<textarea className="tw-textarea tw-textarea-bordered tw-w-full tw-mb-4 tw-h-32 " placeholder="Offers"></textarea>
<textarea className="tw-textarea tw-textarea-bordered tw-w-full tw-h-32 " placeholder="Needs"></textarea>
</div>
<input type="radio" name="my_tabs_2" role="tab" className="tw-tab [--tab-border-color:var(--fallback-bc,oklch(var(--bc)/0.2))]" aria-label="Contact" checked={activeTab == 3 && true} onChange={() => setActiveTab(3)} />
<div role="tabpanel" className="tw-tab-content tw-bg-base-100 tw-rounded-box tw-pt-6 tw-h-[calc(100dvh-332px)] tw-overflow-y-auto">
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='E-Mail ...'></input>
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Telefon ...'></input>
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Webpage ...'></input>
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Matrix ... '></input>
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Telegram ...'></input>
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Instagram ...'></input>
<input className='tw-input tw-mb-2 tw-input-bordered tw-w-full' placeholder='Twitter ...'></input>
</div>
</div>
</div>
<div className="tw-mt-2"><button className={loading ? " tw-loading tw-btn-disabled tw-btn tw-btn-primary tw-float-right" : "tw-btn tw-btn-primary tw-float-right"} onClick={() => onUpdateUser()}>Update</button></div>

View File

@ -62,4 +62,16 @@ input[type="file"] {
position: absolute;
transform: translate(8px, 8px);
}
.tw-tab-content .container {
height: 100%;
}
.w-md-editor-text {
height: 100%;
}
.w-md-editor-text-input {
min-height: 100%;
}

View File

@ -7,6 +7,8 @@ module.exports = {
theme: {
extend: {
zIndex: {
'3000': '3000',
'2000': '2000',
'1000': '1000',
'500': '500',
},

View File

@ -3,7 +3,7 @@
"outDir": "dist",
"module": "esnext",
"target": "es5",
"lib": ["es6", "dom", "es2016", "es2017", "es2020"],
"lib": ["es6", "dom","es2015", "es2016", "es2017", "es2020"],
"sourceMap": true,
"allowJs": false,
"jsx": "react",