homemanager-fe/src/components/house-planner/PlannerPropertyPanel.vue

154 lines
4.2 KiB
Vue

<template>
<PlannerSidebar title="Properties">
<div
class="bg-white-50 flex flex-col"
v-if="selectedObject && applicableProperties"
>
<div
class="grid grid-cols-2 px-2 py-2"
v-for="prop of applicableProperties.properties"
>
<label :for="`${prop.key}-${selectedObject.id}`">{{
prop.title
}}</label>
<input
v-if="prop.type === 'string'"
:id="`${prop.key}-${selectedObject.id}`"
type="text"
:value="selectedObject[prop.key as keyof typeof selectedObject]"
@input="updateProp(prop, ($event.target as HTMLInputElement)?.value)"
/>
<input
v-else-if="prop.type === 'color'"
:id="`${prop.key}-${selectedObject.id}`"
type="color"
:value="selectedObject[prop.key as keyof typeof selectedObject]"
@change="updateProp(prop, ($event.target as HTMLInputElement)?.value)"
/>
<input
v-else-if="prop.type === 'number'"
:id="`${prop.key}-${selectedObject.id}`"
type="number"
:value="selectedObject[prop.key as keyof typeof selectedObject]"
@input="updateProp(prop, ($event.target as HTMLInputElement)?.value)"
/>
<input
v-else-if="prop.type === 'boolean'"
:id="`${prop.key}-${selectedObject.id}`"
type="checkbox"
:checked="(selectedObject[prop.key as keyof typeof selectedObject] as boolean)"
@input="
updateProp(prop, ($event.target as HTMLInputElement)?.checked)
"
/>
<select
v-else-if="prop.type === 'select'"
:id="`${prop.key}-${selectedObject.id}`"
:value="selectedObject[prop.key as keyof typeof selectedObject]"
@input="updateProp(prop, ($event.target as HTMLInputElement)?.value)"
>
<option v-for="option of prop.options" :value="option.value">
{{ option.title }}
</option>
</select>
</div>
</div>
</PlannerSidebar>
</template>
<script setup lang="ts">
import PlannerSidebar from './PlannerSidebar.vue';
import { Layer } from '../../modules/house-planner/interfaces';
import {
ObjectProperties,
ObjectProperty,
} from './interfaces/properties.interfaces';
import { computed } from 'vue';
const props = defineProps<{
layers: Layer[];
}>();
const emit = defineEmits<{
(
e: 'update',
layerId: number,
objectId: number,
key: string,
value: unknown
): void;
}>();
const commonProps: ObjectProperty[] = [
{ key: 'name', title: 'Name', type: 'string' },
{ key: 'visible', title: 'Visible', type: 'boolean', groupable: true },
];
const lineProps: ObjectProperty[] = [
...commonProps,
{ key: 'width', title: 'Line Width', type: 'number', groupable: true },
{ key: 'color', title: 'Color', type: 'color', groupable: true },
{
key: 'lineCap',
title: 'Line Cap',
type: 'select',
groupable: true,
options: [
{ value: undefined, title: '' },
{ value: 'butt', title: 'Butt' },
{ value: 'round', title: 'Round' },
{ value: 'square', title: 'Square' },
],
},
{ key: 'closed', title: 'Closed', type: 'boolean', groupable: true },
];
const objectTypeProperties: ObjectProperties[] = [
{
type: 'line',
properties: lineProps,
},
{
type: 'curve',
properties: lineProps,
},
{
type: 'room',
properties: lineProps,
},
{
type: 'object',
properties: commonProps,
},
];
const currentLayer = computed(() =>
props.layers.find((layer) => layer.active && layer.visible)
);
// TODO multi edit
const selectedObject = computed(
() => currentLayer.value?.contents?.filter((obj) => obj.selected)[0]
);
const applicableProperties = computed(
() =>
selectedObject.value &&
objectTypeProperties.find(
(prop) => prop.type === selectedObject.value?.type
)
);
const updateProp = (prop: ObjectProperty, value: unknown) => {
if (!currentLayer.value || !selectedObject.value) return;
if (prop.type === 'number') value = parseFloat(value as string);
emit(
'update',
currentLayer.value!.id,
selectedObject.value!.id,
prop.key,
value
);
};
</script>