Newer
Older
NocodeToolOnRDL / src / components / property / property.tsx
@Sakoda2269 Sakoda2269 10 days ago 5 KB useMemoを撤廃
import type { ComponentActions, ComponentState } from "../../hooks/useComponent";
import { ComponentType } from "../../types/component";
import type { Component } from "../../types/component";
import { useEffect, useState } from "react";
import { TextProperty } from "./textProperties";
import { ButtonProperty } from "./buttonProperties";
import type { Table } from "../../types/table";
import { TableProperty } from "./tableProperties";
import type { Screen } from "../../types/screen";
import { ActiveTab } from "../../constants/activeTab";

interface PropertyProps {
    componentState: ComponentState,
    tables: Table[]
    screens: Screen[],
    curScreenIndex: number,
    componentActions: ComponentActions,
}


export default function Property({
    componentState,
    tables,
    screens,
    curScreenIndex,
    componentActions
}: PropertyProps) {

    const { selectingComponent, selectingComponentIndex } = componentState

    if (selectingComponent === null)
        return <div></div>

    return <ComponentPropertyArea
        component={selectingComponent}
        tables={tables}
        index={selectingComponentIndex}
        screens={screens}
        curScreenIndex={curScreenIndex}
        componentActions={componentActions}
    />;
}

interface ComponentPropertyAreaProps {
    component: Component
    index: number
    tables: Table[]
    screens: Screen[]
    curScreenIndex: number
    componentActions: ComponentActions,
}

function ComponentPropertyArea({
    component,
    index,
    tables,
    screens,
    curScreenIndex,
    componentActions
}: ComponentPropertyAreaProps) {
    
    const componentName = component.name;
    const [name, setName] = useState<string>(componentName);
    const [activeTab, setActiveTab] = useState<ActiveTab>(ActiveTab.GENERAL);

    useEffect(() => {
        // eslint-disable-next-line react-hooks/set-state-in-effect
        setName(componentName);
    }, [componentName])

    const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setName(e.target.value);
    }

    function nameValidate() {
        if (!name.trim()) return false;
        return true;
    }

    const handleNameConfirm = (e: React.FocusEvent<HTMLInputElement, Element>) => {
        if (!nameValidate()) {
            setName(component.name);
            return;
        }
        componentActions.updateComponent(index, { ...component, name: e.target.value })
        // componentActions.updateConfirm({ ...component, name: e.target.value });
    }

    return (
        <div className="flex-col flex h-full">
            <nav className="flex w-full border-b-1">
                <button
                    className={`flex-1 text-sm py-4 px-1 block hover:text-blue-500 focus:outline-none ${activeTab == ActiveTab.GENERAL ? "text-blue-500 border-b-2 font-medium border-blue-500" : "text-gray-600"}`}
                    onClick={() => setActiveTab(ActiveTab.GENERAL)}
                >
                    一般
                </button>
                <button
                    className={`flex-1 text-sm py-4 px-1 block hover:text-blue-500 focus:outline-none ${activeTab == ActiveTab.STYLE ? "text-blue-500 border-b-2 font-medium border-blue-500" : "text-gray-600"}`}
                    onClick={() => setActiveTab(ActiveTab.STYLE)}
                >
                    スタイル
                </button>
                <button
                    className={`flex-1 text-sm py-4 px-1 block hover:text-blue-500 focus:outline-none ${activeTab == ActiveTab.ACTION ? "text-blue-500 border-b-2 font-medium border-blue-500" : "text-gray-600"}`}
                    onClick={() => setActiveTab(ActiveTab.ACTION)}
                >
                    アクション
                </button>
            </nav>
            <div className="flex-col mt-8 ml-4 mr-4 flex h-full overflow-y-auto">
                {activeTab === 0 && <div className="mb-4">
                    <label className="block font-medium text-gray-700 mb-2">
                        id
                    </label>
                    <input
                        type="text"
                        value={name}
                        onChange={(e) => handleNameChange(e)}
                        onBlur={(e) => handleNameConfirm(e)}
                        onKeyDown={(e) => {
                            if (e.key === "Enter") {
                                e.preventDefault()
                                    ; (e.currentTarget as HTMLInputElement).blur()
                            }
                        }}
                        className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
                    />
                </div>}
                {component.type === ComponentType.Text &&
                    <TextProperty
                        component={component}
                        activeTab={activeTab}
                        index={index}
                        componentActions={componentActions}
                        updateComponent={componentActions.updateComponent}
                    />
                }
                {component.type === ComponentType.Button &&
                    <ButtonProperty
                        component={component}
                        activeTab={activeTab}
                        index={index}
                        screens={screens}
                        curScreenIndex={curScreenIndex}
                        componentActions={componentActions}
                        tables={tables}
                    />
                }
                {component.type === ComponentType.Table &&
                    <TableProperty
                        component={component}
                        tables={tables}
                        activeTab={activeTab}
                        index={index}
                        updateComponent={componentActions.updateComponent}
                    />
                }
            </div>
        </div>
    )
}