<template> <el-row :gutter="20"> <el-col :span="2"><div class="grid-content ep-bg-purple" /></el-col> <el-col :span="20"> <el-card style="width: 100%"> <template #header> <div class="card-header"> <span>Your Wishlist Information</span> </div> </template> <div class="common-layout"> <el-container> <!-- Aside Coding Area --> <el-aside width="300px"> <el-space direction="vertical" width="100%"> <el-badge class="item" v-for="(item, index) in wishlistList.value" :value="totalMatchCountList.value[index]" :hidden = "totalMatchCountList.value[index] === 0" > <el-card shadow="hover" style="width: 280px" @click="selectItem(index)" > <span>{{ item.cityName }}, {{ item.state }}</span> <div class="bottom"> <time class="time" >"{{ formatDate(item.startTime) }} to {{ formatDate(item.endTime) }}"</time > </div> </el-card> </el-badge> <el-card class="item" shadow="hover" style="width: 280px" @click="addNewWishlistItem()" > <el-icon><Plus /></el-icon> <span> + Add New Item To Wishlist</span> </el-card> </el-space> </el-aside> <!-- Main Coding Area --> <el-main> <el-card shadow="never" class="main-card"> <span>Wishlist Item Detail</span> <el-form ref="ruleFormRef" :model="wishlistItem" :rules="rules" label-width="120px" :label-position="'left'" class="demo-ruleForm" :size="formSize" status-icon > <el-form-item></el-form-item> <el-form-item label="City Name:" prop="cityName"> <el-input v-model="wishlistItem.cityName" :readonly="buttonState === 'edit'" /> </el-form-item> <el-form-item label="Zip Code:" prop="zipCode"> <el-input v-model="wishlistItem.zipCode" :readonly="buttonState === 'edit'"/> </el-form-item> <el-form-item label="State:" prop="state"> <el-select v-model="wishlistItem.state" placeholder="Please select state" :disabled="buttonState === 'edit'" > <el-option v-for="(state_item, index) in USA_STATE_INITAL_LIST" :label="state_item" :value="state_item" /> </el-select> </el-form-item> <el-form-item label="Trip Start Time" required> <el-form-item prop="startTime"> <el-date-picker v-model="wishlistItem.startTime" type="date" label="Pick a date" placeholder="Pick a date" style="width: 100%" :readonly="buttonState === 'edit'" /> </el-form-item> </el-form-item> <el-form-item label="Trip End Time" required> <el-form-item prop="endTime"> <el-date-picker v-model="wishlistItem.endTime" type="date" label="Pick a date" placeholder="Pick a date" style="width: 100%" :readonly="buttonState === 'edit'" /> </el-form-item> </el-form-item> <el-form-item label="Details:" prop="details"> <el-input v-model="wishlistItem.details" type="textarea" placeholder="Trip plan or want to visit places..." :readonly="buttonState === 'edit'" /> </el-form-item> <el-button type="primary" v-if="buttonState === 'create'" @click="submitForm(ruleFormRef)" >Create</el-button> <el-button type="primary" v-if="buttonState === 'edit'" @click="onEdit(ruleFormRef)" >Edit</el-button> <el-button type="success" v-if="buttonState === 'update'" @click="updateForm(ruleFormRef)" >Save</el-button> <el-button type="danger" v-if="buttonState === 'update'" @click="deleteForm(ruleFormRef)"> Delete</el-button> </el-form> </el-card> </el-main> <el-aside width="300px"> <el-space direction="vertical" width="100%" :fill="true"> <div class="card-header"> <span>Matched Offer for: {{wishlistItem.cityName}}, {{wishlistItem.state}} </span> </div> <el-card v-for="(item, index) in offerMatchList.value" shadow="hover" style="width: 280px" @click="selectMatchOfferItem(index)" > <span> {{formatDate(item.startTime)}} - {{formatDate(item.endTime)}} </span> <div> <span class="o-zipCode"> Zip code: {{item.zipCode}} </span> <br> <span class="o-owner"> Host name: {{item.hostName}} </span> </div> </el-card> </el-space> </el-aside> </el-container> </div> </el-card> </el-col> <el-col :span="2"><div class="grid-content ep-bg-purple" /></el-col> </el-row> </template> <script lang="ts" setup> import { reactive, ref, onMounted } from "vue"; import type { FormInstance, FormRules } from "element-plus"; import { WishlistItemModel } from "@/models/WishlistItemModel"; import * as WishlistService from "@/services/WishlistService"; import { USA_STATE_INITAL_LIST } from "@/services/Constans"; const formSize = ref("default"); const ruleFormRef = ref<FormInstance>(); const rules = reactive<FormRules>({ cityName: [ { required: true, message: "Please give which city you want to visit.", trigger: "blur", }, { min: 0, max: 20, message: "Length should be 0 to 20", trigger: "blur" }, ], zipCode:[ { required: true, message: "Please give the stat of the city located.", trigger: "blur", }, ], state: [ { required: true, message: "Please give the stat of the city located.", trigger: "blur", }, ], startTime: [ { type: "date", required: true, message: "Please pick a date", trigger: "change", }, ], endTime: [ { type: "date", required: true, message: "Please pick a time", trigger: "change", }, ], }); const wishlistList = reactive({value:[]}); const wishlistItem = ref(new WishlistItemModel()); wishlistItem.value.wishlistItemId = null; let buttonState = ref("create"); const selectedIdx = ref(0); const offerMatchList = reactive({value:[]}); const totalMatchCountList = reactive({value:[]}); onMounted(() => { selectedIdx.value = 0; wishlistInitLoad(); }) const onEdit = () =>{ buttonState.value = "update"; } const wishlistInitLoad = async() =>{ await WishlistService.getUserWishlistInfo().then((data)=>{ console.log("Receiving wishlist list data", data); if(data["data"] === null || data["data"].length === 0){ wishlistList.value = []; buttonState.value = "create"; }else{ wishlistList.value = data["data"]; selectItem(0); buttonState.value = "edit"; loadMatchNumbersForAllList(data["data"]); } }) } const loadMatchNumbersForAllList = async (wishlistItemList: Array<WishlistItemModel>) =>{ await WishlistService.loadMatchOfferNumbersFor(wishlistItemList).then((data) =>{ console.log("Receiving offer match count list data: ", data); if(data["data"] === null || data["data"].length === 0){ for(let i=0; i<totalMatchCountList.value.length; ++i){ totalMatchCountList.value.push(0); } }else{ totalMatchCountList.value = data["data"]; } }) } const loadOfferMatchList = async () =>{ await WishlistService.getOfferMatchList(wishlistItem.value.wishlistItemId).then((data) =>{ console.log("Receiving offer match list data: ", data); if(data["data"] === null || data["data"].length === 0){ offerMatchList.value = []; }else{ offerMatchList.value = data["data"]; } }) } const formatDate = (dateString) => { const date = new Date(dateString); return new Intl.DateTimeFormat('en-US').format(date); } function selectItem(idx: number) { console.log("Selected wishlist Item: " + idx); wishlistItem.value = reactive(wishlistList.value[idx]); buttonState.value = "edit"; selectedIdx.value = idx; loadOfferMatchList(wishlistItem.value.wishlistItemId); } function addNewWishlistItem() { // TODO: disable it when it already displays the form console.log("addNewWishlistItem"); wishlistItem.value = new WishlistItemModel(); wishlistItem.value.wishlistItemId = null; buttonState.value = "create"; } const submitForm = async (formEl: FormInstance | undefined) => { if (!formEl) return; await formEl.validate((valid, fields) => { if (valid) { WishlistService.createNewWishlistItem( wishlistItem.value).then((data)=>{ console.log("Receiving create wishlist item data", data); if(data["data"] === null){ // TODO: create failed, handle it later }else{ wishlistItem.value = data["data"]; wishlistList.value.push(data["data"]); buttonState.value = "edit"; } }) console.log("submit!"); } else { console.log("error submit!", fields); } console.log(wishlistItem.value); }); }; const updateForm = async (formEl: FormInstance | undefined) =>{ if (!formEl) return; await formEl.validate((valid, fields) => { if (valid) { WishlistService.createNewWishlistItem( wishlistItem.value).then((data)=>{ console.log("Receiving wishlist item data", data); if(data["data"] === null){ // TODO: create failed, handle it later }else{ wishlistItem.value = data["data"]; wishlistList.value[selectedIdx] = data["data"]; buttonState.value = "edit"; } ) console.log("submit!"); } else { console.log("error submit!", fields); } console.log(wishlistItem.value); }); } const deleteForm = async (formEl: FormInstance | undefined) => { if(wishlistItem.value.wishlistItemId !== null){ await WishlistService.deleteWishlistItem( wishlistItem.value.wishlistItemId).then((data)=>{ console.log("Delete wishlist item", data); if(data["data"] === null){ // TODO: delete failed or something wrong }else{ wishlistList.value=data["data"]; addNewWishlistItem(); } }) } }; const options = Array.from({ length: 10000 }).map((_, idx) => ({ value: `${idx + 1}`, label: `${idx + 1}`, })); </script> <style scoped> .time { font-size: 12px; color: #999; } .bottom { margin-top: 13px; line-height: 12px; display: flex; justify-content: space-between; align-items: center; } .el-main { --el-main-padding: 0px 20px 20px 20px; } .main-card { padding: 0 0 0 20px; } .o-zipCode { font-size: 12px; } .o-owner { font-size: 12px; } .item { margin-top: 10px; margin-right: 40px; } </style>