diff --git a/src/assets/datatable.css b/src/assets/datatable.css index d1e59c3..1e21160 100644 --- a/src/assets/datatable.css +++ b/src/assets/datatable.css @@ -39,4 +39,25 @@ @apply hover:bg-gray-300; } -} \ No newline at end of file +} + +.dt-paging-button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + cursor: pointer; + transition: border-color 0.25s; +} + +.dt-paging-button:hover { + border-color: #646cff; +} +.dt-paging-button:focus, +.dt-paging-button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + + diff --git a/src/components/CreateTagModal.vue b/src/components/CreateTagModal.vue new file mode 100644 index 0000000..d21fc00 --- /dev/null +++ b/src/components/CreateTagModal.vue @@ -0,0 +1,84 @@ + + + + + + + Name + + {{ errors.name }} + + {{ error }} + + + diff --git a/src/components/ModalComponent.vue b/src/components/ModalComponent.vue new file mode 100644 index 0000000..aac7674 --- /dev/null +++ b/src/components/ModalComponent.vue @@ -0,0 +1,64 @@ + + + + + + + ✕ + + {{ props.title }} + {{ props.text }} + + + + + {{ props.confirmButtonText }} + + + {{ props.rejectButtonText }} + + + + + + diff --git a/src/components/RestaurantsTable.vue b/src/components/RestaurantsTable.vue index 3e7a708..ddaaf59 100644 --- a/src/components/RestaurantsTable.vue +++ b/src/components/RestaurantsTable.vue @@ -4,7 +4,7 @@ import "../assets/datatable.css"; import DataTable from "datatables.net-vue3"; import DataTablesCore from "datatables.net"; import "datatables.net-select"; -import { PropType } from "vue"; +import { PropType, ref } from "vue"; import RatingField from "./RatingField.vue"; DataTable.use(DataTablesCore); @@ -19,18 +19,27 @@ const columns = [ { data: "average_rating", title: "" }, ]; +const table = ref(); + 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"]); + +defineExpose({ deselectAll }); true, +}); defineExpose({ open, close }); @@ -43,7 +47,7 @@ defineExpose({ open, close }); - + }, labels: { type: Map as PropType>, default: () => {} }, @@ -14,6 +16,8 @@ const emit = defineEmits(["updateModelValue"]); const query = ref(""); +const createTagModal = ref(); + function onBadgeClicked(value: string) { if (model.value?.includes(value)) { model.value = model.value.filter((val) => val != value); @@ -46,6 +50,10 @@ function onClear() { model.value = []; } +function onCreateNewTag() { + createTagModal.value?.show(); +} + function filteredOptions() { if (!query.value) return props.options; const lcquery = query.value.toLocaleLowerCase(); @@ -54,7 +62,7 @@ function filteredOptions() { - + @@ -78,6 +86,7 @@ function filteredOptions() { + Create new tag... @@ -86,4 +95,6 @@ function filteredOptions() { + + diff --git a/src/style.css b/src/style.css index a0491ef..4fef441 100644 --- a/src/style.css +++ b/src/style.css @@ -47,25 +47,6 @@ h2 { line-height: 1.1; } -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - .card { padding: 2em; } diff --git a/src/views/CreateView.vue b/src/views/CreateView.vue index 3bf7978..ef8924e 100644 --- a/src/views/CreateView.vue +++ b/src/views/CreateView.vue @@ -5,7 +5,7 @@ import * as yup from "yup"; import "@/assets/form.css"; import { pb } from "../pocketbase.ts"; -import MultiSelectField from "../components/MultiSelectField.vue"; +import TagsField from "../components/TagsField.vue"; import { computed, onMounted, ref } from "vue"; const { meta, errors, handleSubmit, defineField, resetForm } = useForm({ @@ -59,6 +59,10 @@ const [price, priceAttrs] = defineField("price"); onMounted(async () => { availableTags.value = await pb.collection("tags").getFullList(); + + pb.collection("tags").subscribe("*", async (e) => { + availableTags.value = await pb.collection("tags").getFullList(); + }); }); @@ -88,7 +92,7 @@ onMounted(async () => { Tags - + {{ errors.tags }} diff --git a/src/views/ListView.vue b/src/views/ListView.vue index 31e9cf5..d2b40b9 100644 --- a/src/views/ListView.vue +++ b/src/views/ListView.vue @@ -9,10 +9,11 @@ import { average } from "../utils/math"; const data = ref([]); const drawer = ref(); +const table = ref(); const selectedRestaurant = ref(); -onMounted(async () => { +async function load() { const restaurants = await pb.collection("restaurants").getFullList({ expand: "tags,reviews_via_restaurant" }); restaurants.forEach((restaurant) => { @@ -34,25 +35,41 @@ onMounted(async () => { } }); - console.log(restaurants); data.value = restaurants; +} + +onMounted(async () => { + await load(); + + pb.collection("restaurants").subscribe("*", (e) => { + load(); + }); + + pb.collection("reviews").subscribe("*", (e) => { + load(); + }); }); function onRestaurantSelected(restaurant: Object) { selectedRestaurant.value = restaurant; drawer.value?.open(); } + +function onDrawerClosed() { + console.log("closed"); + table.value?.deselectAll(); +} - + - +