# Location Management System - Implementation Guide

## Overview
This Location Management System has been successfully implemented with the following features:
- State, City, Area, Pincode, and Pickup Location management
- Area-wise delivery charges with free delivery option
- Dynamic AJAX dropdowns
- Delivery checker for frontend
- Complete admin panel integration

## Database Migrations

Run the following command to create all tables:

```bash
php artisan migrate
```

This will create:
- states
- cities
- areas (with delivery charge fields)
- pincodes
- pickup_locations

## Admin Panel Access

Access the Location Management from the admin panel sidebar:
**Location Management** (dropdown menu)
- States
- Cities
- Areas
- Pincodes
- Pickup Locations

### Admin Routes
- States: `/admin/states`
- Cities: `/admin/cities`
- Areas: `/admin/areas`
- Pincodes: `/admin/pincodes`
- Pickup Locations: `/admin/pickup-locations`

## API Endpoints

All location API endpoints are available at `/api/v1/locations/`:

### Get States
```
GET /api/v1/locations/states
```

### Get Cities by State
```
GET /api/v1/locations/cities?state_id={state_id}
```

### Get Areas by City
```
GET /api/v1/locations/areas?city_id={city_id}
```

### Get Pincodes by Area
```
GET /api/v1/locations/pincodes?area_id={area_id}
```

### Get Pickup Locations
```
GET /api/v1/locations/pickup-locations?area_id={area_id}
GET /api/v1/locations/pickup-locations?pincode_id={pincode_id}
```

### Check Delivery Availability
```
POST /api/v1/locations/check-delivery
Body: {
    "pincode": "400001",
    "order_amount": 1000
}
```

### Calculate Delivery Charge
```
POST /api/v1/locations/calculate-delivery-charge
Body: {
    "area_id": 1,
    "order_amount": 1000
}
```

## Frontend Integration

### 1. Include Delivery Checker on Product Page

Add this to your product detail page:

```blade
@include('components.delivery-checker')

<!-- Add this hidden input with order amount -->
<input type="hidden" id="order-amount" value="{{ $product->online_price }}">
```

### 2. Checkout Page Integration

Example checkout page with location dropdowns:

```blade
@extends('layouts.app')

@section('content')
<div class="container">
    <h2>Checkout</h2>

    <form action="{{ route('checkout.process') }}" method="POST">
        @csrf

        <!-- Customer Details -->
        <div class="card mb-3">
            <div class="card-header">Delivery Address</div>
            <div class="card-body">
                <div class="row">
                    <div class="col-md-6 mb-3">
                        <label>State *</label>
                        <select class="form-select" name="state_id" id="state_id" required>
                            <option value="">Select State</option>
                        </select>
                    </div>
                    <div class="col-md-6 mb-3">
                        <label>City *</label>
                        <select class="form-select" name="city_id" id="city_id" required>
                            <option value="">Select City</option>
                        </select>
                    </div>
                    <div class="col-md-6 mb-3">
                        <label>Area *</label>
                        <select class="form-select" name="area_id" id="area_id" required>
                            <option value="">Select Area</option>
                        </select>
                    </div>
                    <div class="col-md-6 mb-3">
                        <label>Pincode *</label>
                        <select class="form-select" name="pincode_id" id="pincode_id" required>
                            <option value="">Select Pincode</option>
                        </select>
                    </div>
                </div>

                <!-- Delivery Charge Display -->
                <div class="alert alert-info" id="delivery-info" style="display:none;">
                    <strong>Delivery Charge: </strong>
                    <span id="checkout-delivery-charge"></span>
                    <br>
                    <strong>Delivery Time: </strong>
                    <span id="checkout-delivery-days"></span>
                </div>
            </div>
        </div>

        <!-- Order Summary -->
        <div class="card mb-3">
            <div class="card-header">Order Summary</div>
            <div class="card-body">
                <table class="table">
                    <tr>
                        <td>Subtotal</td>
                        <td class="text-end">₹<span id="subtotal">{{ $cartTotal }}</span></td>
                    </tr>
                    <tr>
                        <td>Delivery Charge</td>
                        <td class="text-end">₹<span id="delivery-charge-amount">0</span></td>
                    </tr>
                    <tr class="fw-bold">
                        <td>Total</td>
                        <td class="text-end">₹<span id="final-total">{{ $cartTotal }}</span></td>
                    </tr>
                </table>
            </div>
        </div>

        <input type="hidden" name="delivery_charge" id="delivery-charge-input" value="0">

        <button type="submit" class="btn btn-primary btn-lg">Place Order</button>
    </form>
</div>

@push('scripts')
<script>
    const stateSelect = document.getElementById('state_id');
    const citySelect = document.getElementById('city_id');
    const areaSelect = document.getElementById('area_id');
    const pincodeSelect = document.getElementById('pincode_id');
    const cartTotal = parseFloat('{{ $cartTotal }}');

    // Load states on page load
    fetch('/api/v1/locations/states')
        .then(response => response.json())
        .then(data => {
            data.data.forEach(state => {
                stateSelect.innerHTML += `<option value="${state.id}">${state.state_name}</option>`;
            });
        });

    // State change
    stateSelect.addEventListener('change', function() {
        const stateId = this.value;
        citySelect.innerHTML = '<option value="">Loading...</option>';
        areaSelect.innerHTML = '<option value="">Select Area</option>';
        pincodeSelect.innerHTML = '<option value="">Select Pincode</option>';

        if (!stateId) {
            citySelect.innerHTML = '<option value="">Select City</option>';
            return;
        }

        fetch(`/api/v1/locations/cities?state_id=${stateId}`)
            .then(response => response.json())
            .then(data => {
                citySelect.innerHTML = '<option value="">Select City</option>';
                data.data.forEach(city => {
                    citySelect.innerHTML += `<option value="${city.id}">${city.city_name}</option>`;
                });
            });
    });

    // City change
    citySelect.addEventListener('change', function() {
        const cityId = this.value;
        areaSelect.innerHTML = '<option value="">Loading...</option>';
        pincodeSelect.innerHTML = '<option value="">Select Pincode</option>';

        if (!cityId) {
            areaSelect.innerHTML = '<option value="">Select Area</option>';
            return;
        }

        fetch(`/api/v1/locations/areas?city_id=${cityId}`)
            .then(response => response.json())
            .then(data => {
                areaSelect.innerHTML = '<option value="">Select Area</option>';
                data.data.forEach(area => {
                    areaSelect.innerHTML += `<option value="${area.id}">${area.area_name}</option>`;
                });
            });
    });

    // Area change
    areaSelect.addEventListener('change', function() {
        const areaId = this.value;
        pincodeSelect.innerHTML = '<option value="">Loading...</option>';

        if (!areaId) {
            pincodeSelect.innerHTML = '<option value="">Select Pincode</option>';
            return;
        }

        fetch(`/api/v1/locations/pincodes?area_id=${areaId}`)
            .then(response => response.json())
            .then(data => {
                pincodeSelect.innerHTML = '<option value="">Select Pincode</option>';
                data.data.forEach(pincode => {
                    pincodeSelect.innerHTML += `<option value="${pincode.id}">${pincode.pincode}</option>`;
                });
            });

        // Calculate delivery charge
        calculateDeliveryCharge(areaId);
    });

    function calculateDeliveryCharge(areaId) {
        fetch('/api/v1/locations/calculate-delivery-charge', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
            },
            body: JSON.stringify({
                area_id: areaId,
                order_amount: cartTotal
            })
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                const deliveryCharge = parseFloat(data.data.delivery_charge);
                const finalTotal = cartTotal + deliveryCharge;

                document.getElementById('delivery-charge-amount').textContent = deliveryCharge.toFixed(2);
                document.getElementById('final-total').textContent = finalTotal.toFixed(2);
                document.getElementById('delivery-charge-input').value = deliveryCharge;

                // Show delivery info
                const deliveryInfo = document.getElementById('delivery-info');
                const chargeText = data.data.is_free_delivery ? 'FREE' : `₹${deliveryCharge.toFixed(2)}`;
                document.getElementById('checkout-delivery-charge').textContent = chargeText;
                
                // You may want to fetch area details for delivery days
                deliveryInfo.style.display = 'block';
            }
        });
    }
</script>
@endpush
@endsection
```

## Delivery Charge Logic

The delivery charge is calculated automatically based on:

1. **Area Delivery Charge**: Base charge set for each area
2. **Free Delivery Above**: If order amount >= this value, delivery is FREE
3. **Order Amount**: Current cart/order total

```php
// In Area Model
public function calculateDeliveryCharge($orderAmount)
{
    if ($this->free_delivery_above && $orderAmount >= $this->free_delivery_above) {
        return 0;
    }
    return $this->delivery_charge;
}
```

## Example Use Cases

### 1. Area Setup Example
- Area: "Downtown Mumbai"
- Delivery Charge: ₹50
- Free Delivery Above: ₹500
- Min Delivery Days: 1
- Max Delivery Days: 2

Result:
- Order ₹300 → Delivery Charge: ₹50
- Order ₹600 → Delivery Charge: FREE

### 2. Pincode Management
- Add pincodes for each area
- Enable/Disable delivery for specific pincodes
- Check pincode serviceability

### 3. Pickup Locations
- Set up physical pickup points
- Display on map (Google Maps integration)
- Show opening hours
- Filter by area/pincode

## Features Implemented

✅ Complete CRUD for States, Cities, Areas, Pincodes, Pickup Locations
✅ Area-wise delivery charge with free delivery threshold
✅ Delivery days configuration (min/max)
✅ Dynamic AJAX cascading dropdowns
✅ Delivery availability checker
✅ Pickup location management with timings
✅ Search and filter functionality
✅ Bulk operations (delete)
✅ Status toggle for all entities
✅ API endpoints for frontend integration
✅ Responsive admin panel
✅ Frontend delivery checker component

## Next Steps

1. **Run Migrations**: `php artisan migrate`
2. **Add Initial Data**: Create states, cities, areas via admin panel
3. **Configure Areas**: Set delivery charges and thresholds
4. **Add Pincodes**: Import or manually add pincodes
5. **Setup Pickup Locations**: Add physical pickup points
6. **Integrate Checkout**: Use the checkout example above
7. **Test Delivery Checker**: Add to product pages

## Support & Customization

All models, controllers, and views are fully customizable. You can:
- Add more fields to any entity
- Customize delivery charge calculation logic
- Add zone-based pricing
- Implement CSV import for bulk pincode upload
- Add Google Maps autocomplete
- Integrate with third-party shipping APIs

## File Structure

```
app/
├── Models/
│   ├── State.php
│   ├── City.php
│   ├── Area.php
│   ├── Pincode.php
│   └── PickupLocation.php
├── Http/Controllers/
│   ├── Admin/
│   │   ├── StateController.php
│   │   ├── CityController.php
│   │   ├── AreaController.php
│   │   ├── PincodeController.php
│   │   └── PickupLocationController.php
│   └── Api/
│       └── LocationController.php

resources/views/
├── admin/locations/
│   ├── states/ (index, create, edit)
│   ├── cities/ (index, create, edit)
│   ├── areas/ (index, create, edit)
│   ├── pincodes/ (index, create, edit)
│   └── pickup-locations/ (index, create, edit)
└── components/
    └── delivery-checker.blade.php

database/migrations/
├── 2026_02_28_000001_create_states_table.php
├── 2026_02_28_000002_create_cities_table.php
├── 2026_02_28_000003_create_areas_table.php
├── 2026_02_28_000004_create_pincodes_table.php
└── 2026_02_28_000005_create_pickup_locations_table.php
```

## Admin Panel Screenshots

Access via `/admin/states`, `/admin/cities`, etc.

All modules include:
- List view with search and filters
- Create/Edit forms with validation
- Status toggle
- Bulk delete
- Pagination

## Conclusion

The Location Management System is now fully implemented and ready to use. All features requested have been implemented including:
- Complete admin panel
- API endpoints
- Delivery checker
- Checkout integration
- Area-wise delivery charges

You can now manage your locations and delivery charges efficiently!
