Webbserver - Love Blomberg

Show sourcecode

The following files exists in this folder. Click to view.

public_html/smartkortet/pages/

hem.php
historik.php
installningar.php
restauranger.php
statistik.php

restauranger.php

431 lines UTF-8 Windows (CRLF)
<?php

declare(strict_types=1);

require_once 
__DIR__ '/../includes/data.php';

$userId = (int) $user['id'];

if (
$_SERVER['REQUEST_METHOD'] === 'POST') {
    
verifyCsrf();
    
$action $_POST['action'] ?? '';

    if (
$action === 'add_place') {
        
$name trim($_POST['name'] ?? '');
        if (
$name === '') {
            
setFlash('error''Ange ett namn på restaurangen/butiken.');
        } else {
            
saveFavoritePlace($userId$name);
            
setFlash('success''Favorit sparad.');
        }
        
redirect('/index.php?tab=restauranger');
    }

    if (
$action === 'delete_place') {
        
$placeId = (int) ($_POST['place_id'] ?? 0);
        if (
$placeId 0) {
            
removeFavoritePlace($userId$placeId);
            
setFlash('success''Favorit borttagen.');
        }
        
redirect('/index.php?tab=restauranger');
    }
}

$flash getFlash();
$places getFavoritePlaces($userId);

$stockholmRestaurants = [
    [
        
'name' => 'Bamses Pizzeria',
        
'address' => 'Grafikvägen 1',
        
'lat' => 59.2976837,
        
'lng' => 18.0795049,
    ],
    [
        
'name' => 'Bastard Burger',
        
'address' => 'Gullmarsvägen 2',
        
'lat' => 59.2988238,
        
'lng' => 18.0786706,
    ],
    [
        
'name' => 'Bengal Bites',
        
'address' => 'Sköntorpsvägen 80',
        
'lat' => 59.3000488,
        
'lng' => 18.0570767,
    ],
    [
        
'name' => 'Casa Piadina',
        
'address' => 'Götgatan 78',
        
'lat' => 59.3120917,
        
'lng' => 18.0734224,
    ],
    [
        
'name' => 'Cafeterian Värmdö gymnasium',
        
'address' => 'Simlångsvägen 26',
        
'lat' => 59.299478,
        
'lng' => 18.0768563,
    ],
    [
        
'name' => 'Falafel House',
        
'address' => 'Arenavägen 23',
        
'lat' => 59.2960006,
        
'lng' => 18.0804159,
    ],
    [
        
'name' => 'Gullmarsplan Bowling',
        
'address' => 'Simlångsvägen 50',
        
'lat' => 59.2999068,
        
'lng' => 18.0790802,
    ],
    [
        
'name' => 'Gradi',
        
'address' => 'Hammarby Kajgata 4-6',
        
'lat' => 59.3031232,
        
'lng' => 18.0815875,
    ],
    [
        
'name' => 'Happie Hands',
        
'address' => 'Gullmarsvägen 8',
        
'lat' => 59.2985164,
        
'lng' => 18.076977,
    ],
    [
        
'name' => 'Hemköp',
        
'address' => 'Gullmarsplan 4-6',
        
'lat' => 59.298329,
        
'lng' => 18.0790869,
    ],
    [
        
'name' => 'Hermans',
        
'address' => 'Fjällgatan 23B',
        
'lat' => 59.3175886,
        
'lng' => 18.0839872,
    ],
    [
        
'name' => 'Hjälmaren',
        
'address' => 'Hjälmarsvägen 43',
        
'lat' => 59.2966865,
        
'lng' => 18.0525921,
    ],
    [
        
'name' => 'ICA Supermarket Globen',
        
'address' => 'Arenaslingan 1',
        
'lat' => 59.2925,
        
'lng' => 18.08207,
    ],
    [
        
'name' => 'ICA Nära Årsta',
        
'address' => 'Sköntorpsvägen 27',
        
'lat' => 59.2977933,
        
'lng' => 18.0632859,
    ],
    [
        
'name' => 'Il Coure',
        
'address' => 'Fyrvaktarkroken 16',
        
'lat' => 59.2900934,
        
'lng' => 18.0916167,
    ],
    [
        
'name' => 'KEB',
        
'address' => 'Arenavägen 63',
        
'lat' => 59.2925941,
        
'lng' => 18.0824323,
    ],
    [
        
'name' => 'Max Hammarby Sjöstad',
        
'address' => 'Lugnets allé 22',
        
'lat' => 59.3021565,
        
'lng' => 18.1034832,
    ],
    [
        
'name' => 'Max Medborgarplatsen',
        
'address' => 'Götgatan 41',
        
'lat' => 59.3156567,
        
'lng' => 18.0730792,
    ],
    [
        
'name' => 'Riviera Pizzeria',
        
'address' => 'Gullmarsvägen 12',
        
'lat' => 59.2982792,
        
'lng' => 18.0755552,
    ],
    [
        
'name' => 'Seven Eleven',
        
'address' => 'Gullmarsplan 2',
        
'lat' => 59.2987356,
        
'lng' => 18.0795879,
    ],
    [
        
'name' => 'Stenugnsbageriet',
        
'address' => 'Gullmarsplan 4-6',
        
'lat' => 59.2983211,
        
'lng' => 18.0791698,
    ],
    [
        
'name' => 'Subway Globen',
        
'address' => 'Arenaslingan 3A',
        
'lat' => 59.2921533,
        
'lng' => 18.0826564,
    ],
    [
        
'name' => 'Subway Skrapan',
        
'address' => 'Götgatan 78',
        
'lat' => 59.3120917,
        
'lng' => 18.0734224,
    ],
    [
        
'name' => 'Subway Ringvägen',
        
'address' => 'Ringvägen 100',
        
'lat' => 59.307396,
        
'lng' => 18.0757218,
    ],
    [
        
'name' => 'Sushi Bar Nikko',
        
'address' => 'Gullmarsplan 4',
        
'lat' => 59.2983357,
        
'lng' => 18.0791867,
    ],
    [
        
'name' => 'Sushi Yama',
        
'address' => 'Gullmarsplan 4',
        
'lat' => 59.2985362,
        
'lng' => 18.0790181,
    ],
    [
        
'name' => 'Sushirullen',
        
'address' => 'Arenavägen 57',
        
'lat' => 59.293319,
        
'lng' => 18.0809775,
    ],
    [
        
'name' => 'Taco Bar Globen',
        
'address' => 'Arenavägen 69',
        
'lat' => 59.2914205,
        
'lng' => 18.0831635,
    ],
    [
        
'name' => 'Taco Bar Hammarby',
        
'address' => 'Hammarby Kajgata 8A',
        
'lat' => 59.3032843,
        
'lng' => 18.0822363,
    ],
    [
        
'name' => 'Tastory',
        
'address' => 'Hammarbybacken 31',
        
'lat' => 59.3006659,
        
'lng' => 18.0846122,
    ],
    [
        
'name' => 'Trafiket',
        
'address' => 'Gullmarsplan T-bana',
        
'lat' => 59.2991381,
        
'lng' => 18.0814241,
    ],
    [
        
'name' => 'Tullfritt',
        
'address' => 'Gullmarsplan 1',
        
'lat' => 59.2986969,
        
'lng' => 18.0798381,
    ],
    [
        
'name' => 'Årsta kvarterskrog',
        
'address' => 'Gullmarsvägen 42C',
        
'lat' => 59.2989651,
        
'lng' => 18.072056,
    ],
];

$stockholmRestaurantsJson json_encode(
    
$stockholmRestaurants,
    
JSON_UNESCAPED_UNICODE JSON_HEX_TAG JSON_HEX_APOS JSON_HEX_AMP JSON_HEX_QUOT
);
?>
<article class="card panel restaurants-page">
    <h3>Sparade restauranger och butiker</h3>

    <?php if ($flash): ?>
        <div class="notice <?= e($flash['type']) ?>"><?= e($flash['message']) ?></div>
    <?php endif; ?>

    <form method="post" class="form-grid">
        <input type="hidden" name="csrf_token" value="<?= e(csrfToken()) ?>">
        <input type="hidden" name="action" value="add_place">

        <label class="field">
            <span>Namn</span>
            <input type="text" name="name" placeholder="Exempel: Sushi Yama" required>
        </label>

        <div class="form-actions">
            <button class="btn" type="submit">Spara favorit</button>
        </div>
    </form>

    <div class="history-list favorites-list">
        <?php foreach ($places as $place): ?>
            <form method="post" class="history-item favorite-row">
                <input type="hidden" name="csrf_token" value="<?= e(csrfToken()) ?>">
                <input type="hidden" name="action" value="delete_place">
                <input type="hidden" name="place_id" value="<?= e((string) $place['id']) ?>">
                <span class="favorite-name"><?= e($place['name']) ?></span>
                <button class="btn btn-danger" type="submit">Ta bort</button>
            </form>
        <?php endforeach; ?>

        <?php if (!$places): ?>
            <p class="subtitle">Inga favoriter sparade ännu.</p>
        <?php endif; ?>
    </div>

    <section class="card restaurants-section" style="margin-top: 1rem;">
        <h4>Restauranger på matkortet</h4>
        <link
            rel="stylesheet"
            href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css">
        <div id="stockholm-restaurants-map" class="restaurants-map"></div>
        <script
            src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
        <script>
            (function () {
                var mapContainer = document.getElementById('stockholm-restaurants-map');
                if (!mapContainer || typeof maplibregl === 'undefined') {
                    return;
                }

                var restaurants = <?= $stockholmRestaurantsJson ?: '[]' ?>;
                if (!restaurants.length) {
                    return;
                }

                function escapeHtml(text) {
                    return String(text)
                        .replace(/&/g, '&amp;')
                        .replace(/</g, '&lt;')
                        .replace(/>/g, '&gt;')
                        .replace(/\"/g, '&quot;')
                        .replace(/'/g, '&#039;');
                }

                var features = restaurants.map(function (restaurant) {
                    return {
                        type: 'Feature',
                        geometry: {
                            type: 'Point',
                            coordinates: [restaurant.lng, restaurant.lat]
                        },
                        properties: {
                            name: restaurant.name,
                            address: restaurant.address
                        }
                    };
                });

                var map = new maplibregl.Map({
                    container: 'stockholm-restaurants-map',
                    style: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
                    center: [18.067615, 59.324622],
                    zoom: 12
                });

                map.addControl(new maplibregl.NavigationControl(), 'top-right');

                map.on('load', function () {
                    map.addSource('restaurants', {
                        type: 'geojson',
                        data: {
                            type: 'FeatureCollection',
                            features: features
                        }
                    });

                    map.addLayer({
                        id: 'restaurant-points',
                        type: 'circle',
                        source: 'restaurants',
                        paint: {
                            'circle-radius': 7,
                            'circle-color': '#22d3ee',
                            'circle-stroke-color': '#0f172a',
                            'circle-stroke-width': 2
                        }
                    });

                    map.addLayer({
                        id: 'restaurant-labels',
                        type: 'symbol',
                        source: 'restaurants',
                        layout: {
                            'text-field': ['get', 'name'],
                            'text-size': 13,
                            'text-offset': [0, 1.2],
                            'text-anchor': 'top',
                            'text-font': ['Noto Sans Regular']
                        },
                        paint: {
                            'text-color': '#f8fafc',
                            'text-halo-color': '#020617',
                            'text-halo-width': 1.4
                        }
                    });

                    var bounds = new maplibregl.LngLatBounds();
                    features.forEach(function (feature) {
                        bounds.extend(feature.geometry.coordinates);
                    });

                    map.fitBounds(bounds, {
                        padding: 40,
                        maxZoom: 14,
                        duration: 0
                    });
                });

                map.on('click', 'restaurant-points', function (event) {
                    var feature = event.features && event.features[0];
                    if (!feature) {
                        return;
                    }

                    var props = feature.properties || {};
                    new maplibregl.Popup()
                        .setLngLat(feature.geometry.coordinates)
                        .setHTML('<strong>' + escapeHtml(props.name || '') + '</strong><br>' + escapeHtml(props.address || ''))
                        .addTo(map);
                });

                map.on('mouseenter', 'restaurant-points', function () {
                    map.getCanvas().style.cursor = 'pointer';
                });

                map.on('mouseleave', 'restaurant-points', function () {
                    map.getCanvas().style.cursor = '';
                });
            })();
        </script>

        <div class="history-list restaurants-list" style="margin-top: 1rem;">
            <?php foreach ($stockholmRestaurants as $restaurant): ?>
                <?php
                $destination 
rawurlencode($restaurant['address']);
                
$navigationUrl "https://www.google.com/maps/dir/?api=1&destination={$destination}&travelmode=driving";
                
?>
                <div class="history-item restaurant-row">
                    <div class="restaurant-meta">
                        <strong><?= e($restaurant['name']) ?></strong><br>
                        <span class="subtitle"><?= e($restaurant['address']) ?></span>
                    </div>
                    <div class="restaurant-actions">
                        <form method="post">
                            <input type="hidden" name="csrf_token" value="<?= e(csrfToken()) ?>">
                            <input type="hidden" name="action" value="add_place">
                            <input type="hidden" name="name" value="<?= e($restaurant['name']) ?>">
                            <button class="btn" type="submit">Lägg till favorit</button>
                        </form>
                        <a class="btn" href="<?= e($navigationUrl?>" target="_blank" rel="noopener noreferrer">Navigera</a>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
    </section>
</article>