Hướng dẫn tự làm “Hệ thống chi nhánh Google Maps” cực kỳ đơn giản cho WordPress

🗣 Bài viết đăng bởi Pinker vào lúc 28-07-2024 và cập nhật lúc 14-08-2024 👁 490 lượt xem
Chia sẻ ➯
He-thong-chi-nhanh-cua-hang-Google-Maps

Hiện nay, các doanh nghiệp mở rộng nhiều chi nhánh, nhiều cửa hàng là điều không hề xa lạ. Ví dụ như Thế Giới Di Động, họ có tới hàng nghìn cửa hàng trải khắp từ Bắc tới Nam, ở mọi tỉnh thành, quận huyện đều có. Và khi khách hàng truy cập vào website. Để tìm kiếm vị trí các cửa hàng một cách thuận tiện, thì việc xây dựng “Hệ thống chi nhánh Google Maps” là rất cần thiết, giúp tăng trải nghiệm khách hàng.

Trong phạm vi bài viết này, tôi sẽ hướng dẫn các bạn cách để tự làm trang hệ thống cửa hàng, chi nhánh đơn giản nhất mà không cần bỏ chi phí mua plugin. Mà vẫn đem lại sự hiệu quả.

Hệ thống chi nhánh Google Maps
Hệ thống chi nhánh Google Maps.

 

Bài viết khác

Phần 1: Hướng dẫn tạo hệ thống chi nhánh với Google Maps

Bước 01: Tạo shortcode

Chúng ta sẽ tạo shortcode và code vào trong đó để tiện linh hoạt khi đặt vào bất cứ đâu. Trong code này sẽ viết các mã HTML, CSS, JAVASCRIPT

<?php 
add_shortcode('vdh_map_local', function(){
    ob_start();
    ?>
        // Code tại đây
    <?php
    wp_reset_postdata();
    $content = ob_get_contents();
    ob_end_clean();
    return $content;
});
?>

Bước 02: Tạo cấu trúc HTML với 2 cột

Đặt code vào trong shortcode trên, bên trái sẽ là danh sách các địa điểm, bên phải sẽ là bản đồ

<!-- HTML -->
<div class="pk_row">
    <div class="pk_column pk-column-data">
				
    </div>
    <div class="pk_column pk-column-map">
				
    </div>
</div>

<!-- CSS-->
<style>
.pk_row {
    height: 600px;
}

.pk_column {
    float: left;
    width: 50%;
    padding: 10px;
    height:100%;
    background:white;
    border: 5px solid #ccc;
}

.pk_row:after {
    content: "";
    display: table;
    clear: both;
}
</style>
Tạo bộ khung 2 cột
Tạo bộ khung 2 cột

Bước 03: Tạo danh sách dữ liệu trong cột bên trái (pk-column-data)

Tôi sẽ demo bằng dữ liệu danh sách cửa hàng Mediamart Hà Nội. Các bạn lưu ý đặt dữ liệu theo cấu trúc mẫu phía dưới, các thẻ <li> có thuộc tính data-map chính là src mã google maps embed chúng ta lấy ở trên https://google.com/maps

<!-- HTML -->
<ul id="pk_list_map">
    <li data-map="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d5264.906561212957!2d105.81119061764379!3d21.078607217417975!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3135ab633709e735:0xbce4be42931e79d7!2zTWVkaWFtYXJ0IEzhuqFjIExvbmcgUXXDom4!5e0!3m2!1svi!2sus!4v1722133884574!5m2!1svi!2sus">
        672 Lạc Long Quân, Nhật Tân, Tây Hồ, Hà Nội <br>
        ☏ <i><small>0986209305</small></i>
    </li>

    <li data-map="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3130.8015597413832!2d105.80639835563994!3d21.065811820350714!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3135aae689795b9b:0x39e9258e56203cb9!2zU2nDqnUgdGjhu4sgxJBp4buHbiBtw6F5IE1lZGlhIE1hcnQ!5e0!3m2!1svi!2sus!4v1722133932522!5m2!1svi!2sus">
        583 Lạc Long Quân, Xuân La, Tây Hồ, Hà Nội <br>
        ☏ <i><small>0986209305</small></i>
    </li>

    <li data-map="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2214.094906617745!2d105.80137716234678!3d21.046728308119164!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3135ab8c9f51eeef:0x7c09768e45ee74cb!2sMedia Mart!5e0!3m2!1svi!2sus!4v1722133970512!5m2!1svi!2sus">
        16 Hoàng Quốc Việt, Nghĩa Đô, Cầu Giấy, Hà Nội <br>
        ☏ <i><small>0986209305</small></i>
    </li>

    <li data-map="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3833.2027027936233!2d105.76428382213098!3d21.029529258588838!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x313454baf43641c3:0x75277794a7c0b824!2zU2nDqnUgdGjhu4sgxJBp4buHbiBNw6F5IE1lZGlhIE1hcnQ!5e0!3m2!1svi!2sus!4v1722134009397!5m2!1svi!2sus">
        16 Lê Đức Thọ, Nam Từ Liêm, Hà Nội <br>
        ☏ <i><small>0986209305</small></i>
    </li>

    <li data-map="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3415.3947807557834!2d105.79690308937232!3d21.012093216795318!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3135ab9708dddbc1:0xc72f7e9f994503e2!2zTWVkaWFtYXJ0IFRy4bqnbiBEdXkgSMawbmc!5e0!3m2!1svi!2sus!4v1722137271657!5m2!1svi!2sus">
        40 Trần Duy Hưng, Cầu Giấy, Hà Nội <br>
        ☏ <i><small>0986209305</small></i>
    </li>
    <li data-map="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3415.326610172044!2d105.80953837029361!3d21.015070348300892!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3135abdc18b626a9:0x9d51f4ff9c19e8ad!2zTWVkaWFtYXJ0IEzDoW5nIEjhuqE!5e0!3m2!1svi!2sus!4v1722137304395!5m2!1svi!2sus">
        26 Láng Hạ, Đống Đa, Hà Nội <br>
        ☏ <i><small>0986209305</small></i>
    </li>

    <li data-map="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3131.4436900706596!2d105.81549671021469!3d21.035282000583322!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3135abce85df50c1:0x5f86be6355b1e2c5!2zU2nDqnUgVGjhu4sgxJBp4buHbiBNw6F5IE1lZGlhTWFydCDEkOG7mWkgQ-G6pW4!5e0!3m2!1svi!2s!4v1722137779617!5m2!1svi!2s">
        218 Đội Cấn, Ba Đình, Hà Nội <br>
        ☏ <i><small>0986209305</small></i>
    </li>
</ul>
<!-- CSS -->
<style>
.pk-column-data ul li {
    margin-bottom:5px;
    margin-left:0;
    padding: 10px;
    padding-left:15px;
    background: #efefefc7;
    list-style-type:none;
}

.pk-column-data ul li:hover {
    cursor: pointer;
    background:#326e5130;
}

.pk-column-data ul li.pk-active {
    background:#326e51;
    color:white;
}
</style>
Danh sách các địa điểm
Danh sách các địa điểm

Bước 04: Chèn iframe google maps vào cột bên phải (pk-column-map)

Chúng ta sẽ lấy full cấu trúc embed mà trên google maps đã chia sẻ. Lưu ý thay đổi thuộc tính width, height cho phù hợp với khung đã tạo. Ở đây tôi đặt width=”100%” và height=”570″

<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d5264.906561212957!2d105.81119061764379!3d21.078607217417975!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3135ab633709e735:0xbce4be42931e79d7!2zTWVkaWFtYXJ0IEzhuqFjIExvbmcgUXXDom4!5e0!3m2!1svi!2sus!4v1722133884574!5m2!1svi!2sus" width="100%" height="570" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>

Link iframe sẽ là địa chỉ mặc định đầu tiên ở danh sách trên. Lúc này giao diện hiển thị ra đã hoàn chỉnh, nhưng khi click vào địa chỉ thì chưa hoạt động, không có thay đổi gì. Chúng ta cần code thêm javascript.

Bước 04: Viết code Javascript để thực hiện thao tác

<script>
const list_map = document.querySelectorAll('#pk_list_map li')
list_map.forEach(item => {
    item.addEventListener('click', function(){
        var map = this.getAttribute('data-map')
        document.querySelector('.pk-column-map iframe').src = map
        list_map.forEach(e => e.classList.remove("pk-active"));
        this.classList.add("pk-active");
    })
});
</script>

Bước 05: Hoàn thành cấu trúc và chức năng

Vậy là đến bước này, đã có thể sử dụng tính năng một cách hoàn chỉnh về mặt cấu trúc + chức năng. Để thay đổi danh sách thì bạn quay lại bước 03 để cập nhật. Các bạn hãy xem video hướng dẫn để có thể hiểu hơn về tính năng này.

Bài viết này sẽ còn update thêm tính năng lấy dữ liệu từ trong admin, database để thuận tiện cho việc chỉnh sửa mà không cần phải sửa trong code.


Phần 2: Quản lý dữ liệu chi nhánh trong Admin & phân theo tỉnh (thành), quận (huyện)

Hệ thống cửa hàng phân theo tỉnh thành quận huyện
Hệ thống cửa hàng phân theo tỉnh thành quận huyện

Ở phần 1 các bạn đã có thể tạo được 1 trang tĩnh cơ bản đủ chức năng mong muốn, tại phần 2 này, tôi sẽ hướng dẫn tạo phần quản lý chi nhánh trong Admin và nâng cấp bộ lọc địa chỉ. Các bạn cùng theo dõi.

Bước 01: Tạo Custom Post Type & Taxonomy

<?php
add_action('init', function(){
    register_post_type('location-map',
        array(
            'public' => true,
            'has_archive' => true,
            'menu_icon' => 'dashicons-store',
            'supports' => array('title', 'thumbnail'),
            'labels' => array(
                'name'                  => 'Chi nhánh',
                'singular_name'         => 'Chi nhánh',
                'add_new_item'          => 'Thêm mới chi nhánh',
                'add_new'               => 'Thêm mới',
                'edit_item'             => 'Sửa chi nhánh',
                'featured_image'        => 'Ảnh đại diện',
                'set_featured_image'    => 'Chọn ảnh',
                'remove_featured_image' => 'Xóa ảnh',
                'menu_name'             => 'Chi nhánh'
            ),
        )
    );

    register_taxonomy('province', 'location-map', [
        'label' => 'Tỉnh thành',
        'hierarchical' => true,
        'show_admin_column' => true,
        'show_in_rest' => true
    ]);
});
?>
Taxonomy-Tỉnh-thành
Taxonomy-Tỉnh-thành

Bước 02: Tạo thêm trường dữ liệu với add_meta_box

<?php
add_action('add_meta_boxes', function(){
    add_meta_box('chi-nhanh', 'Thông tin chi nhánh', function($post){
        $location_address = get_post_meta( $post->ID, 'location_address', true );
        $location_phone = get_post_meta( $post->ID, 'location_phone', true );
        $location_link = get_post_meta( $post->ID, 'location_link', true );
        ?>
            <div class="input_custom">
                <label for="location_address">Địa chỉ: </label>
                <input type="text" id="location_address" name="location_address" placeholder="Địa chỉ" style="width:500px" value="<?php echo !empty($location_address) ? esc_attr($location_address) : null ?>" />
            </div>

            <div class="input_custom">
                <label for="location_link">Link iframe: </label>
                <input type="text" id="location_link" name="location_link" placeholder="Link iframe" style="width:500px" value="<?php echo !empty($location_link) ? esc_attr($location_link) : null ?>" />
            </div>

            <div class="input_custom">
                <label for="location_phone">Số điện thoại: </label>
                <input type="text" id="location_phone" name="location_phone" placeholder="Số điện thoại" style="width:500px" value="<?php echo !empty($location_phone) ? esc_attr($location_phone) : null ?>" />
            </div>

            <style>
                .input_custom {
                    margin-bottom: 10px;
                }

                .input_custom label {
                    display:inline-block;
                    width: 100px;
                }
            </style>
        <?php
    }, 'location-map');
});
?>
Custom-Post-Type-chi-nhánh
Custom-Post-Type-chi-nhánh

Lưu dữ liệu từ custom meta box ở trên vào database

<?php
add_action('save_post', function($post_id){
    if(!empty($_POST['location_address'])) {
        $location_address = sanitize_text_field($_POST['location_address']);
        update_post_meta($post_id, 'location_address', $location_address);
    }

    if(!empty($_POST['location_link'])) {
        $location_link = sanitize_text_field($_POST['location_link']);
        update_post_meta($post_id, 'location_link', $location_link);
    }

    if(!empty($_POST['location_phone'])) {
        $location_phone = sanitize_text_field($_POST['location_phone']);
        update_post_meta($post_id, 'location_phone', $location_phone);
    }
});
?>

Tạo danh sách chi nhánh mẫu

Danh-sách-chi-nhánh
Danh-sách-chi-nhánh

Bước 03: Get dữ liệu Tỉnh thành, Quận huyện + Chi nhánh

Ở giao diện bên ngoài, sẽ cần hiển thị danh sách các dữ liệu ở trên ra bên ngoài. Ở shortcode trong Bước 1 (Phần 1), đặt code sau để lấy dữ liệu cần thiết

/* Lấy tỉnh thành quận huyện */
$province = get_terms([
    'taxonomy' => 'province',
    'hide_empty' => false,
]);

/* Lấy danh sách chi nhánh */
$locations = get_posts([
    'post_type' => 'location-map',
    'post_status' => 'publish',
    'posts_per_page' => -1
]);

Tạo cấu trúc Tỉnh thành – Quận huyện bằng Select Option và hiển thị dữ liệu đã lấy ở trên

<div class="pk_row">
    <div class="pk_column pk-column-data">

        <div class="province location">
	    <label for="">Tỉnh thành</label>
	    <select id="province">
		<option value="">Lựa chọn</option>
		<?php foreach($province as $item): if($item->parent == 0): ?>
		<option value="<?php echo $item->term_id ?? null ?>"><?php echo $item->name ?? null ?></option>
		<?php endif; endforeach; ?>
	    </select>
	</div>
				
	<div class="district location">
	    <label for="">Quận/Huyện</label>
	    <select id="district" disabled="">
		<option value="">Lựa chọn</option>
		<?php foreach($province as $item): if($item->parent > 0): ?>
		<option value="<?php echo $item->term_id ?? null ?>" data-parent-id="<?php echo $item->parent ?? null ?>"><?php echo $item->name ?? null ?></option>
		<?php endif; endforeach; ?>
	    </select>
	</div>
				
        <div class="clearfix"></div>
        <hr>

	<ul id="pk_list_map">
	    <?php 
		foreach($locations as $location):
		    $location_address = get_post_meta( $location->ID, 'location_address', true );
		    $location_phone = get_post_meta( $location->ID, 'location_phone', true );
		    $location_link = get_post_meta( $location->ID, 'location_link', true );
		    $terms = wp_get_post_terms($location->ID, 'province');
		    $ids = array_column($terms, 'term_id');
		?>
		<li data-term="<?php echo json_encode($ids) ?? null ?>" data-map="<?php echo $location_link ?? null ?>">
		    <p class="location_title"><?php echo $location->post_title ?? null ?></p>
		    <p class="location_address"><?php echo $location_address ?? null ?></p>
		    ☏ <i><small><?php echo $location_phone ?? null ?></small></i>
		</li>
	    <?php endforeach; ?>
	</ul>
    </div>
    <div class="pk_column pk-column-map">
	<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d1861.8583177565963!2d105.81213348044113!3d21.0440212023018!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3135ab105387c82f:0x743e0ea8682ba96c!2zVGjhur8gR2nhu5tpIERpIMSQ4buZbmc!5e0!3m2!1svi!2s!4v1722329069267!5m2!1svi!2s" width="100%" height="570" style="border:0;" allowfullscreen=""></iframe>
    </div>
</div>

<style>
.pk-column-data ul li.pk-active, .pk-column-data ul li.pk-active .location_title {
    background:#326e51;
    color:white;
}

.location {
    float: left;
    width: 48%;
}

.clearfix {
    clear:both;
}

#district option.hidden {
    display:none;
}

.province {
    margin-right: 20px;
}

.location_title, .location_address {
    margin-bottom:2px;
}

.location_title {
    font-weight: bold;
    color:#326e51;
}
</style>

Bước 04: Sử dụng Javascript để tạo trải nghiệm

Những bước ở trên đã có thể tạo được giao diện hoàn chỉnh + dữ liệu hoàn chỉnh, nhưng thao tác sử dụng chưa có đúng ở bộ lọc, cần áp dụng thêm code javascript sau

<script>
			
    const locations = document.querySelectorAll("#pk_list_map li"); 
    const options = document.querySelectorAll("#district option"); 
    const province = document.getElementById('province');
    const district = document.getElementById('district');

    document.getElementById('province').addEventListener('change', function() {
        var province_id = this.value;
	if(province_id == '') {
	    district.setAttribute('disabled', '')
	    locations.forEach(e => e.classList.remove('hidden'))
	} else {
	    district.removeAttribute('disabled')
	    getDistrict(province_id)
	    getLocation(province_id)
	}
	    district.selectedIndex = 0
    });

    function getDistrict(province_id) {
	options.forEach(function(v){
	    var parent_id = v.getAttribute('data-parent-id')
	    if(v.hasAttribute('data-parent-id')) {
		if(parent_id != province_id) {
		    v.classList.add("hidden")
		} else {
		    v.classList.remove("hidden")
		}
	    }
	})
    }

    document.getElementById('district').addEventListener('change', function() {
	var value = this.value;
	getLocation(value)
    });

    function getLocation(term_id) {
	var province_id = province.value;
	locations.forEach(function(v){
	    var parent_id = v.getAttribute('data-term')
	        parent_id = JSON.parse(parent_id)

	    if(term_id == '') {
		province_id = parseInt(province_id)
		if(parent_id.includes(province_id)) {
		    v.classList.remove("hidden")
		} else {
		    v.classList.add("hidden")
		}
	    } else {
		var parent_id = v.getAttribute('data-term')
		    parent_id = JSON.parse(parent_id)
		    term_id = parseInt(term_id)
		if(parent_id.includes(term_id)) {
		    v.classList.remove("hidden")
		} else {
		    v.classList.add("hidden")
		}
	    }
	})
    }

    const list_map = document.querySelectorAll('#pk_list_map li')
    list_map.forEach(item => {
	item.addEventListener('click', function(){
	    var map = this.getAttribute('data-map')
	    document.querySelector('.pk-column-map iframe').src = map

	    list_map.forEach(e => e.classList.remove('pk-active'))
	    this.classList.add('pk-active')
	})
    });
</script>

Xem video hướng dẫn thực hiện

5/5 - (5 bình chọn)

Bài viết khác

Tổng hợp Download Plugin - Theme cho WordPress : Xem ngay
Nhóm Zalo : Tham gia ngay
TAGS: BẢN ĐỒ CHI NHÁNH BẢN ĐỒ HỆ THỐNG CỬA HÀNG CHI NHÁNH MAPS CỬA HÀNG CHI NHÁNH WORDPRESS HỆ THỐNG CHI NHÁNH HỆ THỐNG CHI NHÁNH GOOGLE MAPS MAPS LOCAL STORE

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

9 trừ ba bằng mấy (trả lời bằng chữ) ?