fixed note editor, dropdown is suck use modal instead

This commit is contained in:
Nomi Nonsense (Nonszy) 2024-03-17 21:05:02 +07:00
parent 7ff1b1f81d
commit e66eeb961b
2 changed files with 117 additions and 13 deletions

View File

@ -7,6 +7,7 @@ import EvoDropDown from "../forms/EvoDropDown";
import Button from "../forms/Button"; import Button from "../forms/Button";
import { pitch } from "../../data/melodies"; import { pitch } from "../../data/melodies";
import { PatchPiezoMusic } from "../../controllers/BoardController"; import { PatchPiezoMusic } from "../../controllers/BoardController";
import SearchItemModal from "../modals/SearchItemModal";
function getNoteItems () { function getNoteItems () {
const pitches = Object.keys(pitch); const pitches = Object.keys(pitch);
@ -45,6 +46,7 @@ function NoteItem ({note, index, parentIndex}: { note: string, index: number, pa
} }
return ( return (
<>
<button <button
className="min-w-40 h-40 transition border group border-border rounded-lg animate-size-fade-in relative" className="min-w-40 h-40 transition border group border-border rounded-lg animate-size-fade-in relative"
> >
@ -65,13 +67,22 @@ function NoteItem ({note, index, parentIndex}: { note: string, index: number, pa
<div className="text-xl"> <div className="text-xl">
{note} {note}
</div> </div>
<EvoDropDown.Menu {/* <EvoDropDown.Menu
className="!w-44 top-0 h-40 z-30 overflow-y-scroll v-scrollbar left-2" className="!w-44 top-0 h-40 z-30 overflow-y-scroll v-scrollbar left-2"
appear={dropAppear} appear={dropAppear}
items={noteItems} items={noteItems}
onValueChange={handleChange} onValueChange={handleChange}
/> /> */}
</button> </button>
{dropAppear == true && <SearchItemModal
name="Piezo"
items={noteItems}
initItem={{ name: note.replace("S", "#"), value: note.replace("S", "#") }}
onValueChange={handleChange}
onClose={toggleDropdown}
/>}
</>
) )
} }
@ -84,23 +95,32 @@ function NotePlus ({ parentIndex }: { parentIndex: number }) {
const handleAddNote = (item: { name: string, value: any }) => { const handleAddNote = (item: { name: string, value: any }) => {
addNote(parentIndex, item.value); addNote(parentIndex, item.value);
setApper(false);
} }
return ( return (
<>
<button className="border border-border bg-secondary-solid rounded-lg min-w-40 h-40" onClick={toggleDropdown}> <button className="border border-border bg-secondary-solid rounded-lg min-w-40 h-40" onClick={toggleDropdown}>
<i className="bi bi-plus text-2xl"></i> <i className="bi bi-plus text-2xl"></i>
<EvoDropDown.Menu {/* <EvoDropDown.Menu
className="!w-32 top-0 h-56 z-30 overflow-y-scroll v-scrollbar" className="!w-32 top-0 h-56 z-30 overflow-y-scroll v-scrollbar"
appear={dropAppear} appear={dropAppear}
items={noteItems} items={noteItems}
onValueChange={handleAddNote} onValueChange={handleAddNote}
/> /> */}
</button> </button>
{dropAppear == true && <SearchItemModal
name="Piezo"
items={noteItems}
onValueChange={handleAddNote}
onClose={toggleDropdown}
/>}
</>
) )
} }
function PiezoEditor ({ piezo, index }: { piezo: PiezoMusic, index: number }) { function PiezoEditor ({ piezo, index }: { piezo: PiezoMusic, index: number }) {
const { setName, setPin, setBeat, setTempo } = usePiezoMusic(); const { setName, setPin, setBeat, setTempo, removePiezo } = usePiezoMusic();
const beatsItem = [ const beatsItem = [
{ {
@ -123,6 +143,9 @@ function PiezoEditor ({ piezo, index }: { piezo: PiezoMusic, index: number }) {
const initBeatItem = beatsItem.find((item) => item.value == piezo.beats); const initBeatItem = beatsItem.find((item) => item.value == piezo.beats);
const exportJson = () => {
}
const handle = { const handle = {
changeName: (e: ChangeEvent<HTMLInputElement | null>) => { changeName: (e: ChangeEvent<HTMLInputElement | null>) => {
setName(index, e.target.value); setName(index, e.target.value);
@ -137,13 +160,20 @@ function PiezoEditor ({ piezo, index }: { piezo: PiezoMusic, index: number }) {
const tempo = Number.parseInt(e.target.value); const tempo = Number.parseInt(e.target.value);
setTempo(index, tempo); setTempo(index, tempo);
}, },
remove: () => {
removePiezo(index);
},
play: () => { play: () => {
PatchPiezoMusic(piezo); PatchPiezoMusic(piezo);
} },
export: exportJson
} }
return ( return (
<div className="flex flex-col gap-5 bg-secondary border border-border rounded-lg p-5 animate-size-fade-in"> <div className="flex flex-col gap-5 bg-secondary border border-border rounded-lg p-5 animate-size-fade-in relative">
<button className="ms-auto absolute -right-24 top-1/2 -translate-y-1/2 bg-finn hover:bg-secondary transition border border-border rounded-lg px-5" onClick={handle.remove}>
<i className="bi bi-dash text-3xl"></i>
</button>
<div className="flex flex-row justify-between"> <div className="flex flex-row justify-between">
<div className="flex flex-row gap-3"> <div className="flex flex-row gap-3">
<Input <Input
@ -174,7 +204,7 @@ function PiezoEditor ({ piezo, index }: { piezo: PiezoMusic, index: number }) {
/> />
</div> </div>
<div className="flex flex-row gap-3"> <div className="flex flex-row gap-3">
<Button.Secondary className="!py-0 !px-6 flex items-center gap-3"> <Button.Secondary className="!py-0 !px-6 flex items-center gap-3" onClick={exportJson}>
<div className="text-sm">Export</div> <div className="text-sm">Export</div>
<i className="bi bi-upload text-sm"></i> <i className="bi bi-upload text-sm"></i>
</Button.Secondary> </Button.Secondary>

View File

@ -0,0 +1,74 @@
import { ChangeEvent, useEffect, useState } from "react";
import EvoInput from "../forms/EvoInput";
import Input from "../forms/Input";
type EvoDropDownItem = {
name: string,
value: any
}
interface SearchItemModalProps {
className?: string;
name?: string;
items: EvoDropDownItem[];
initItem?: EvoDropDownItem;
onValueChange?: (item: EvoDropDownItem) => void;
onClose?: () => void
}
export default function SearchItemModal ({ className, items, name, initItem, onClose, onValueChange }: SearchItemModalProps) {
const [filteredItems, setItems] = useState<EvoDropDownItem[]>(items);
const [currentItem, setItem] = useState<EvoDropDownItem>(initItem || items[0]);
const [searchVal, setSearch] = useState<string>("");
const handleSearch = (e: ChangeEvent<HTMLInputElement | null>) => {
setSearch(e.target.value);
}
useEffect(() => {
if (searchVal.length > 0) {
const filter = items.filter(item => item.name.toLocaleLowerCase().includes(searchVal.toLowerCase()));
setItems(filter);
}
else {
setItems(items);
}
}, [searchVal])
return (
<div className={`fixed left-0 top-0 bg-finn w-screen h-screen z-50 ${className}`}>
<div className="bg-black border border-border rounded-lg absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 h-96 w-96 p-3 flex flex-col justify-items-start">
<button className="p-1 absolute right-2 top-2" onClick={onClose}>
<i className="bi bi-x text-3xl"></i>
</button>
<header className="text-left">
<h1 className="text-2xl font-bold font-poppins px-2 py-4">{name}</h1>
<Input
className="w-full mb-3"
name="Search"
placeholder="Search..."
value={searchVal}
onChange={handleSearch}
/>
</header>
<div className="overflow-y-scroll flex-grow flex flex-col">
{filteredItems.map((item) => (
<button
className="py-2 px-3 flex justify-between items-center bg-transparent bg-opacity-100 hover:bg-indigo-300 hover:bg-opacity-20 rounded-md"
onClick={() => {
setItem(item);
if (onValueChange) onValueChange(item)}
}
>
<div className="text-left text-sm">
{item.name}
</div>
{currentItem.value == item.value && <div className="rounded-full bg-white w-2 h-2"></div>}
</button>
))}
</div>
</div>
</div>
)
}