address
This commit is contained in:
parent
b0eda5e389
commit
a2caec5b74
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Province;
|
||||
use App\Models\District;
|
||||
use App\Models\Subdistrict;
|
||||
use App\Models\City;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AddressController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$addresses = auth()->user()->addresses;
|
||||
return view('account.addresses', compact('addresses'));
|
||||
}
|
||||
|
||||
public function provinces()
|
||||
{
|
||||
$provinces = Province::orderBy('name')->get();
|
||||
|
||||
|
||||
return [
|
||||
'data' => $provinces,
|
||||
];
|
||||
}
|
||||
|
||||
public function cities($provinceId)
|
||||
{
|
||||
$cities = City::where('province_id', $provinceId)->orderBy('name')->get();
|
||||
|
||||
return [
|
||||
'data' => $cities,
|
||||
];
|
||||
}
|
||||
|
||||
public function districts($city_id)
|
||||
{
|
||||
$districts = District::where('city_id', $city_id)->orderBy('name')->get();
|
||||
|
||||
return [
|
||||
'data' => $districts,
|
||||
];
|
||||
}
|
||||
|
||||
public function villages($districtId)
|
||||
{
|
||||
$villages = Subdistrict::where('district_id', $districtId)->orderBy('name')->get();
|
||||
|
||||
return [
|
||||
'data' => $villages,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ class SetLocale
|
|||
|
||||
// Check if locale is in session
|
||||
elseif (Session::has('locale')) {
|
||||
$locale = Session::get('locale');
|
||||
$locale = Session::get('locale') ?? 'id';
|
||||
|
||||
if (in_array($locale, ['en', 'id'])) {
|
||||
App::setLocale($locale);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
|
||||
class Address extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use SoftDeletes;
|
||||
use LogsActivity;
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults();
|
||||
}
|
||||
|
||||
protected $table = 'address';
|
||||
|
||||
protected $fillable = [
|
||||
'label',
|
||||
'name',
|
||||
'address',
|
||||
'province_id',
|
||||
'city_id',
|
||||
'district_id',
|
||||
'subdistrict_id',
|
||||
'province_name',
|
||||
'city_name',
|
||||
'district_name',
|
||||
'subdistrict_name',
|
||||
'postal_code',
|
||||
'phone',
|
||||
'longitude',
|
||||
'latitude',
|
||||
'user_id',
|
||||
'is_primary'
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||
}
|
||||
|
||||
public function province()
|
||||
{
|
||||
return $this->belongsTo(Province::class, 'province_id', 'id');
|
||||
}
|
||||
|
||||
public function city()
|
||||
{
|
||||
return $this->belongsTo(City::class, 'city_id', 'id');
|
||||
}
|
||||
|
||||
public function district()
|
||||
{
|
||||
return $this->belongsTo(District::class, 'district_id', 'id');
|
||||
}
|
||||
|
||||
public function subdistrict()
|
||||
{
|
||||
return $this->belongsTo(Subdistrict::class, 'subdistrict_id', 'id');
|
||||
}
|
||||
|
||||
|
||||
public function getLocationAttribute()
|
||||
{
|
||||
$province = $this->province?->name;
|
||||
$city = $this->city?->name;
|
||||
$district = $this->district?->name;
|
||||
$subdistrict = $this->subdistrict?->name;
|
||||
$postalCode = $this->postal_code;
|
||||
|
||||
return "{$province}, {$city}, {$district}, {$subdistrict}, {$postalCode}";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class City extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['province_id', 'name'];
|
||||
|
||||
public function province()
|
||||
{
|
||||
return $this->belongsTo(Province::class, 'province_id', 'id');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class District extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['city_id', 'name'];
|
||||
|
||||
public function city()
|
||||
{
|
||||
return $this->belongsTo(City::class, 'city_id', 'id');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class PosCode extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'code',
|
||||
'village',
|
||||
'district',
|
||||
'regency',
|
||||
'province',
|
||||
'latitude',
|
||||
'longitude',
|
||||
'elevation',
|
||||
'timezone',
|
||||
];
|
||||
|
||||
public function provinceRef(){
|
||||
return $this->belongsTo(Province::class,"provice_id","id");
|
||||
}
|
||||
|
||||
public function cityRef(){
|
||||
return $this->belongsTo(City::class,"city_id","id");
|
||||
}
|
||||
|
||||
public function districtRef(){
|
||||
return $this->belongsTo(City::class,"district_id","id");
|
||||
}
|
||||
|
||||
public function subdistrictRef(){
|
||||
return $this->belongsTo(City::class,"subdistrict_id","id");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Province extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['name'];
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Subdistrict extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['district_id', 'name'];
|
||||
|
||||
public function district()
|
||||
{
|
||||
return $this->belongsTo(District::class, 'district_id', 'id');
|
||||
}
|
||||
}
|
||||
|
|
@ -56,4 +56,9 @@ class User extends Authenticatable
|
|||
{
|
||||
return $this->hasOne(Customer::class);
|
||||
}
|
||||
|
||||
public function addresses()
|
||||
{
|
||||
return $this->hasMany(Address::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,295 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repositories\Member\Address;
|
||||
|
||||
use App\Models\Address;
|
||||
use App\Models\City;
|
||||
use App\Models\District;
|
||||
use App\Models\Province;
|
||||
use App\Models\Subdistrict;
|
||||
use App\Models\PosCode;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class MemberAddressRepository
|
||||
{
|
||||
public function getList($request)
|
||||
{
|
||||
$model = Address::where('user_id', auth()->user()->id)->orderBy('created_at','desc')->paginate($request->limit);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function geocode($params){
|
||||
|
||||
$lat = @$params["latitude"];
|
||||
$lon = @$params["longitude"];
|
||||
$res = Cache::remember("geocode_$lat\_$lon", 60 * 60 * 24, function () use ($lat, $lon){
|
||||
return Http::get("https://nominatim.openstreetmap.org/reverse",[
|
||||
"email" => "husnusetiawan@gmail.com",
|
||||
"lat" => $lat,
|
||||
"lon" => $lon,
|
||||
"format" => "json"
|
||||
])->json();
|
||||
});
|
||||
|
||||
|
||||
|
||||
try {
|
||||
$address = @$res["address"];
|
||||
|
||||
$posCode = PosCode::where("code", $address['postcode'])->firstOrFail();
|
||||
|
||||
$province_id = $posCode->province_id ?? null;
|
||||
$city_id = $posCode->city_id ?? null;
|
||||
$district_id = $posCode->district_id ?? null;
|
||||
$subdistrict_id = $posCode->subdistrict_id ?? null;
|
||||
if ($address != null) {
|
||||
$addr_province = $address["state"] ?? $address["city"] ?? $posCode->province;
|
||||
$addr_city = $address["city"] ?? $address["county"] ?? $address["city_district"] ?? $posCode->city;
|
||||
$addr_district = $address["suburb"] ?? $address["district"] ?? $posCode->district;
|
||||
$addr_subdistrict = $address["neighbourhood"] ?? $address["village"] ?? $posCode->subdistrict;
|
||||
|
||||
if ($addr_province != null && $province_id == null) {
|
||||
// search by nominatim
|
||||
$province = Province::whereRaw('name ILIKE ?', ['%' . trim($addr_province) . '%'])->first();
|
||||
|
||||
// search by poscode
|
||||
if ($province == null) {
|
||||
$province = Province::whereRaw('name ILIKE ?', ['%' . trim($posCode->province) . '%'])->first();
|
||||
}
|
||||
|
||||
$province_id = $posCode->province_id ?? $province->id ?? null;
|
||||
|
||||
}
|
||||
|
||||
if ($addr_city != null && $city_id == null) {
|
||||
// search by nominatim
|
||||
$city = City::whereRaw('name ILIKE ?', ['%' . trim($addr_city) . '%'])
|
||||
->where("province_id", $province_id)
|
||||
->first();
|
||||
|
||||
// search by poscode
|
||||
if ($city == null) {
|
||||
$city = City::whereRaw('name ILIKE ?', ['%' . trim($posCode->city) . '%'])
|
||||
->where("province_id", $province_id)
|
||||
->first();
|
||||
}
|
||||
|
||||
$city_id = $posCode->city_id ?? $city->id ?? null;
|
||||
}
|
||||
|
||||
|
||||
if ($addr_district != null && $district_id == null) {
|
||||
// search by nominatim
|
||||
$district = District::whereRaw('name ILIKE ?', ['%' . trim($addr_district) . '%'])
|
||||
->where("city_id", $city_id)
|
||||
->first();
|
||||
|
||||
|
||||
|
||||
// search by poscode
|
||||
if ($district == null) {
|
||||
$district = District::whereRaw('name ILIKE ?', ['%' . trim($posCode->district) . '%'])
|
||||
->where("city_id", $city_id)
|
||||
->first();
|
||||
}
|
||||
|
||||
|
||||
|
||||
$district_id = $posCode->district_id ?? $district->id ?? null;
|
||||
}
|
||||
|
||||
if ($addr_subdistrict != null && $subdistrict_id == null) {
|
||||
// search by nominatim
|
||||
$subdistrict = Subdistrict::whereRaw('name ILIKE ?', ['%' . trim($addr_subdistrict) . '%'])
|
||||
->where("district_id", $district_id)
|
||||
->first();
|
||||
|
||||
// search by poscode
|
||||
if ($subdistrict == null) {
|
||||
$subdistrict = Subdistrict::whereRaw('name ILIKE ?', ['%' . trim($posCode->subdistrict) . '%'])
|
||||
->where("district_id", $district_id)
|
||||
->first();
|
||||
}
|
||||
|
||||
$subdistrict_id = $posCode->subdistrict_id ?? $subdistrict->id ?? null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$address = new Address([
|
||||
'label' => "",
|
||||
'name' => "",
|
||||
'address' => $address["road"] ?? $res["display_name"],
|
||||
'province_id' => $province_id,
|
||||
'city_id' => $city_id,
|
||||
'district_id' => $district_id,
|
||||
'subdistrict_id' => $subdistrict_id,
|
||||
|
||||
'postal_code' => $address['postcode'],
|
||||
'phone' => "",
|
||||
'latitude' => $res['lat'],
|
||||
'longitude' => $res['lon'],
|
||||
'user_id' => auth()->user()->id,
|
||||
'is_primary' => false
|
||||
]);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
|
||||
abort(404, 'lokasi tidak didukung');
|
||||
}
|
||||
|
||||
return $address;
|
||||
}
|
||||
|
||||
public function create($data)
|
||||
{
|
||||
$model = DB::transaction(function () use ($data) {
|
||||
|
||||
$model = Address::create([
|
||||
'label' => $data['label'],
|
||||
'name' => $data['name'],
|
||||
'address' => $data['address'],
|
||||
'province_id' => $data['province_id'],
|
||||
'city_id' => $data['city_id'],
|
||||
'district_id' => $data['district_id'],
|
||||
'subdistrict_id' => $data['subdistrict_id'],
|
||||
'postal_code' => $data['postal_code'],
|
||||
'phone' => $data['phone'],
|
||||
'latitude' => $data['latitude'],
|
||||
'longitude' => $data['longitude'],
|
||||
'user_id' => auth()->user()->id,
|
||||
'is_primary' => $data['is_primary']
|
||||
]);
|
||||
|
||||
return $model;
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function update($id ,$data)
|
||||
{
|
||||
$model = DB::transaction(function () use ($id, $data) {
|
||||
|
||||
$model = Address::findOrFail($id);
|
||||
$model->label = $data['label'] ?? $model->label;
|
||||
$model->name = $data['name'] ?? $model->name;
|
||||
$model->address = $data['address'] ?? $model->address;
|
||||
$model->province_id = $data['province_id'] ?? $model->province_id;
|
||||
$model->city_id = $data['city_id'] ?? $model->city_id;
|
||||
$model->district_id = $data['district_id'] ?? $model->district_id;
|
||||
$model->subdistrict_id = $data['subdistrict_id'] ?? $model->subdistrict_id;
|
||||
$model->postal_code = $data['postal_code'] ?? $model->postal_code;
|
||||
$model->phone = $data['phone'] ?? $model->phone;
|
||||
$model->latitude = $data['latitude'] ?? $model->latitude;
|
||||
$model->longitude = $data['longitude'] ?? $model->longitude;
|
||||
$model->is_primary = $data['is_primary'] ?? $model->is_primary;
|
||||
$model->save();
|
||||
return $model;
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function setPrimary($id)
|
||||
{
|
||||
$model = DB::transaction(function () use ($id) {
|
||||
|
||||
$model = Address::findOrFail($id);
|
||||
|
||||
Address::where("user_id", $model->user_id)->update([
|
||||
"is_primary" => 0
|
||||
]);
|
||||
|
||||
|
||||
$model->is_primary = 1;
|
||||
$model->save();
|
||||
|
||||
return $model;
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function delete($model)
|
||||
{
|
||||
$model = DB::transaction(function () use ($model) {
|
||||
$model->delete();
|
||||
return $model;
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function getProvince($request)
|
||||
{
|
||||
$model = Province::orderBy('name','desc')->where("is_new",true)->paginate($request->limit);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function getCity($request)
|
||||
{
|
||||
$all = $request->all();
|
||||
|
||||
$model = City::orderBy('name','desc')->where("is_new",true)
|
||||
->where(function($query) use ($all){
|
||||
if (@$all["province_id"])
|
||||
$query->where("province_id", $all["province_id"]);
|
||||
})->paginate($request->limit);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function getDistrict($request)
|
||||
{
|
||||
$all = $request->all();
|
||||
|
||||
$model = District::orderBy('name','desc')->where("is_new",true)
|
||||
->where(function($query) use ($all){
|
||||
if (@$all["city_id"])
|
||||
$query->where("city_id", $all["city_id"]);
|
||||
})->paginate($request->limit);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function getSubdistrict($request)
|
||||
{
|
||||
$all = $request->all();
|
||||
$model = Subdistrict::orderBy('name','desc')->where("is_new",true)
|
||||
->where(function($query) use ($all){
|
||||
if (@$all["district_id"])
|
||||
$query->where("district_id", $all["district_id"]);
|
||||
})
|
||||
->paginate($request->limit);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function getPoscode($request)
|
||||
{
|
||||
|
||||
$all = $request->all();
|
||||
$model = PosCode::orderBy('province','desc')
|
||||
->where(function($query) use ($all){
|
||||
if (@$all["village"])
|
||||
$query->where("village", $all["village"]);
|
||||
|
||||
if (@$all["district"])
|
||||
$query->where("district", $all["district"]);
|
||||
|
||||
if (@$all["regency"])
|
||||
$query->where("regency", $all["regency"]);
|
||||
})
|
||||
->paginate($request->limit);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'page_title' => 'Addresses',
|
||||
'shipping_address' => 'Shipping address',
|
||||
'primary' => 'Primary',
|
||||
'edit' => 'Edit',
|
||||
'country' => 'Country',
|
||||
'select_country' => 'Select country...',
|
||||
'province' => 'Province',
|
||||
'select_province' => 'Select province...',
|
||||
'city' => 'City',
|
||||
'select_city' => 'Select city...',
|
||||
'district' => 'District',
|
||||
'select_district' => 'Select district...',
|
||||
'village' => 'Village',
|
||||
'select_village' => 'Select village...',
|
||||
'zip_code' => 'ZIP code',
|
||||
'address' => 'Address',
|
||||
'set_as_primary_address' => 'Set as primary address',
|
||||
'save_changes' => 'Save changes',
|
||||
'close' => 'Close',
|
||||
'alternative_shipping_address' => 'Alternative shipping address',
|
||||
'add_address' => 'Add address',
|
||||
'please_select_country' => 'Please select your country!',
|
||||
'please_select_province' => 'Please select your province!',
|
||||
'please_select_city' => 'Please select your city!',
|
||||
'please_select_district' => 'Please select your district!',
|
||||
'please_select_village' => 'Please select your village!',
|
||||
'please_enter_zip_code' => 'Please enter your ZIP code!',
|
||||
'please_enter_address' => 'Please enter your address!',
|
||||
'regions' => [
|
||||
'africa' => 'Africa',
|
||||
'asia' => 'Asia',
|
||||
'europe' => 'Europe',
|
||||
'north_america' => 'North America',
|
||||
'south_america' => 'South America',
|
||||
'oceania' => 'Oceania'
|
||||
]
|
||||
];
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'page_title' => 'Alamat',
|
||||
'shipping_address' => 'Alamat Pengiriman',
|
||||
'primary' => 'Utama',
|
||||
'edit' => 'Edit',
|
||||
'country' => 'Negara',
|
||||
'select_country' => 'Pilih negara...',
|
||||
'province' => 'Provinsi',
|
||||
'select_province' => 'Pilih provinsi...',
|
||||
'city' => 'Kota',
|
||||
'select_city' => 'Pilih kota...',
|
||||
'district' => 'Kecamatan',
|
||||
'select_district' => 'Pilih kecamatan...',
|
||||
'village' => 'Kelurahan',
|
||||
'select_village' => 'Pilih kelurahan...',
|
||||
'zip_code' => 'Kode Pos',
|
||||
'address' => 'Alamat',
|
||||
'set_as_primary_address' => 'Jadikan alamat utama',
|
||||
'save_changes' => 'Simpan perubahan',
|
||||
'close' => 'Tutup',
|
||||
'alternative_shipping_address' => 'Alamat Pengiriman Alternatif',
|
||||
'add_address' => 'Tambah alamat',
|
||||
'please_select_country' => 'Silakan pilih negara Anda!',
|
||||
'please_select_province' => 'Silakan pilih provinsi Anda!',
|
||||
'please_select_city' => 'Silakan pilih kota Anda!',
|
||||
'please_select_district' => 'Silakan pilih kecamatan Anda!',
|
||||
'please_select_village' => 'Silakan pilih kelurahan Anda!',
|
||||
'please_enter_zip_code' => 'Silakan masukkan kode pos Anda!',
|
||||
'please_enter_address' => 'Silakan masukkan alamat Anda!',
|
||||
'regions' => [
|
||||
'africa' => 'Afrika',
|
||||
'asia' => 'Asia',
|
||||
'europe' => 'Eropa',
|
||||
'north_america' => 'Amerika Utara',
|
||||
'south_america' => 'Amerika Selatan',
|
||||
'oceania' => 'Oseania'
|
||||
]
|
||||
];
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
@extends('layouts.account', ['title' => 'Account - Addresses'])
|
||||
@extends('layouts.account', ['title' => __('addresses.page_title')])
|
||||
|
||||
@section('content')
|
||||
<!-- Addresses content -->
|
||||
|
|
@ -6,198 +6,177 @@
|
|||
<div class="ps-lg-3 ps-xl-0">
|
||||
|
||||
<!-- Page title -->
|
||||
<h1 class="h2 mb-1 mb-sm-2">Addresses</h1>
|
||||
<h1 class="h2 mb-1 mb-sm-2">{{ __('addresses.page_title') }}</h1>
|
||||
|
||||
<!-- Primary shipping address -->
|
||||
<div class="border-bottom py-4">
|
||||
<div class="nav flex-nowrap align-items-center justify-content-between pb-1 mb-3">
|
||||
<div class="d-flex align-items-center gap-3 me-4">
|
||||
<h2 class="h6 mb-0">Shipping address</h2>
|
||||
<span class="badge text-bg-info rounded-pill">Primary</span>
|
||||
@foreach ($addresses as $address)
|
||||
<div class="border-bottom py-4">
|
||||
<div class="nav flex-nowrap align-items-center justify-content-between pb-1 mb-3">
|
||||
<div class="d-flex align-items-center gap-3 me-4">
|
||||
<h2 class="h6 mb-0">{{ $address->label }}</h2>
|
||||
@if ($address->is_primary)
|
||||
<span class="badge text-bg-info rounded-pill">{{ __('addresses.primary') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
<a class="nav-link hiding-collapse-toggle text-decoration-underline p-0 collapsed primaryAddressEditButton"
|
||||
data-address-id="{{ $address->id }}" href=".primary-address-{{ $address->id }}"
|
||||
data-bs-toggle="collapse" aria-expanded="false"
|
||||
aria-controls="primaryAddressPreview{{ $address->id }} primaryAddressEdit{{ $address->id }}">{{ __('addresses.edit') }}</a>
|
||||
</div>
|
||||
<div class="collapse primary-address-{{ $address->id }} show"
|
||||
id="primaryAddressPreview{{ $address->id }}">
|
||||
<ul class="list-unstyled fs-sm m-0">
|
||||
<li>{{ $address->location }}</li>
|
||||
<li>{{ $address->address }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="collapse primary-address-{{ $address->id }}" id="primaryAddressEdit{{ $address->id }}">
|
||||
<form class="row g-3 g-sm-4 needs-validation" novalidate>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="position-relative">
|
||||
<label class="form-label">{{ __('addresses.province') }}</label>
|
||||
<select class="form-select province-select" data-select='{"searchEnabled": true}'
|
||||
aria-label="Select city" required data-address-id="{{ $address->id }}">
|
||||
<option value="">{{ __('addresses.select_province') }}</option>
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_select_province') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="position-relative">
|
||||
<label class="form-label">{{ __('addresses.city') }}</label>
|
||||
<select class="form-select city-select" data-select='{"searchEnabled": true}'
|
||||
aria-label="Select city" required data-address-id="{{ $address->id }}">
|
||||
<option value="">{{ __('addresses.select_city') }}</option>
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_select_city') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="position-relative">
|
||||
<label class="form-label">{{ __('addresses.district') }}</label>
|
||||
<select class="form-select district-select" data-select='{"searchEnabled": true}'
|
||||
aria-label="Select district" required data-address-id="{{ $address->id }}">
|
||||
<option value="">{{ __('addresses.select_district') }}</option>
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_select_district') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="position-relative">
|
||||
<label class="form-label">{{ __('addresses.village') }}</label>
|
||||
<select class="form-select village-select" data-select='{"searchEnabled": true}'
|
||||
aria-label="Select village" required data-address-id="{{ $address->id }}">
|
||||
<option value="">{{ __('addresses.select_village') }}</option>
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_select_village') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="position-relative">
|
||||
<label for="psa-zip-{{ $address->id }}"
|
||||
class="form-label">{{ __('addresses.zip_code') }}</label>
|
||||
<input type="text" class="form-control" id="psa-zip-{{ $address->id }}"
|
||||
value="{{ $address->postal_code }}" required>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_enter_zip_code') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div class="position-relative">
|
||||
<label for="psa-address-{{ $address->id }}"
|
||||
class="form-label">{{ __('addresses.address') }}</label>
|
||||
<input type="text" class="form-control" id="psa-address-{{ $address->id }}"
|
||||
value="{{ $address->address }}" required>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_enter_address') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check mb-0">
|
||||
<input type="checkbox" class="form-check-input" id="set-primary-{{ $address->id }}"
|
||||
{{ $address->is_primary ? 'checked' : '' }}>
|
||||
<label for="set-primary-{{ $address->id }}"
|
||||
class="form-check-label">{{ __('addresses.set_as_primary_address') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="d-flex gap-3 pt-2 pt-sm-0">
|
||||
<button type="submit"
|
||||
class="btn btn-primary">{{ __('addresses.save_changes') }}</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-toggle="collapse"
|
||||
data-bs-target=".primary-address-{{ $address->id }}" aria-expanded="true"
|
||||
aria-controls="primaryAddressPreview{{ $address->id }} primaryAddressEdit{{ $address->id }}">{{ __('addresses.close') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<a class="nav-link hiding-collapse-toggle text-decoration-underline p-0 collapsed" href=".primary-address"
|
||||
data-bs-toggle="collapse" aria-expanded="false"
|
||||
aria-controls="primaryAddressPreview primaryAddressEdit">Edit</a>
|
||||
</div>
|
||||
<div class="collapse primary-address show" id="primaryAddressPreview">
|
||||
<ul class="list-unstyled fs-sm m-0">
|
||||
<li>New York 11741, USA</li>
|
||||
<li>396 Lillian Bolavandy, Holbrook</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="collapse primary-address" id="primaryAddressEdit">
|
||||
<form class="row g-3 g-sm-4 needs-validation" novalidate>
|
||||
<div class="col-sm-6">
|
||||
<div class="position-relative">
|
||||
<label class="form-label">Country</label>
|
||||
<select class="form-select" data-select='{"searchEnabled": true}'
|
||||
aria-label="Select country" required>
|
||||
<option value="">Select country...</option>
|
||||
<optgroup label="Africa">
|
||||
<option value="Nigeria">Nigeria</option>
|
||||
<option value="South Africa">South Africa</option>
|
||||
<option value="Kenya">Kenya</option>
|
||||
<option value="Egypt">Egypt</option>
|
||||
<option value="Ethiopia">Ethiopia</option>
|
||||
</optgroup>
|
||||
<optgroup label="Asia">
|
||||
<option value="China">China</option>
|
||||
<option value="India">India</option>
|
||||
<option value="Japan">Japan</option>
|
||||
<option value="South Korea">South Korea</option>
|
||||
<option value="Saudi Arabia">Saudi Arabia</option>
|
||||
</optgroup>
|
||||
<optgroup label="Europe">
|
||||
<option value="Germany">Germany</option>
|
||||
<option value="France">France</option>
|
||||
<option value="United Kingdom">United Kingdom</option>
|
||||
<option value="Italy">Italy</option>
|
||||
<option value="Spain">Spain</option>
|
||||
</optgroup>
|
||||
<optgroup label="North America">
|
||||
<option value="United States" selected>United States</option>
|
||||
<option value="Canada">Canada</option>
|
||||
<option value="Mexico">Mexico</option>
|
||||
<option value="Jamaica">Jamaica</option>
|
||||
<option value="Costa Rica">Costa Rica</option>
|
||||
</optgroup>
|
||||
<optgroup label="South America">
|
||||
<option value="Brazil">Brazil</option>
|
||||
<option value="Argentina">Argentina</option>
|
||||
<option value="Colombia">Colombia</option>
|
||||
<option value="Chile">Chile</option>
|
||||
<option value="Peru">Peru</option>
|
||||
</optgroup>
|
||||
<optgroup label="Oceania">
|
||||
<option value="Australia">Australia</option>
|
||||
<option value="New Zealand">New Zealand</option>
|
||||
<option value="Papua New Guinea">Papua New Guinea</option>
|
||||
<option value="Fiji">Fiji</option>
|
||||
<option value="Solomon Islands">Solomon Islands</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<div class="invalid-feedback">Please select your country!</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="position-relative">
|
||||
<label class="form-label">City</label>
|
||||
<select class="form-select" data-select='{"searchEnabled": true}' aria-label="Select city"
|
||||
required>
|
||||
<option value="">Select city...</option>
|
||||
<option value="Austin">Austin</option>
|
||||
<option value="Charlotte">Charlotte</option>
|
||||
<option value="Chicago">Chicago</option>
|
||||
<option value="Columbus">Columbus</option>
|
||||
<option value="Dallas">Dallas</option>
|
||||
<option value="Houston">Houston</option>
|
||||
<option value="Jacksonville">Jacksonville</option>
|
||||
<option value="Los Angeles">Los Angeles</option>
|
||||
<option value="New York" selected>New York</option>
|
||||
<option value="Orlando">Orlando</option>
|
||||
<option value="Philadelphia">Philadelphia</option>
|
||||
<option value="Phoenix">Phoenix</option>
|
||||
<option value="San Antonio">San Antonio</option>
|
||||
<option value="San Diego">San Diego</option>
|
||||
<option value="San Jose">San Jose</option>
|
||||
</select>
|
||||
<div class="invalid-feedback">Please select your city!</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="position-relative">
|
||||
<label for="psa-zip" class="form-label">ZIP code</label>
|
||||
<input type="text" class="form-control" id="psa-zip" value="11741" required>
|
||||
<div class="invalid-feedback">Please enter your ZIP code!</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div class="position-relative">
|
||||
<label for="psa-address" class="form-label">Address</label>
|
||||
<input type="text" class="form-control" id="psa-address"
|
||||
value="396 Lillian Bolavandy, Holbrook" required>
|
||||
<div class="invalid-feedback">Please enter your address!</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check mb-0">
|
||||
<input type="checkbox" class="form-check-input" id="set-primary-1" checked>
|
||||
<label for="set-primary-1" class="form-check-label">Set as primary
|
||||
address</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="d-flex gap-3 pt-2 pt-sm-0">
|
||||
<button type="submit" class="btn btn-primary">Save changes</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-toggle="collapse"
|
||||
data-bs-target=".primary-address" aria-expanded="true"
|
||||
aria-controls="primaryAddressPreview primaryAddressEdit">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
|
||||
|
||||
<!-- Add address button -->
|
||||
<div class="nav pt-4">
|
||||
<a class="nav-link animate-underline fs-base px-0" href="#newAddressModal" data-bs-toggle="modal">
|
||||
<i class="ci-plus fs-lg ms-n1 me-2"></i>
|
||||
<span class="animate-target">{{ __('addresses.add_address') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alternative shipping address -->
|
||||
<div class="border-bottom py-4">
|
||||
<div class="nav flex-nowrap align-items-center justify-content-between pb-1 mb-3">
|
||||
<div class="d-flex align-items-center gap-3 me-4">
|
||||
<h2 class="h6 mb-0">Alternative shipping address</h2>
|
||||
</div>
|
||||
<a class="nav-link hiding-collapse-toggle text-decoration-underline p-0 collapsed"
|
||||
href=".alternative-address" data-bs-toggle="collapse" aria-expanded="false"
|
||||
aria-controls="alternativeAddressPreview alternativeAddressEdit">Edit</a>
|
||||
<!-- New Address Modal -->
|
||||
<div class="modal fade" id="newAddressModal" tabindex="-1" aria-labelledby="newAddressModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="newAddressModalLabel">{{ __('addresses.add_address') }}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="collapse alternative-address show" id="alternativeAddressPreview">
|
||||
<ul class="list-unstyled fs-sm m-0">
|
||||
<li>Florida 32806, USA</li>
|
||||
<li>514 S. Magnolia St., Orlando</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="collapse alternative-address" id="alternativeAddressEdit">
|
||||
<div class="modal-body">
|
||||
<form class="row g-3 g-sm-4 needs-validation" novalidate>
|
||||
<div class="col-sm-6">
|
||||
<div class="position-relative">
|
||||
<label class="form-label">Country</label>
|
||||
<label class="form-label">{{ __('addresses.country') }}</label>
|
||||
<select class="form-select" data-select='{"searchEnabled": true}'
|
||||
aria-label="Select country" required>
|
||||
<option value="">Select country...</option>
|
||||
<optgroup label="Africa">
|
||||
<option value="">{{ __('addresses.select_country') }}</option>
|
||||
<optgroup label="{{ __('addresses.regions.africa') }}">
|
||||
<option value="Nigeria">Nigeria</option>
|
||||
<option value="South Africa">South Africa</option>
|
||||
<option value="Kenya">Kenya</option>
|
||||
<option value="Egypt">Egypt</option>
|
||||
<option value="Ethiopia">Ethiopia</option>
|
||||
</optgroup>
|
||||
<optgroup label="Asia">
|
||||
<optgroup label="{{ __('addresses.regions.asia') }}">
|
||||
<option value="China">China</option>
|
||||
<option value="India">India</option>
|
||||
<option value="Japan">Japan</option>
|
||||
<option value="South Korea">South Korea</option>
|
||||
<option value="Saudi Arabia">Saudi Arabia</option>
|
||||
</optgroup>
|
||||
<optgroup label="Europe">
|
||||
<optgroup label="{{ __('addresses.regions.europe') }}">
|
||||
<option value="Germany">Germany</option>
|
||||
<option value="France">France</option>
|
||||
<option value="United Kingdom">United Kingdom</option>
|
||||
<option value="Italy">Italy</option>
|
||||
<option value="Spain">Spain</option>
|
||||
</optgroup>
|
||||
<optgroup label="North America">
|
||||
<option value="United States" selected>United States</option>
|
||||
<optgroup label="{{ __('addresses.regions.north_america') }}">
|
||||
<option value="United States">United States</option>
|
||||
<option value="Canada">Canada</option>
|
||||
<option value="Mexico">Mexico</option>
|
||||
<option value="Jamaica">Jamaica</option>
|
||||
<option value="Costa Rica">Costa Rica</option>
|
||||
</optgroup>
|
||||
<optgroup label="South America">
|
||||
<optgroup label="{{ __('addresses.regions.south_america') }}">
|
||||
<option value="Brazil">Brazil</option>
|
||||
<option value="Argentina">Argentina</option>
|
||||
<option value="Colombia">Colombia</option>
|
||||
<option value="Chile">Chile</option>
|
||||
<option value="Peru">Peru</option>
|
||||
</optgroup>
|
||||
<optgroup label="Oceania">
|
||||
<optgroup label="{{ __('addresses.regions.oceania') }}">
|
||||
<option value="Australia">Australia</option>
|
||||
<option value="New Zealand">New Zealand</option>
|
||||
<option value="Papua New Guinea">Papua New Guinea</option>
|
||||
|
|
@ -205,15 +184,15 @@
|
|||
<option value="Solomon Islands">Solomon Islands</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<div class="invalid-feedback">Please select your country!</div>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_select_country') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="position-relative">
|
||||
<label class="form-label">City</label>
|
||||
<label class="form-label">{{ __('addresses.city') }}</label>
|
||||
<select class="form-select" data-select='{"searchEnabled": true}'
|
||||
aria-label="Select city" required>
|
||||
<option value="">Select city...</option>
|
||||
<option value="">{{ __('addresses.select_city') }}</option>
|
||||
<option value="Austin">Austin</option>
|
||||
<option value="Charlotte">Charlotte</option>
|
||||
<option value="Chicago">Chicago</option>
|
||||
|
|
@ -223,61 +202,353 @@
|
|||
<option value="Jacksonville">Jacksonville</option>
|
||||
<option value="Los Angeles">Los Angeles</option>
|
||||
<option value="New York">New York</option>
|
||||
<option value="Orlando" selected>Orlando</option>
|
||||
<option value="Orlando">Orlando</option>
|
||||
<option value="Philadelphia">Philadelphia</option>
|
||||
<option value="Phoenix">Phoenix</option>
|
||||
<option value="San Antonio">San Antonio</option>
|
||||
<option value="San Diego">San Diego</option>
|
||||
<option value="San Jose">San Jose</option>
|
||||
</select>
|
||||
<div class="invalid-feedback">Please select your city!</div>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_select_city') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="position-relative">
|
||||
<label for="asa-zip" class="form-label">ZIP code</label>
|
||||
<input type="text" class="form-control" id="asa-zip" value="32806" required>
|
||||
<div class="invalid-feedback">Please enter your ZIP code!</div>
|
||||
<label for="new-zip" class="form-label">{{ __('addresses.zip_code') }}</label>
|
||||
<input type="text" class="form-control" id="new-zip" required>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_enter_zip_code') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div class="position-relative">
|
||||
<label for="asa-address" class="form-label">Address</label>
|
||||
<input type="text" class="form-control" id="asa-address" value="514 S. Magnolia St."
|
||||
required>
|
||||
<div class="invalid-feedback">Please enter your address!</div>
|
||||
<label for="new-address" class="form-label">{{ __('addresses.address') }}</label>
|
||||
<input type="text" class="form-control" id="new-address" required>
|
||||
<div class="invalid-feedback">{{ __('addresses.please_enter_address') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check mb-0">
|
||||
<input type="checkbox" class="form-check-input" id="set-primary-2">
|
||||
<label for="set-primary-2" class="form-check-label">Set as primary
|
||||
address</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="d-flex gap-3 pt-2 pt-sm-0">
|
||||
<button type="submit" class="btn btn-primary">Save changes</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-toggle="collapse"
|
||||
data-bs-target=".alternative-address" aria-expanded="true"
|
||||
aria-controls="alternativeAddressPreview alternativeAddressEdit">Close</button>
|
||||
<input type="checkbox" class="form-check-input" id="set-primary-new">
|
||||
<label for="set-primary-new"
|
||||
class="form-check-label">{{ __('addresses.set_as_primary_address') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add address button -->
|
||||
<div class="nav pt-4">
|
||||
<a class="nav-link animate-underline fs-base px-0" href="#newAddressModal" data-bs-toggle="modal">
|
||||
<i class="ci-plus fs-lg ms-n1 me-2"></i>
|
||||
<span class="animate-target">Add address</span>
|
||||
</a>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary"
|
||||
data-bs-dismiss="modal">{{ __('addresses.close') }}</button>
|
||||
<button type="submit" class="btn btn-primary">{{ __('addresses.save_changes') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Add click event listener to edit buttons
|
||||
document.addEventListener('click', function(e) {
|
||||
// Check if clicked element is an edit button
|
||||
if (e.target.closest('.primaryAddressEditButton')) {
|
||||
// Find the button element to get its data attribute
|
||||
const button = e.target.closest('.primaryAddressEditButton');
|
||||
console.log('Button clicked:', button);
|
||||
|
||||
// Get address ID from data attribute
|
||||
const addressId = button.getAttribute('data-address-id');
|
||||
console.log('Address ID:', addressId);
|
||||
|
||||
if (addressId) {
|
||||
loadProvincesForAddress(addressId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function loadProvincesForAddress(addressId) {
|
||||
console.log('Loading provinces for address ID:', addressId);
|
||||
const provinceSelect = document.querySelector(`.province-select[data-address-id="${addressId}"]`);
|
||||
if (!provinceSelect) {
|
||||
console.log('Province select not found for address ID:', addressId);
|
||||
return;
|
||||
}
|
||||
|
||||
const currentProvinceId = '{{ $address->province_id }}';
|
||||
const currentCityId = '{{ $address->city_id }}';
|
||||
const currentDistrictId = '{{ $address->district_id }}';
|
||||
const currentVillageId = '{{ $address->subdistrict_id }}';
|
||||
|
||||
// Load provinces via AJAX
|
||||
fetch('/addresses/provinces')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (window.Choices) {
|
||||
// Destroy existing instance if any
|
||||
if (provinceSelect.choices) {
|
||||
provinceSelect.choices.destroy();
|
||||
}
|
||||
}
|
||||
// Clear and set options
|
||||
provinceSelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_province') }}</option>';
|
||||
|
||||
data.data.forEach(province => {
|
||||
const option = document.createElement('option');
|
||||
option.value = province.id;
|
||||
option.textContent = province.name;
|
||||
|
||||
// Select current province if it matches
|
||||
if (province.id == currentProvinceId) {
|
||||
option.selected = true;
|
||||
}
|
||||
|
||||
provinceSelect.appendChild(option);
|
||||
});
|
||||
|
||||
console.log(provinceSelect);
|
||||
|
||||
// Initialize Choices.js
|
||||
if (window.Choices) {
|
||||
// Destroy existing instance if any
|
||||
if (provinceSelect.choices) {
|
||||
provinceSelect.choices.destroy();
|
||||
}
|
||||
// Initialize new Choices instance
|
||||
provinceSelect.choices = new window.Choices(provinceSelect, {
|
||||
searchEnabled: true,
|
||||
itemSelectText: 'Select an option',
|
||||
noResultsText: 'No results found',
|
||||
shouldSort: false
|
||||
});
|
||||
}
|
||||
|
||||
// Load cities if province is selected
|
||||
if (currentProvinceId) {
|
||||
loadCitiesForAddress(addressId, currentProvinceId, currentCityId, currentDistrictId,
|
||||
currentVillageId);
|
||||
}
|
||||
})
|
||||
.catch(error => console.log('Error loading provinces:', error));
|
||||
}
|
||||
|
||||
// Add change event listener to province selects
|
||||
document.addEventListener('change', function(e) {
|
||||
if (e.target.classList.contains('province-select')) {
|
||||
const addressId = e.target.dataset.addressId;
|
||||
const provinceId = e.target.value;
|
||||
|
||||
// Clear district and village selects
|
||||
const citySelect = document.querySelector(
|
||||
`.city-select[data-address-id="${addressId}"]`);
|
||||
const districtSelect = document.querySelector(
|
||||
`.district-select[data-address-id="${addressId}"]`);
|
||||
const villageSelect = document.querySelector(
|
||||
`.village-select[data-address-id="${addressId}"]`);
|
||||
|
||||
if (citySelect) {
|
||||
citySelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_city') }}</option>';
|
||||
}
|
||||
if (districtSelect) {
|
||||
districtSelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_district') }}</option>';
|
||||
}
|
||||
if (villageSelect) {
|
||||
villageSelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_village') }}</option>';
|
||||
}
|
||||
|
||||
// Load cities if province is selected
|
||||
if (provinceId) {
|
||||
loadCitiesForAddress(addressId, provinceId);
|
||||
}
|
||||
}
|
||||
|
||||
if (e.target.classList.contains('city-select')) {
|
||||
const addressId = e.target.dataset.addressId;
|
||||
const cityId = e.target.value;
|
||||
|
||||
// Clear district and village selects
|
||||
const districtSelect = document.querySelector(
|
||||
`.district-select[data-address-id="${addressId}"]`);
|
||||
const villageSelect = document.querySelector(
|
||||
`.village-select[data-address-id="${addressId}"]`);
|
||||
|
||||
if (districtSelect) {
|
||||
districtSelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_district') }}</option>';
|
||||
}
|
||||
if (villageSelect) {
|
||||
villageSelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_village') }}</option>';
|
||||
}
|
||||
|
||||
// Load districts if city is selected
|
||||
if (cityId) {
|
||||
loadDistrictsForAddress(addressId, cityId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add change event listener to district selects
|
||||
document.addEventListener('change', function(e) {
|
||||
if (e.target.classList.contains('district-select')) {
|
||||
const addressId = e.target.dataset.addressId;
|
||||
const districtId = e.target.value;
|
||||
|
||||
// Clear village select
|
||||
const villageSelect = document.querySelector(
|
||||
`.village-select[data-address-id="${addressId}"]`);
|
||||
if (villageSelect) {
|
||||
villageSelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_village') }}</option>';
|
||||
}
|
||||
|
||||
// Load villages if district is selected
|
||||
if (districtId) {
|
||||
loadVillages(addressId, districtId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function loadCitiesForAddress(addressId, provinceId, currentCityId = null, currentDistrictId = null,
|
||||
currentVillageId = null) {
|
||||
fetch(`/addresses/cities/${provinceId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const citySelect = document.querySelector(
|
||||
`.city-select[data-address-id="${addressId}"]`);
|
||||
if (citySelect) {
|
||||
// Clear and set options
|
||||
citySelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_city') }}</option>';
|
||||
|
||||
data.data.forEach(city => {
|
||||
const option = document.createElement('option');
|
||||
option.value = city.id;
|
||||
option.textContent = city.name;
|
||||
|
||||
if (currentCityId && city.id == currentCityId) {
|
||||
option.selected = true;
|
||||
}
|
||||
|
||||
citySelect.appendChild(option);
|
||||
});
|
||||
|
||||
// Initialize Choices.js
|
||||
if (window.Choices) {
|
||||
// Destroy existing instance if any
|
||||
if (citySelect.choices) {
|
||||
citySelect.choices.destroy();
|
||||
}
|
||||
// Initialize new Choices instance
|
||||
citySelect.choices = new window.Choices(citySelect, {
|
||||
searchEnabled: true,
|
||||
itemSelectText: 'Select an option',
|
||||
noResultsText: 'No results found',
|
||||
shouldSort: false
|
||||
});
|
||||
}
|
||||
|
||||
// Load districts if city is selected
|
||||
if (currentCityId) {
|
||||
loadDistrictsForAddress(addressId, currentCityId, currentDistrictId,
|
||||
currentVillageId);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => console.log('Error loading cities:', error));
|
||||
}
|
||||
|
||||
function loadDistrictsForAddress(addressId, cityId, currentDistrictId = null, currentVillageId = null) {
|
||||
fetch(`/addresses/districts/${cityId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const districtSelect = document.querySelector(
|
||||
`.district-select[data-address-id="${addressId}"]`);
|
||||
if (districtSelect) {
|
||||
// Clear and set options
|
||||
districtSelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_district') }}</option>';
|
||||
|
||||
data.data.forEach(district => {
|
||||
const option = document.createElement('option');
|
||||
option.value = district.id;
|
||||
option.textContent = district.name;
|
||||
|
||||
if (currentDistrictId && district.id == currentDistrictId) {
|
||||
option.selected = true;
|
||||
}
|
||||
|
||||
districtSelect.appendChild(option);
|
||||
});
|
||||
|
||||
// Initialize Choices.js
|
||||
if (window.Choices) {
|
||||
// Destroy existing instance if any
|
||||
if (districtSelect.choices) {
|
||||
districtSelect.choices.destroy();
|
||||
}
|
||||
// Initialize new Choices instance
|
||||
districtSelect.choices = new window.Choices(districtSelect, {
|
||||
searchEnabled: true,
|
||||
itemSelectText: 'Select an option',
|
||||
noResultsText: 'No results found',
|
||||
shouldSort: false
|
||||
});
|
||||
}
|
||||
|
||||
// Load villages if district is selected
|
||||
if (currentDistrictId) {
|
||||
loadVillages(addressId, currentDistrictId, currentVillageId);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => console.log('Error loading districts:', error));
|
||||
}
|
||||
|
||||
function loadVillages(addressId, districtId, currentVillageId = null) {
|
||||
fetch(`/addresses/villages/${districtId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const villageSelect = document.querySelector(
|
||||
`.village-select[data-address-id="${addressId}"]`);
|
||||
if (villageSelect) {
|
||||
// Clear and set options
|
||||
villageSelect.innerHTML =
|
||||
'<option value="">{{ __('addresses.select_village') }}</option>';
|
||||
|
||||
data.data.forEach(village => {
|
||||
const option = document.createElement('option');
|
||||
option.value = village.id;
|
||||
option.textContent = village.name;
|
||||
|
||||
if (currentVillageId && village.id == currentVillageId) {
|
||||
option.selected = true;
|
||||
}
|
||||
|
||||
villageSelect.appendChild(option);
|
||||
});
|
||||
|
||||
// Initialize Choices.js
|
||||
if (window.Choices) {
|
||||
// Destroy existing instance if any
|
||||
if (villageSelect.choices) {
|
||||
villageSelect.choices.destroy();
|
||||
}
|
||||
// Initialize new Choices instance
|
||||
villageSelect.choices = new window.Choices(villageSelect, {
|
||||
searchEnabled: true,
|
||||
itemSelectText: 'Select an option',
|
||||
noResultsText: 'No results found',
|
||||
shouldSort: false
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => console.log('Error loading villages:', error));
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -68,12 +68,12 @@
|
|||
<h6 class="pt-4 ps-2 ms-1">{{ __('account_sidebar.manage_account') }}</h6>
|
||||
<nav class="list-group list-group-borderless">
|
||||
<a class="list-group-item list-group-item-action d-flex align-items-center"
|
||||
href="{{ route('second', ['account', 'info']) }}">
|
||||
href="{{ route('profile') }}">
|
||||
<i class="ci-user fs-base opacity-75 me-2"></i>
|
||||
{{ __('account_sidebar.personal_info') }}
|
||||
</a>
|
||||
<a class="list-group-item list-group-item-action d-flex align-items-center"
|
||||
href="{{ route('second', ['account', 'addresses']) }}">
|
||||
href="{{ route('addresses') }}">
|
||||
<i class="ci-map-pin fs-base opacity-75 me-2"></i>
|
||||
{{ __('account_sidebar.addresses') }}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Http\Controllers\Auth\AddressController;
|
||||
use App\Http\Controllers\Auth\LoginEmailController;
|
||||
use App\Http\Controllers\Auth\LoginWaController;
|
||||
use App\Http\Controllers\Auth\RegisterController;
|
||||
|
|
@ -71,3 +72,10 @@ Route::group(['prefix' => '/login/google'], function () {
|
|||
Route::get('/profile', [ProfileController::class, 'index'])->name('profile');
|
||||
Route::post('/profile', [ProfileController::class, 'update'])->name('profile.update');
|
||||
Route::put('/profile/password', [ProfileController::class, 'updatePassword'])->name('profile.password.update');
|
||||
|
||||
|
||||
Route::get('/addresses', [AddressController::class, 'index'])->name('addresses');
|
||||
Route::get('/addresses/provinces', [AddressController::class, 'provinces'])->name('addresses.provinces');
|
||||
Route::get('/addresses/cities/{provinceId}', [AddressController::class, 'cities'])->name('addresses.cities');
|
||||
Route::get('/addresses/districts/{provinceId}', [AddressController::class, 'districts'])->name('addresses.districts');
|
||||
Route::get('/addresses/villages/{districtId}', [AddressController::class, 'villages'])->name('addresses.villages');
|
||||
|
|
|
|||
Loading…
Reference in New Issue