import { useState } from "react";
import type { Project } from "../types/project";
import type { Screen } from "../types/screen";
import type { UIData, Component, GeneralData, ButtonGeneralData, TextGeneralData, TextFieldGeneralData, TableGeneralData } from "../types/component";
import { ComponentType } from "../types/component";
import type { Table } from "../types/table";
function getInitialGeneralData(type: ComponentType): GeneralData {
switch (type) {
case ComponentType.Text:
return { text: "text" }
case ComponentType.Button:
return { text: "button" }
case ComponentType.TextField:
return { text: "text field" }
case ComponentType.Table:
return { referenceTableName: "", columns: [] }
}
}
export interface ProjectStates {
project: Project,
screens: Screen[],
tables: Table[]
}
export interface ProjectActions {
addScreen: (name: string) => void
updateScreen: (screen: Screen) => void
deleteScreen: (screenId: string) => void
addComponent: (screenId: string, type: ComponentType) => void
addComponents: (screenId: string, components: Component[]) => void
updateComponent: (screenId: string, component: Component) => void
moveComponent: (screenId: string, componentId: string, uiData: UIData) => void
deleteComponent: (screenIndex: number, componentIndex: number) => void
addTable: (table: Table) => void
updateTable: (table: Table) => void
deleteTable: (tableId: string) => void
}
export interface ProjectStatesAndActions {
projectStates: ProjectStates
projectActions: ProjectActions
}
export function useProject(initProject: Project = {
id: "",
title: "",
detail: "",
createdTime: "",
updatedTime: "",
screens: [
{
id: "screen1",
components: [],
index: 0,
name: "screen1",
projectId: ""
}
],
tables: []
}): ProjectStatesAndActions {
const [project, setProject] = useState<Project>(initProject);
const screens = project.screens;
const tables = project.tables;
const addScreen = (name: string) => {
const nextIndex = screens[screens.length - 1].index + 1;
const newScreenId = "screen" + nextIndex;
const newScreen: Screen = {
id: newScreenId,
components: [],
index: nextIndex,
name: name,
projectId: project.id
}
setProject(prev => ({ ...prev, screens: [...prev.screens, newScreen] }));
return newScreenId;
}
const deleteScreen = (screenId: string) => {
setProject(prev => ({ ...prev, screens: prev.screens.filter(s => s.id !== screenId) }));
}
const updateScreen = (screen: Screen) => {
setProject(prev => ({ ...prev, screens: prev.screens.map(s => s.id === screen.id ? screen : s) }));
}
const addComponent = (screenId: string, type: ComponentType) => {
const screen = screens.find(s => s.id === screenId);
if (!screen) {
return;
}
const nextIndex = screen.components.length > 0 ? screen.components[screen.components.length - 1].index + 1 : 0;
const uiData: UIData = {
posX: 100,
posY: 100,
width: 75,
height: 25
};
const newId = screen.id + "Widget" + nextIndex;
let newComponent: Component;
switch (type) {
case ComponentType.Button:
newComponent = {
id: newId,
name: newId,
type: type,
index: nextIndex,
screenId: screen.id,
generalData: getInitialGeneralData(type) as ButtonGeneralData,
style: {},
uiData: uiData,
}
break;
case ComponentType.Text:
newComponent = {
id: newId,
name: newId,
type: type,
index: nextIndex,
screenId: screen.id,
generalData: getInitialGeneralData(type) as TextGeneralData,
style: {},
uiData: uiData,
}
break;
case ComponentType.TextField:
newComponent = {
id: newId,
name: newId,
type: type,
index: nextIndex,
screenId: screen.id,
generalData: getInitialGeneralData(type) as TextFieldGeneralData,
style: {},
uiData: uiData,
}
break;
case ComponentType.Table:
newComponent = {
id: newId,
name: newId,
type: type,
index: nextIndex,
screenId: screen.id,
generalData: getInitialGeneralData(type) as TableGeneralData,
style: {},
uiData: uiData,
}
break;
}
setProject(prev => (
{
...prev,
screens: prev.screens.map((s, i) => s.id === screenId ? {
...prev.screens[i],
components: [...prev.screens[i].components, newComponent]
} : s)
}
))
}
const addComponents = (screenId: string, components: Component[]) => {
setProject(prev => (
{
...prev,
screens: prev.screens.map((s, i) => s.id === screenId ? {
...prev.screens[i],
components: [...prev.screens[i].components, ...components]
} : s)
}
))
}
const moveComponent = (screenId: string, componentId: string, uiData: UIData) => {
setProject(prev => (
{
...prev,
screens: prev.screens.map((s, i) => s.id === screenId ? {
...prev.screens[i],
components: prev.screens[i].components.map((c, i) => c.id === componentId ? {
...prev.screens[i].components[i],
uiData: uiData
} : c)
} : s)
}
))
}
const updateComponent = (screenId: string, component: Component) => {
setProject(prev => (
{
...prev,
screens: prev.screens.map((s, i) => s.id === screenId ? {
...prev.screens[i],
components: prev.screens[i].components.map(c => c.id === component.id ? component : c)
} : s)
}
))
}
const deleteComponent = (screenIndex: number, componentIndex: number) => {
setProject(prev => (
{
...prev,
screens: prev.screens.map((s, i) => i === screenIndex ? {
...prev.screens[i],
components: prev.screens[i].components.filter((_, i) => i !== componentIndex)
} : s)
}
))
}
const addTable = (table: Table) => {
setProject(prev => ({
...prev,
tables: [...prev.tables, table]
}))
}
const updateTable = (table: Table) => {
setProject(prev => ({
...prev,
tables: prev.tables.map(t => t.id === table.id ? table : t)
}));
}
const deleteTable = (tableId: string) => {
setProject(prev => ({
...prev,
tables: prev.tables.filter(table => table.id !== tableId)
}))
}
return {
projectStates: { project, screens, tables },
projectActions: {
addScreen,
updateScreen,
deleteScreen,
addComponent,
addComponents,
updateComponent,
moveComponent,
deleteComponent,
addTable,
updateTable,
deleteTable
}
}
}