Fading Coder

One Final Commit for the Last Sprint

Home > Notes > Content

Implementing Address Management in Web Applications

Notes 3

Adding Addresses for New Users

Frontend Implementation

<template>
  <div class="container">
    <AppHeader>
      <div slot="center">Edit Shipping Address</div>
    </AppHeader>
    <div class="main-content">
      <van-address-edit
        :area-list="regionData"
        show-postal
        show-set-default
        show-search-result
        :search-result="locationSuggestions"
        :area-columns-placeholder="['Select Province', 'Select City', 'Select District']"
        @save="handleSave"
        @delete="handleDelete"
        @change-detail="handleDetailChange"
      />
    </div>
  </div>
</template>

<script>
import AppHeader from '@/components/AppHeader';
import apiClient from '@/utils/apiClient';
import regionData from '@/utils/regionData';
import Vue from 'vue';
import { AddressEdit, Toast } from 'vant';

Vue.use(AddressEdit);
Vue.use(Toast);

export default {
  components: {
    AppHeader
  },
  data() {
    return {
      regionData: regionData,
      locationSuggestions: []
    };
  },
  methods: {
    handleSave(addressData) {
      const userId = localStorage.getItem('userId');
      apiClient.post('/addresses', {
        userId: userId,
        recipientName: addressData.name,
        phoneNumber: addressData.tel,
        province: addressData.province,
        city: addressData.city,
        district: addressData.county,
        detailedAddress: addressData.addressDetail,
        isDefault: addressData.isDefault ? 1 : 0,
        regionCode: addressData.areaCode,
        postalCode: addressData.postalCode
      }).then(() => {
        Toast('Address added successfully');
        this.$router.back();
      });
    },
    handleDelete() {
      Toast('Address deletion triggered');
    },
    handleDetailChange(value) {
      // Placeholder for search functionality
    }
  }
};
</script>

Backand Implemantation

router.post('/addresses', (req, res) => {
  const { userId, recipientName, phoneNumber, detailedAddress, isDefault, province, city, district, postalCode, regionCode } = req.body;
  const defaultFlag = isDefault ? 1 : 0;
  const addressId = 'addr_' + uuid.v1();

  if (defaultFlag === 1) {
    db.update('Addresses', { userId, isDefault: 1 }, { $set: { isDefault: 0 } }).then(() => {
      db.insert('Addresses', { userId, recipientName, phoneNumber, detailedAddress, isDefault: defaultFlag, province, city, district, postalCode, regionCode, addressId }).then(() => {
        res.json({ code: 200, message: 'Address created' });
      });
    });
  } else {
    db.find('Addresses', { userId }, { _id: 0 }).then(existingAddresses => {
      if (existingAddresses.length === 0) {
        defaultFlag = 1;
      }
      db.insert('Addresses', { userId, recipientName, phoneNumber, detailedAddress, isDefault: defaultFlag, province, city, district, postalCode, regionCode, addressId }).then(() => {
        res.json({ code: 200, message: 'Address created' });
      });
    });
  }
});

Displaying and Managing Adress Lists

Frontend Implemantation

<template>
  <div class="container">
    <AppHeader>
      <div slot="center">Address List</div>
    </AppHeader>
    <div class="main-content">
      <van-address-list
        v-model="selectedAddressId"
        :list="addresses"
        @add="addNewAddress"
        @edit="editAddress"
        @select="setDefaultAddress"
      />
    </div>
  </div>
</template>

<style lang="scss">
@import '@/styles/reset.scss';
.van-address-item__name {
  font-size: 15px;
}
</style>

<script>
import AppHeader from '@/components/AppHeader';
import apiClient from '@/utils/apiClient';
import Vue from 'vue';
import { AddressList, Dialog, Toast } from 'vant';

Vue.use(AddressList);
Vue.use(Dialog);
Vue.use(Toast);

export default {
  components: {
    AppHeader
  },
  data() {
    return {
      selectedAddressId: null,
      addresses: [],
      hasError: false
    };
  },
  created() {
    const userId = this.$route.query.userId;
    if (!userId) {
      Dialog.alert({ message: 'Please log in first' });
      this.$router.replace('/login');
    } else {
      apiClient.get(`/addresses?userId=${userId}`).then(response => {
        if (response.data.code !== 30000) {
          response.data.data.forEach((addr, index) => {
            addr.id = index;
            addr.address = `${addr.province}${addr.city}${addr.district}${addr.detailedAddress}`;
            if (addr.isDefault === 1) {
              this.selectedAddressId = index;
            }
          });
          this.addresses = response.data.data;
        } else {
          Dialog.alert({ message: 'No addresses found. Add one.' });
        }
      });
    }
  },
  methods: {
    addNewAddress() {
      this.$router.push('/addresses/new');
    },
    editAddress(item) {
      this.$router.push(`/addresses/edit?addressId=${item.addressId}`);
    },
    setDefaultAddress(item) {
      apiClient.post('/addresses/default', {
        userId: item.userId,
        addressId: item.addressId
      }).then(() => {
        Toast('Default address updated');
      });
    }
  }
};
</script>

Backand Implementation

router.get('/addresses/default', (req, res) => {
  const { userId } = req.query;
  db.find('Addresses', { userId, isDefault: 1 }, { _id: 0 }).then(data => {
    if (data.length === 0) {
      res.json({ code: 30000, message: 'No default address' });
    } else {
      res.json({ code: 200, message: 'Default address retrieved', data });
    }
  });
});

router.get('/addresses', (req, res) => {
  const { addressId } = req.query;
  db.find('Addresses', { addressId }, { _id: 0 }).then(data => {
    res.json({ code: 200, message: 'Address details', data });
  });
});

router.post('/addresses/default', (req, res) => {
  const { userId, addressId } = req.body;
  db.update('Addresses', { userId, isDefault: 1 }, { $set: { isDefault: 0 } }).then(() => {
    db.update('Addresses', { addressId }, { $set: { isDefault: 1 } }).then(() => {
      res.json({ code: 200, message: 'Default address updated' });
    });
  });
});

Modifying and Deleting Addresses

Frontend Implementation

<template>
  <div class="container">
    <AppHeader>
      <div slot="center">Edit Address</div>
    </AppHeader>
    <div class="main-content">
      <van-address-edit
        :area-list="regionData"
        :address-info="currentAddress"
        save-button-text="Update"
        show-postal
        show-delete
        show-set-default
        show-search-result
        :search-result="locationSuggestions"
        :area-columns-placeholder="['Select Province', 'Select City', 'Select District']"
        @save="updateAddress"
        @delete="removeAddress"
        @change-detail="handleDetailChange"
      />
    </div>
  </div>
</template>

<script>
import AppHeader from '@/components/AppHeader';
import apiClient from '@/utils/apiClient';
import regionData from '@/utils/regionData';
import Vue from 'vue';
import { AddressEdit, Toast } from 'vant';

Vue.use(AddressEdit);
Vue.use(Toast);

export default {
  components: {
    AppHeader
  },
  data() {
    return {
      regionData: regionData,
      locationSuggestions: [],
      currentAddress: {}
    };
  },
  mounted() {
    const addressId = this.$route.query.addressId;
    apiClient.get(`/addresses?addressId=${addressId}`).then(response => {
      const addr = response.data.data[0];
      this.currentAddress = {
        name: addr.recipientName,
        tel: addr.phoneNumber,
        province: addr.province,
        city: addr.city,
        county: addr.district,
        areaCode: addr.regionCode,
        postalCode: addr.postalCode,
        addressDetail: addr.detailedAddress
      };
    });
  },
  methods: {
    updateAddress(addressData) {
      const addressId = this.$route.query.addressId;
      const userId = localStorage.getItem('userId');
      apiClient.put('/addresses', {
        addressId,
        userId,
        recipientName: addressData.name,
        phoneNumber: addressData.tel,
        province: addressData.province,
        city: addressData.city,
        district: addressData.county,
        detailedAddress: addressData.addressDetail,
        isDefault: addressData.isDefault ? 1 : 0,
        regionCode: addressData.areaCode,
        postalCode: addressData.postalCode
      }).then(() => {
        Toast('Address updated');
        this.$router.back();
      });
    },
    removeAddress() {
      const addressId = this.$route.query.addressId;
      apiClient.delete('/addresses', { addressId }).then(() => {
        Toast('Address deleted');
        this.$router.back();
      });
    },
    handleDetailChange(value) {
      // Placeholder for search functionality
    }
  }
};
</script>

Backend Implementation

router.put('/addresses', (req, res) => {
  const { addressId, userId, recipientName, phoneNumber, detailedAddress, isDefault, province, city, district, postalCode, regionCode } = req.body;
  const defaultFlag = isDefault ? 1 : 0;

  if (defaultFlag === 1) {
    db.update('Addresses', { userId, isDefault: 1 }, { $set: { isDefault: 0 } }).then(() => {
      // Continue with update
    });
  }
  db.update('Addresses', { addressId }, { $set: { recipientName, phoneNumber, detailedAddress, isDefault: defaultFlag, province, city, district, postalCode, regionCode } }).then(() => {
    res.json({ code: 200, message: 'Address updated' });
  });
});

router.delete('/addresses', (req, res) => {
  const { addressId } = req.body;
  db.delete('Addresses', { addressId }).then(() => {
    res.json({ code: 200, message: 'Address removed' });
  });
});

Related Articles

Designing Alertmanager Templates for Prometheus Notifications

How to craft Alertmanager templates to format alert messages, improving clarity and presentation. Alertmanager uses Go’s text/template engine with additional helper functions. Alerting rules referenc...

Deploying a Maven Web Application to Tomcat 9 Using the Tomcat Manager

Tomcat 9 does not provide a dedicated Maven plugin. The Tomcat Manager interface, however, is backward-compatible, so the Tomcat 7 Maven Plugin can be used to deploy to Tomcat 9. This guide shows two...

Skipping Errors in MySQL Asynchronous Replication

When a replica halts because the SQL thread encounters an error, you can resume replication by skipping the problematic event(s). Two common approaches are available. Methods to Skip Errors 1) Skip a...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.