107 lines
2.3 KiB
Vue
107 lines
2.3 KiB
Vue
<script setup lang="ts">
|
|
import "../assets/datatable.css";
|
|
|
|
import DataTable from "datatables.net-vue3";
|
|
import DataTablesCore from "datatables.net";
|
|
import "datatables.net-select";
|
|
import { PropType, ref } from "vue";
|
|
import RatingField from "./RatingField.vue";
|
|
import Restaurant from "../models/restaurant";
|
|
|
|
DataTable.use(DataTablesCore);
|
|
|
|
const props = defineProps({
|
|
data: { type: Array as PropType<Restaurant[]> },
|
|
});
|
|
|
|
const columns = [
|
|
{ data: "name", title: "Name" },
|
|
{
|
|
data: "tags",
|
|
title: "Tags",
|
|
render: {
|
|
_: "[, ]",
|
|
},
|
|
},
|
|
{ data: "average_rating", title: "" },
|
|
];
|
|
|
|
const table = ref<typeof DataTable>();
|
|
|
|
function onRowSelected(e, dt, type, indexes) {
|
|
if (indexes.length != 0 && props.data !== undefined) {
|
|
emit("restaurantSelected", props.data[indexes[0]]);
|
|
}
|
|
}
|
|
|
|
function deselectAll() {
|
|
table.value?.dt.rows({ selected: true }).deselect();
|
|
}
|
|
|
|
const emit = defineEmits({
|
|
restaurantSelected: (restaurant: Object) => true,
|
|
restaurantHovered: (restaurant: Object | null) => true,
|
|
});
|
|
|
|
const hovered = ref<Restaurant | null>();
|
|
|
|
function onMouseOver(e) {
|
|
const row = e.target?._DT_CellIndex?.row;
|
|
|
|
if (row !== undefined && props.data !== undefined) {
|
|
if (hovered.value != props.data[row]) {
|
|
emit("restaurantHovered", props.data[row].id);
|
|
}
|
|
hovered.value = props.data[row];
|
|
} else {
|
|
if (hovered.value !== null) {
|
|
emit("restaurantHovered", null);
|
|
}
|
|
hovered.value = null;
|
|
}
|
|
}
|
|
|
|
function onMouseLeave() {
|
|
emit("restaurantHovered", null);
|
|
hovered.value = null;
|
|
}
|
|
|
|
defineExpose({ deselectAll });
|
|
</script>
|
|
|
|
<template>
|
|
<DataTable
|
|
class="table"
|
|
ref="table"
|
|
@mouseover="onMouseOver"
|
|
@mouseleave="onMouseLeave"
|
|
:columns="columns"
|
|
:data="props.data"
|
|
:options="{
|
|
layout: {
|
|
top: ['pageLength', null, 'search'],
|
|
topStart: null,
|
|
topEnd: null,
|
|
bottom: 'paging',
|
|
bottomStart: null,
|
|
bottomEnd: null,
|
|
},
|
|
select: {
|
|
style: 'single',
|
|
},
|
|
}"
|
|
@select="onRowSelected"
|
|
>
|
|
<template #column-2="props">
|
|
<RatingField
|
|
v-if="props.cellData !== null"
|
|
:disabled="true"
|
|
:id="props.rowIndex"
|
|
v-model="props.cellData"
|
|
:size="'sm'"
|
|
/>
|
|
<p class="text-gray-500" v-else>No rating yet...</p>
|
|
</template>
|
|
</DataTable>
|
|
</template>
|