summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/Datetime.tsx28
-rw-r--r--src/components/Geshem.tsx65
-rw-r--r--src/components/Map.tsx105
-rw-r--r--src/components/Slider.tsx86
4 files changed, 0 insertions, 284 deletions
diff --git a/src/components/Datetime.tsx b/src/components/Datetime.tsx
deleted file mode 100644
index 8b66a4f..0000000
--- a/src/components/Datetime.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from "react";
-import { DateTime as LuxonDateTime } from "luxon";
-
-interface DateTimeProps {
- images: string[];
- slider: number;
-}
-
-export function DateTime({ images, slider }: DateTimeProps) {
- let datetime: LuxonDateTime | null = null;
-
- if (images.length > 0 && images[slider]) {
- const ds = images[slider].substring(5, 18);
- datetime = LuxonDateTime.fromFormat(ds, "yyyyMMdd/HHmm", {
- zone: "utc",
- }).setZone("Asia/Jerusalem");
- }
-
- const date = datetime ? datetime.toFormat("dd/MM/y") : "";
- const time = datetime ? datetime.toFormat("HH:mm") : "";
-
- return (
- <div id="datetime" className="absolute top-5 left-5 text-white font-mono">
- <div id="date" className="text-xl">{date}</div>
- <div id="time" className="text-4xl">{time}</div>
- </div>
- );
-} \ No newline at end of file
diff --git a/src/components/Geshem.tsx b/src/components/Geshem.tsx
deleted file mode 100644
index 982d841..0000000
--- a/src/components/Geshem.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import React, { useState, useEffect } from "react";
-
-import { Map } from "./Map";
-import { Slider } from "./Slider";
-import { DateTime } from "./Datetime";
-
-import { IMAGES_BASE_URL, PLAYBACK_HOURS, PLAYBACK_SLOTS } from "../config";
-
-interface GeshemProps {
- date?: string;
-}
-
-export function Geshem({ date }: GeshemProps) {
- const [images, setImages] = useState<string[]>([]);
- const [playback] = useState(
- date ||
- (typeof window !== 'undefined' ? new URL(window.location.toString()).searchParams.get("history") : null) ||
- undefined
- );
- const [slider, setSlider] = useState(playback ? PLAYBACK_SLOTS : 9);
-
- useEffect(() => {
- const fetchImages = async () =>
- fetch(`${IMAGES_BASE_URL}/imgs.json`)
- .then(res => res.json())
- .then(imgs => (imgs as any)["280"])
- .then(setImages);
-
- const buildPlayback = async () => {
- const date = playback;
- const hours = Array.from(Array(PLAYBACK_HOURS).keys()).map(
- h => `${String(h).padStart(2, "0")}`
- );
- const minutes = Array.from(Array(6).keys()).map(
- m => `${String(m * 10).padStart(2, "0")}`
- );
- const paths = hours.reduce<string[]>(
- (acc, h) =>
- acc.concat(minutes.map(m => `imgs/${date}/${h}${m}/280.png`)),
- []
- );
- setImages(paths);
- };
-
- let timer: number;
- if (playback) {
- buildPlayback();
- } else {
- fetchImages();
- timer = window.setInterval(fetchImages, 60 * 1000);
- }
-
- return () => {
- if (timer !== undefined) clearInterval(timer);
- };
- }, [playback]);
-
- return (
- <>
- <Map images={images} slider={slider} />
- <DateTime images={images} slider={slider} />
- <Slider slider={slider} playback={playback} setSlider={setSlider} />
- </>
- );
-} \ No newline at end of file
diff --git a/src/components/Map.tsx b/src/components/Map.tsx
deleted file mode 100644
index 070dc5c..0000000
--- a/src/components/Map.tsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import React, { useState, useEffect, useRef } from "react";
-import mapboxgl from 'mapbox-gl';
-
-import {
- MAPBOX_ACCESS_TOKEN,
- IMAGE_COORDINATES,
- IMAGES_BASE_URL
-} from "../config";
-
-import "mapbox-gl/dist/mapbox-gl.css";
-
-interface MapProps {
- slider: number;
- images: string[];
-}
-
-export function Map({ slider, images }: MapProps) {
- const mapContainer = useRef<HTMLDivElement>(null);
- const map = useRef<mapboxgl.Map | null>(null);
-
- const [lng] = useState(35);
- const [lat] = useState(31.9);
- const [zoom] = useState(6.3);
- const [loaded, setLoaded] = useState(false);
-
- const prevImages = useRef(images).current;
-
- useEffect(() => {
- if (map.current || !mapContainer.current) return;
-
- map.current = new mapboxgl.Map({
- accessToken: MAPBOX_ACCESS_TOKEN,
- container: mapContainer.current,
- style: "mapbox://styles/mapbox/dark-v9",
- center: [lng, lat],
- zoom: zoom,
- minZoom: 5,
- maxZoom: 10,
- hash: false,
- });
-
- map.current.on("style.load", () => {
- setLoaded(true);
- });
- }, [lng, lat, zoom]);
-
- useEffect(() => {
- if (!loaded || !map.current) return;
-
- // remove old layers
- prevImages.forEach((img) => {
- if (!images.includes(img)) {
- if (map.current?.getLayer(`layer-${img}`)) {
- map.current.removeLayer(`layer-${img}`);
- }
- if (map.current?.getSource(`source-${img}`)) {
- map.current.removeSource(`source-${img}`);
- }
- }
- });
-
- // add new layers
- images.forEach((img, i) => {
- if (!prevImages.includes(img) && !map.current?.getSource(`source-${img}`)) {
- map.current?.addSource(`source-${img}`, {
- type: "image",
- url: `${IMAGES_BASE_URL}/${img}`,
- coordinates: IMAGE_COORDINATES
- });
- map.current?.addLayer({
- id: `layer-${img}`,
- source: `source-${img}`,
- type: "raster",
- paint: {
- "raster-opacity": 0,
- "raster-opacity-transition": {
- duration: 0
- }
- }
- });
- }
- });
- }, [loaded, prevImages, images]);
-
- useEffect(() => {
- if (!loaded || !images.length || !map.current) return;
-
- if (images[slider]) {
- map.current.setPaintProperty(`layer-${images[slider]}`, "raster-opacity", 0.85);
- }
-
- return () => {
- // callback will hide the previous layer with the previous slider value
- if (images[slider] && map.current?.getLayer(`layer-${images[slider]}`)) {
- map.current.setPaintProperty(`layer-${images[slider]}`, "raster-opacity", 0);
- }
- };
- }, [loaded, slider, images]);
-
- return (
- <div>
- <div ref={mapContainer} className="map-container h-screen w-screen" />
- </div>
- );
-} \ No newline at end of file
diff --git a/src/components/Slider.tsx b/src/components/Slider.tsx
deleted file mode 100644
index 22a8f8f..0000000
--- a/src/components/Slider.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-import React, { useCallback, useRef, useState } from "react";
-import { PLAYBACK_SLOTS } from "../config";
-
-interface SliderProps {
- playback?: string;
- slider: number;
- setSlider: React.Dispatch<React.SetStateAction<number>>;
-}
-
-export function Slider({ playback, slider, setSlider }: SliderProps) {
- const sliderRef = useRef<HTMLDivElement>(null);
- const [isDragging, setIsDragging] = useState(false);
-
- const max = playback ? PLAYBACK_SLOTS : 9;
-
- const handleStart = useCallback((e: React.MouseEvent | React.TouchEvent) => {
- setIsDragging(true);
- updateSliderValue(e);
- }, []);
-
- const updateSliderValue = useCallback((e: MouseEvent | React.MouseEvent | TouchEvent | React.TouchEvent) => {
- if (!sliderRef.current) return;
-
- const rect = sliderRef.current.getBoundingClientRect();
- let clientX: number;
-
- if ('touches' in e) {
- clientX = e.touches?.[0]?.clientX || (e as TouchEvent).changedTouches?.[0]?.clientX || 0;
- } else {
- clientX = e.clientX;
- }
-
- const percentage = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
- const value = Math.round(percentage * max);
- setSlider(value);
- }, [max, setSlider]);
-
- const handleMove = useCallback((e: MouseEvent | TouchEvent) => {
- if (isDragging) {
- e.preventDefault();
- updateSliderValue(e);
- }
- }, [isDragging, updateSliderValue]);
-
- const handleEnd = useCallback(() => {
- setIsDragging(false);
- }, []);
-
- React.useEffect(() => {
- if (isDragging) {
- document.addEventListener('mousemove', handleMove);
- document.addEventListener('mouseup', handleEnd);
- document.addEventListener('touchmove', handleMove, { passive: false });
- document.addEventListener('touchend', handleEnd);
-
- return () => {
- document.removeEventListener('mousemove', handleMove);
- document.removeEventListener('mouseup', handleEnd);
- document.removeEventListener('touchmove', handleMove);
- document.removeEventListener('touchend', handleEnd);
- };
- }
- }, [isDragging, handleMove, handleEnd]);
-
- const percentage = (slider / max) * 100;
-
- return (
- <div id="slider" className="py-2.5 fixed bottom-[8vh] w-[30vw] ml-[35vw] max-[812px]:w-[80vw] max-[812px]:ml-[8vw] max-[812px]:z-10">
- <div
- ref={sliderRef}
- className="relative h-5 bg-blue-500 rounded-full cursor-pointer touch-none"
- onMouseDown={handleStart}
- onTouchStart={handleStart}
- >
- <div
- className={`absolute -top-2.5 w-10 h-10 bg-white rounded-full shadow-md z-[1] ${
- isDragging ? 'cursor-grabbing' : 'cursor-grab'
- }`}
- style={{
- left: `calc(${percentage}% - 20px)`
- }}
- />
- </div>
- </div>
- );
-} \ No newline at end of file