Added connection error message, added max height for tags field, added optional google maps link, added price options.
parent
04fb307b7a
commit
d73cb4dbb8
|
|
@ -18,6 +18,10 @@ const { errors, handleSubmit, defineField, resetForm } = useForm({
|
|||
name: yup.string().required("This field is required."),
|
||||
tags: yup.array().of(yup.string()),
|
||||
price: yup.string().required("This field is required."),
|
||||
googleMapsLink: yup
|
||||
.string()
|
||||
.trim()
|
||||
.matches(/^$|https:\/\/maps\.app\.goo\.gl\/[a-zA-Z0-9]+/, "Not a valid Google Maps link."),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
|
@ -39,6 +43,7 @@ const submit = handleSubmit((values) => {
|
|||
tags: tags,
|
||||
latitude: position.value?.lat,
|
||||
longitude: position.value?.lng,
|
||||
googleMapsLink: values.googleMapsLink,
|
||||
});
|
||||
|
||||
emit("succeeded", `Restaurant ${values.name} created successfully!`);
|
||||
|
|
@ -65,6 +70,7 @@ onMounted(async () => {
|
|||
const [name, nameAttrs] = defineField("name");
|
||||
const [tags, tagsAttrs] = defineField("tags");
|
||||
const [price, priceAttrs] = defineField("price");
|
||||
const [googleMapsLink, googleMapsLinkAttrs] = defineField("googleMapsLink");
|
||||
|
||||
const emit = defineEmits({
|
||||
succeeded: (message: string) => true,
|
||||
|
|
@ -138,12 +144,25 @@ defineExpose({ show, hide, setRestaurantPosition });
|
|||
v-bind="priceAttrs"
|
||||
>
|
||||
<option value="€">1-10€</option>
|
||||
<option value="€€">10-20€</option>
|
||||
<option value="€€€">20-30€</option>
|
||||
<option value="€€">10-15€</option>
|
||||
<option value="€€€">15-20€</option>
|
||||
<option value="€€€€">>20€</option>
|
||||
</select>
|
||||
<label class="text-red-500">{{ errors.price }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row flex-nowrap w-96">
|
||||
<div class="mx-5 my-4 w-full">
|
||||
<label class="form-label"> Google Maps Link (Optional) </label>
|
||||
<input
|
||||
:class="errors.googleMapsLink === undefined ? 'form-field' : 'form-field-error'"
|
||||
v-model="googleMapsLink"
|
||||
v-bind="googleMapsLinkAttrs"
|
||||
type="text"
|
||||
/>
|
||||
<label class="text-red-500">{{ errors.googleMapsLink }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalComponent>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ const columns = [
|
|||
_: "[, ]",
|
||||
},
|
||||
},
|
||||
{ data: "price", title: "Price" },
|
||||
{ data: "average_rating", title: "" },
|
||||
];
|
||||
|
||||
|
|
@ -39,7 +40,7 @@ function deselectAll() {
|
|||
}
|
||||
|
||||
const emit = defineEmits({
|
||||
restaurantSelected: (restaurant: Object) => true,
|
||||
restaurantSelected: (restaurant: Restaurant) => true,
|
||||
restaurantHovered: (restaurant: Object | null) => true,
|
||||
});
|
||||
|
||||
|
|
@ -92,7 +93,7 @@ defineExpose({ deselectAll });
|
|||
}"
|
||||
@select="onRowSelected"
|
||||
>
|
||||
<template #column-2="props">
|
||||
<template #column-3="props">
|
||||
<RatingField
|
||||
v-if="props.cellData !== null"
|
||||
:disabled="true"
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ import { ref } from "vue";
|
|||
import ReviewsList from "./ReviewsList.vue";
|
||||
import ReviewField from "./ReviewField.vue";
|
||||
import { currentUser, pb } from "../pocketbase";
|
||||
import Restaurant from "../models/restaurant";
|
||||
|
||||
const props = defineProps({
|
||||
restaurant: { type: Object },
|
||||
restaurant: { type: Object as () => Restaurant },
|
||||
});
|
||||
|
||||
const opened = ref<boolean>(false);
|
||||
|
|
@ -49,11 +50,22 @@ defineExpose({ open, close });
|
|||
<div class="drawer-side w-full">
|
||||
<label @click.prevent="close" for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
|
||||
<div class="menu p-4 space-y-4 w-full lg:w-2/6 min-h-full bg-base-200 text-base-content">
|
||||
<div class="flex flex-row w-full">
|
||||
<font-awesome-icon
|
||||
@click="close"
|
||||
class="btn btn-circle btn-sm text-gray-500 bg-transparent"
|
||||
icon="fa-solid fa-xmark"
|
||||
/>
|
||||
<div class="flex-1"></div>
|
||||
<a
|
||||
v-if="props.restaurant?.googleMapsLink"
|
||||
:href="props.restaurant.googleMapsLink"
|
||||
class="btn btn-ghost btn-link btn-sm"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>View on Google Maps</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<ReviewField ref="reviewField" @publish="onPublishReview" />
|
||||
<ReviewsList ref="reviewsList" :restaurant="props.restaurant" />
|
||||
|
|
|
|||
|
|
@ -85,7 +85,9 @@ function filteredOptions() {
|
|||
<font-awesome-icon icon="xmark" />
|
||||
</button>
|
||||
</div>
|
||||
<ul class="menu dropdown-content z-10 w-full rounded-lg border border-neutral-content bg-base-100 p-0 shadow">
|
||||
<ul
|
||||
class="menu flex-nowrap dropdown-content overflow-y-auto z-10 max-h-96 w-full rounded-lg border border-neutral-content bg-base-100 p-0 shadow"
|
||||
>
|
||||
<li><button @click="onCreateNewTag">Create new tag...</button></li>
|
||||
<li v-for="option in filteredOptions()" :key="option" role="option" class="m-0 p-0">
|
||||
<button :class="{ active: model?.includes(option) }" @click="onOptionClicked(option)">
|
||||
|
|
|
|||
|
|
@ -6,4 +6,5 @@ export default interface Restaurant {
|
|||
averageRating: number;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
googleMapsLink?: string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,16 +5,17 @@ import RestaurantsMap from "../components/RestaurantsMap.vue";
|
|||
import ReviewsDrawer from "../components/ReviewsDrawer.vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useRestaurantsStore } from "../stores/restaurants";
|
||||
import Restaurant from "../models/restaurant";
|
||||
|
||||
const drawer = ref<typeof ReviewsDrawer>();
|
||||
const table = ref<typeof RestaurantsTable>();
|
||||
|
||||
const selectedRestaurant = ref<Object>();
|
||||
const selectedRestaurant = ref<Restaurant>();
|
||||
const highlightedRestaurant = ref<string>();
|
||||
|
||||
const { restaurants } = storeToRefs(useRestaurantsStore());
|
||||
|
||||
function onRestaurantSelected(restaurant: Object) {
|
||||
function onRestaurantSelected(restaurant: Restaurant) {
|
||||
selectedRestaurant.value = restaurant;
|
||||
drawer.value?.open();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,18 @@ const valid = computed(() => {
|
|||
return username.value !== undefined && password.value !== undefined;
|
||||
});
|
||||
|
||||
const errorMessage = ref<string>();
|
||||
|
||||
async function login() {
|
||||
if (!valid.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await pb.collection("users").authWithPassword(username.value!, password.value!);
|
||||
} catch (err) {
|
||||
errorMessage.value = "Incorrect username or password.";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -35,7 +41,9 @@ async function login() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<button @click="login" :disabled="!valid">Log In</button>
|
||||
<label v-if="errorMessage" class="text-red-500">{{ errorMessage }}</label>
|
||||
|
||||
<button @click="login" :disabled="!valid" class="my-3 btn btn-outline">Log In</button>
|
||||
<p>New to DOXFOOD ? <RouterLink to="/signup">Create an account !</RouterLink></p>
|
||||
</form>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Reference in New Issue