FINALL JAVASCRIPT

mail@pastecode.io avatar
unknown
javascript
a month ago
12 kB
1
Indexable
Never
import Alpine from 'alpinejs';

window.Alpine = Alpine;




window.layoutData = ({
                         apiBaseUrl,
                         deviceId,
                         refreshRate,
                         displayType,
                         backgroundColor = null,
                         primaryColor = null,
                         secondaryColor = null,
                         lines = null,
                         displayMessageOnError = null,
                         departuresInterval = null,
                         adInterval = null,
                         adsPath = null,
                     }) => {
    return {
        scheduleTickNr: 0,
        adsTickNr: 0,
        lastSuccessfulAPIFetch: '',
        heapSize: '',
        loadsInProgress: 0,
        hasErrors: false,
        firstDataGet: false,
        adsLayerVisible: false,
        currentAd: -1,
        scheduleData: [],
        appSettings: {
            apiBaseUrl,
            deviceId,
            refreshRate,
            displayType,
            backgroundColor,
            primaryColor,
            secondaryColor,
            lines,
            displayMessageOnError,
            departuresInterval,
            adInterval,
            adsPath,
        },
        ads: [
            {
                "id": 156,
                "client_id": 1,
                "name": "Testadvert 0",
                "media": "adv/2020_YTP_DFI_1920x360.jpg",
                "media_type": null,
                "media_size": null,
                "ad_interval": 3,
                "visible_from": null,
                "visible_to": null,
                "visible_time_from": null,
                "visible_time_to": null,
                "created_at": "2024-06-12T19:56:51.000000Z",
                "updated_at": "2024-06-12T19:56:51.000000Z",
                "pivot": {"relation_type": "App\\Models\\Layout", "relation_id": 1, "advert_id": 1}
            },
            {
                "id": 9,
                "client_id": 1,
                "name": "Testadvert 1",
                "media": "adv/SA_DFI_1920x360.jpg",
                "media_type": null,
                "media_size": null,
                "ad_interval": 3,
                "visible_from": null,
                "visible_to": null,
                "visible_time_from": null,
                "visible_time_to": null,
                "created_at": "2024-06-12T19:56:51.000000Z",
                "updated_at": "2024-06-12T19:56:51.000000Z",
                "pivot": {"relation_type": "App\\Models\\Layout", "relation_id": 1, "advert_id": 2}
            },
            {
                "id": 1878,
                "client_id": 1,
                "name": "Testadvert 2",
                "media": "adv/TD_Vertrieb_VRR_TFTScreen_1920x1080px.jpg",
                "media_type": null,
                "media_size": null,
                "ad_interval": 6,
                "visible_from": null,
                "visible_to": null,
                "visible_time_from": null,
                "visible_time_to": null,
                "created_at": "2024-06-12T19:56:51.000000Z",
                "updated_at": "2024-06-12T19:56:51.000000Z",
                "pivot": {"relation_type": "App\\Models\\Layout", "relation_id": 1, "advert_id": 3}
            },
            {
                "id": 33,
                "client_id": 1,
                "name": "Testadvert 3",
                "media": "adv/YTP_DFI_1920x360.jpg",
                "media_type": null,
                "media_size": null,
                "ad_interval": 7,
                "visible_from": null,
                "visible_to": null,
                "visible_time_from": null,
                "visible_time_to": null,
                "created_at": "2024-06-12T19:56:51.000000Z",
                "updated_at": "2024-06-12T19:56:51.000000Z",
                "pivot": {"relation_type": "App\\Models\\Layout", "relation_id": 1, "advert_id": 4}
            },
        ],
        newAds: [] || false,

        get availableAds() {
            return this.ads.filter((ad) => this.isCurrentTimeBetween(ad.visible_time_from, ad.visible_time_to));
        },

        mounted() {
            this.runApp();
        },

        isCurrentTimeBetween(startTime, endTime) {
            if (!startTime || !endTime || startTime === '' || endTime === '') return true;
            const currentTime = new Date();
            const currentMs = currentTime.getHours() * 60 * 60 * 1000 +
                currentTime.getMinutes() * 60 * 1000 +
                currentTime.getSeconds() * 1000 +
                currentTime.getMilliseconds();

            const [startHours, startMinutes] = startTime.split(':').map(Number);
            const [endHours, endMinutes] = endTime.split(':').map(Number);

            const startMs = startHours * 60 * 60 * 1000 + startMinutes * 60 * 1000;
            const endMs = endHours * 60 * 60 * 1000 + endMinutes * 60 * 1000;

            if (startMs < endMs) {
                return currentMs >= startMs && currentMs <= endMs;
            } else {
                return currentMs >= startMs || currentMs <= endMs;
            }
        },

        getTranportIcon(transportClass) {
            switch (transportClass) {
                case 'BUS':
                case 'CITY_BUS':
                case 'EXPRESS_BUS':
                case 'REGIONAL_BUS':
                case 'CALL_BUS':
                case 'CITIZEN_BUS':
                    return 'busLogo.svg';
                case 'TRAM':
                case 'UNDERGROUND':
                    return 'tramLogo.svg';
                case 'REGIONAL_TRAIN':
                case 'NATIONAL_TRAIN':
                case 'INTERNATIONAL_TRAIN':
                    return 'trainLogo.svg';
                case 'SUBURBAN_TRAIN':
                    return 'sLogo.svg';
                default:
                    return null;
            }
        },

        getTimeGerman(date) {
            return date.toLocaleDateString('de-DE', {hour: 'numeric', minute: 'numeric'}).split(',')[1];
        },

        parseResponse(response) {
            return response.map((entity) => {
                const departureTime = new Date(entity.departure_planned);
                const estimatedTime = entity.departure_estimated === null ? new Date(0) : new Date(entity.departure_estimated);

                return {
                    platform: entity.platform,
                    departureTime,
                    estimatedTime,
                    departureString: this.getTimeGerman(departureTime),
                    estimatedString: this.getTimeGerman(estimatedTime),
                    destination: entity.destination_name,
                    transportTitle: entity.transport_name ? `${entity.transport_name} ${entity.transport_number}` : (entity.transport_full_name || null),
                    transportClass: entity.transport_class,
                    transportIcon: this.getTranportIcon(entity.transport_class),
                    hint: entity.hints || '',
                    delay: (estimatedTime > departureTime) ? (estimatedTime.getTime() - departureTime.getTime()) / (60 * 1000) : 0
                };
            }).sort((a, b) => a.departureTime.getTime() - b.departureTime.getTime());
        },

        async makeApiCall(api) {
            this.loadsInProgress++;
            const requestUrl = api === 'ads' ? `${this.appSettings.apiBaseUrl}${this.appSettings.deviceId}/ads` : `${this.appSettings.apiBaseUrl}${this.appSettings.deviceId}/departures?limit=${this.appSettings.lines}`;


            return fetch(requestUrl, {
                method: 'GET',
            }).then((response) => {
                if (response.headers.get("X-Force-Refresh") === "1") {
                    return window.location.reload();
                }
                return response.json();
            }).then((data) => {
                this.loadsInProgress--;
                return data;
            }).catch((error) => {
                this.hasErrors = true;
                this.loadsInProgress--;
                throw new Error('API fetching error' + error);
            });
        },

        async doAppTick() {
            this.scheduleTickNr++;
            const departuresData = await this.makeApiCall('departures');

            if (departuresData !== null) {
                try {
                    this.lastSuccessfulAPIFetch = (new Date()).toLocaleDateString('de-DE', {
                        year: 'numeric',
                        month: 'numeric',
                        day: 'numeric',
                        hour: 'numeric',
                        minute: 'numeric',
                        second: 'numeric'
                    });
                    this.firstDataGet = true;
                    this.scheduleData = this.parseResponse(departuresData);
                } catch (error) {
                    this.hasErrors = true;
                    throw new Error('Error in departures API response: ' + error);
                }
            }
        },

        findNextAdIndex(ads) {
            const nextAd = ads.findIndex(ad => ad.id === this.currentAd);
            if (nextAd === -1) {
                return 0;
            }
            return nextAd === (ads.length - 1) ? 0 : nextAd + 1;
        },

        async doAdsTick() {
            this.adsTickNr++;
            const adsData = await this.makeApiCall('ads');

            if (adsData !== null) {
                try {
                    this.ads = adsData;
                } catch (error) {
                    this.hasErrors = true;
                    throw new Error('Error in ads API response: ' + error);
                }

                let defaultSpaceBetweenAds = this.appSettings.departuresInterval * 1000;

                if (this.availableAds.length === 0) {
                    setTimeout(() => {
                        this.doAdsTick();
                    }, defaultSpaceBetweenAds);
                    return;
                }

                const nextAdIndex = this.findNextAdIndex(this.availableAds);
                const currentAdVisibilityTime = () => {
                    return this.availableAds[nextAdIndex].ad_interval ? this.availableAds[nextAdIndex].ad_interval * 1000 : this.appSettings.adInterval * 1000;
                }

                this.currentAd = this.availableAds[nextAdIndex].id;
                this.adsLayerVisible = true;

                setTimeout(() => {
                    this.adsLayerVisible = false;
                }, currentAdVisibilityTime());

                setTimeout(() => {
                    this.doAdsTick();
                }, currentAdVisibilityTime() + defaultSpaceBetweenAds);
            }
        },

        runApp() {
            try {
                this.doAppTick();
                setInterval(() => {
                    this.doAppTick();
                }, this.appSettings.refreshRate * 1000);
                setTimeout(() => {
                    this.doAdsTick();
                }, this.appSettings.departuresInterval * 1000);
            } catch (error) {
                console.error('Error in runApp:', error);
            }
        },
    }
}

Alpine.start();

Leave a Comment