Skip to content

Commit eb9d094

Browse files
committed
SALG-1278: Styling routepage
1 parent f07898e commit eb9d094

12 files changed

+133
-52
lines changed

src/App.jsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,14 @@ function App() {
139139
</LatLongContext.Provider>
140140
{audioRef && source && (
141141
// eslint-disable-next-line jsx-a11y/media-has-caption
142-
<audio ref={audioRef} controls src={`${fileUrl}${source}`} />
142+
<div className="fixed left-3 bottom-0 right-3 bg-zinc-200 dark:bg-zinc-700">
143+
<audio
144+
className="w-full"
145+
ref={audioRef}
146+
controls
147+
src={`${fileUrl}${source}`}
148+
/>
149+
</div>
143150
)}
144151
</div>
145152
);

src/components/Image.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { React, useContext } from "react";
22
import ApiEndpointContext from "../context/api-endpoint-context";
33

4-
function Image({ src }) {
4+
function Image({ src, className }) {
55
const { fileUrl } = useContext(ApiEndpointContext);
6-
return <img width="300" src={`${fileUrl}${src}`} alt="" />;
6+
return <img className={className} src={`${fileUrl}${src}`} alt="" />;
77
}
88

99
export default Image;

src/components/points-of-interest/PointOfInterest.jsx

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import PodcastWrapper from "./PodcastWrapper";
55
import PermissionContext from "../../context/permission-context";
66
import AudioContext from "../../context/audio-context";
77
import Image from "../Image";
8+
import { ReactComponent as CirclePlay } from "../../icons/circle-play-solid.svg";
9+
import { ReactComponent as ClosedCap } from "../../icons/closed-captioning-solid.svg";
10+
import { ReactComponent as RulerHorizontal } from "../../icons/ruler-horizontal-solid.svg";
11+
import { ReactComponent as Xmark } from "../../icons/xmark-solid.svg";
812

913
function PointOfInterest({
1014
pointOfInterest: {
@@ -83,18 +87,54 @@ function PointOfInterest({
8387
}
8488
}, []);
8589

90+
8691
return (
87-
<>
88-
<h2>{name}</h2>
89-
<Image src={image} />
90-
<div>
91-
{!unlocked && (
92-
<label htmlFor="distance">
93-
afstand
94-
{/* todo this is slow and would benefit from loading screen / skeleton componenet */}
95-
<div id="distance">{proximity} m</div>
96-
</label>
97-
)}
92+
<div className="flex items-start gap-4 p-4">
93+
<Image src={image} className="w-24 h-24 rounded-full" />
94+
<div className="flex flex-col">
95+
<h2 className="text-zinc-900 text-sm font-bold dark:text-zinc-200 my-3">
96+
{name}
97+
</h2>
98+
<div className="text-zinc-500 text-sm font-medium dark:text-zinc-400">
99+
{!unlocked && (
100+
<label htmlFor="distance">
101+
<RulerHorizontal className="w-4 inline mr-3" />
102+
<span className="sr-only">Afstand</span>
103+
{/* todo this is slow and would benefit from loading screen / skeleton componenet */}
104+
<span className="text-md" id="distance">
105+
{proximity} m
106+
</span>
107+
</label>
108+
)}
109+
<div className="flex gap-2">
110+
{unlocked && (
111+
<button
112+
className="p-1 rounded text-zinc-800 bg-zinc-100"
113+
type="button"
114+
onClick={() => setSource(podcast)}
115+
>
116+
<CirclePlay className="w-6"/>
117+
<span className="sr-only">Afspil</span>
118+
</button>
119+
)}
120+
{unlocked && (
121+
<button
122+
className="p-1 rounded text-zinc-800 bg-zinc-100"
123+
type="button"
124+
onClick={() => setViewSubtitles(!viewSubtitles)}
125+
>
126+
{viewSubtitles ? (
127+
<Xmark className="h-6 w-6 text-zinc-800" />
128+
) : (
129+
<ClosedCap className="h-6 w-6 text-zinc-800" />
130+
)}
131+
<span className="sr-only">Se tekst</span>
132+
</button>
133+
)}
134+
</div>
135+
{viewSubtitles && <div className="bg-zinc-200 text-zinc-800 dark:bg-zinc-500 dark:text-white p-2 rounded mt-2">{subtitles}</div>}
136+
{!unlocked && <div>Lås op ved at gå tættere på</div>}
137+
</div>
98138
</div>
99139
{unlocked && (
100140
<button type="button" onClick={() => setSource(podcast)}>

src/components/routes/Route.jsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { React, useEffect, useState } from "react";
22
import { Link } from "react-router-dom";
33
import useFetch from "../../util/useFetch";
44
import Image from "../Image";
5+
import { ReactComponent as CirclePlay } from "../../icons/circle-play-solid.svg";
56

67
function Route({ id }) {
78
const { data } = useFetch(`routes/${id}`);
@@ -16,8 +17,11 @@ function Route({ id }) {
1617
if (route === null) return null;
1718

1819
return (
19-
<Link className="bg-zinc-100 dark:bg-zinc-700 flex" to={`/route/${id}`}>
20-
<Image className="flex-1 w-32" src={route.image} />
20+
<Link className="bg-zinc-100 dark:bg-zinc-700 flex relative" to={`/route/${id}`}>
21+
<div className="w-32 flex justify-center place-items-center" >
22+
<CirclePlay className="absolute w-6" />
23+
<Image className="object-cover h-full" src={route.image} />
24+
</div>
2125
<div className="flex-initial text-left leading-none p-3">
2226
<span className="block mb-1">{route.name}</span>
2327
<span className="text-xs ">{route.description}</span>

src/components/routes/RouteCarousel.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import "react-responsive-carousel/lib/styles/carousel.min.css"; // requires a lo
77
function RouteCarousel({ routes, onCarouselChange }) {
88
return (
99
<Carousel
10-
className="absolute left-0 bottom-0 right-0 m-5 rounded-lg overflow-hidden max-h-96 md:max-w-xs"
10+
className="absolute left-0 bottom-0 right-0 m-5 rounded-lg overflow-hidden max-h-96 md:max-w-lg"
1111
showThumbs={false}
1212
showStatus={false}
1313
autoplay

src/components/routes/RoutePage.jsx

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import useFetch from "../../util/useFetch";
44
import PointOfInterest from "../points-of-interest/PointOfInterest";
55
import { getAngleFromLocationToDestination } from "../../util/helper";
66
import BackButton from "../BackButton";
7+
import { ReactComponent as LocationArrow } from "../../icons/location-arrow-solid.svg";
78

89
function RoutePage() {
910
const { id } = useParams();
@@ -91,41 +92,54 @@ function RoutePage() {
9192

9293
if (selectedRoute === null) return null;
9394
return (
94-
<>
95+
<div className="flex flex-col place-items-start pb-20">
9596
<BackButton>Afslut</BackButton>
9697
<h1 className="text-xl font-bold my-3">{selectedRoute.name}</h1>
97-
{pointsOfInterest &&
98-
pointsOfInterest
99-
.toReversed()
100-
.map((pointOfInterest) => (
101-
<PointOfInterest
102-
pointOfInterest={pointOfInterest}
103-
key={pointOfInterest.id}
104-
/>
105-
))}
106-
<img
107-
alt=""
108-
style={{
109-
width: 100,
110-
display: "block",
111-
margin: "auto",
112-
transform: `rotate(${-rotation}deg)`,
113-
}}
114-
src="data:image/png;base64,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"
115-
/>
116-
<button
117-
style={{
118-
width: 300,
119-
height: 100,
120-
display: "block",
121-
margin: "auto",
122-
}}
123-
type="button"
124-
onClick={() => startWaypointer()}
125-
>
126-
Vis mig vej til {destinationName}
127-
</button>
128-
</>
98+
<div className="overflow-y-auto h-4/6 relative w-full bg-white dark:bg-zinc-700 dark:highlight-white/5 shadow-lg ring-1 ring-black/5 rounded-lg flex flex-col divide-y dark:divide-zinc-200/5">
99+
{pointsOfInterest &&
100+
pointsOfInterest
101+
.toReversed()
102+
.map((pointOfInterest) => (
103+
<PointOfInterest
104+
pointOfInterest={pointOfInterest}
105+
key={pointOfInterest.id}
106+
/>
107+
))}
108+
</div>
109+
{/* TODO: Make room for audio player below when playing */}
110+
<div className="fixed left-3 bottom-3 right-3 bg-zinc-200 dark:bg-zinc-700 flex gap-3 rounded-lg p-3 pb-15 divide-x dark:divide-zinc-200/5">
111+
<div>
112+
<span className="block text-sm text-bold">Afstand til del 1</span>
113+
<span className="block">180 meter</span>
114+
<button
115+
className="bg-zinc-700 dark:bg-zinc-200 dark:text-zinc-800 rounded text-sm py-1 px-3"
116+
type="button"
117+
onClick={() => startWaypointer()}
118+
>
119+
Vis mig vej
120+
</button>
121+
</div>
122+
<div className="pl-3">
123+
<div className="flex justify-between mb-3">
124+
<span className="text-sm text-bold">Retning</span>
125+
<span className="w-1/2">
126+
<LocationArrow
127+
className="inline w-5"
128+
style={{
129+
transform: `rotate(${-rotation}deg)`,
130+
}}
131+
/>
132+
</span>
133+
</div>
134+
<div className="text-xs text-zinc-500">
135+
Lat: {userLatitude}/{latitude}
136+
</div>
137+
<div className="text-xs text-zinc-500">
138+
Long: {userLongitude}/{longitude}
139+
</div>
140+
</div>
141+
</div>
142+
</div>
129143
);
130144
}
131145

src/icons/angle-left-solid.svg

Lines changed: 3 additions & 1 deletion
Loading

src/icons/circle-play-solid.svg

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

src/icons/location-arrow-solid.svg

Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)