Merge branch 'main' of https://repos.hackathon.bz.it/2025-summer/team-1 into scanner_page

This commit is contained in:
Simone Tesini 2025-08-02 06:24:13 +02:00
commit 7170c7b663
13 changed files with 99 additions and 79 deletions

View file

@ -8,6 +8,7 @@
"name": "frontend",
"version": "0.0.1",
"dependencies": {
"@lucide/svelte": "^0.536.0",
"socket.io-client": "^4.8.1",
"zod": "^4.0.14"
},
@ -30,7 +31,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
@ -499,7 +499,6 @@
"version": "0.3.12",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
"integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@ -510,7 +509,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@ -520,20 +518,27 @@
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
"integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.29",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
"integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@lucide/svelte": {
"version": "0.536.0",
"resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-0.536.0.tgz",
"integrity": "sha512-YAeoWU+0B/RriFZZ3wHno1FMkbrVrFdityuo2B0YuphD0vtJWXStzZkWLGVhT3jMb7zhugmhayIg+gI4+AZu1g==",
"license": "ISC",
"peerDependencies": {
"svelte": "^5"
}
},
"node_modules/@polka/url": {
"version": "1.0.0-next.29",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
@ -831,7 +836,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz",
"integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"acorn": "^8.9.0"
@ -1207,14 +1211,12 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"dev": true,
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@ -1227,7 +1229,6 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
@ -1237,7 +1238,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
@ -1273,7 +1273,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@ -1433,14 +1432,12 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
"dev": true,
"license": "MIT"
},
"node_modules/esrap": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.0.tgz",
"integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@ -1487,7 +1484,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.6"
@ -1756,14 +1752,12 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
"dev": true,
"license": "MIT"
},
"node_modules/magic-string": {
"version": "0.30.17",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
"integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0"
@ -2181,7 +2175,6 @@
"version": "5.37.1",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.37.1.tgz",
"integrity": "sha512-h8arWpQZ+3z8eahyBT5KkiBOUsG6xvI5Ykg0ozRr9xEdImgSMUPUlOFWRNkUsT7Ti0DSUCTEbPoped0aoxFyWA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.3.0",
@ -2441,7 +2434,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz",
"integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==",
"dev": true,
"license": "MIT"
},
"node_modules/zod": {

View file

@ -28,7 +28,8 @@
"vite": "^7.0.4"
},
"dependencies": {
"zod": "^4.0.14",
"socket.io-client": "^4.8.1"
"@lucide/svelte": "^0.536.0",
"socket.io-client": "^4.8.1",
"zod": "^4.0.14"
}
}

View file

@ -7,7 +7,7 @@ function geolocation_to_simple_coords(coordinates: GeolocationCoordinates): Coor
return { latitude: coordinates.latitude, longitude: coordinates.longitude }
}
export function get_coords(): Promise<{ coords: Coordinates | null, error: string | null }> {
export function get_coords(): Promise<{ coords: Coordinates | null; error: string | null }> {
return new Promise((resolve) => {
if (!navigator.geolocation) {
resolve({ coords: null, error: "Geolocation is not supported by your browser" })
@ -18,7 +18,7 @@ export function get_coords(): Promise<{ coords: Coordinates | null, error: strin
console.log(gps_error)
resolve({
coords: null,
error: `Unable to retrieve your location: (${gps_error.message})`
error: `Unable to retrieve your location: (${gps_error.message})`,
})
return
}
@ -26,7 +26,7 @@ export function get_coords(): Promise<{ coords: Coordinates | null, error: strin
const success_callback = (gps_position: GeolocationPosition) => {
resolve({
coords: geolocation_to_simple_coords(gps_position.coords),
error: null
error: null,
})
return
}
@ -34,29 +34,3 @@ export function get_coords(): Promise<{ coords: Coordinates | null, error: strin
navigator.geolocation.getCurrentPosition(success_callback, error_callback)
})
}
function distance_between_coords(
lhs: Coordinates,
rhs: Coordinates
): number {
const R = 6371000; // earth radius in meters
const to_rad = (deg: number) => (deg * Math.PI) / 180;
const d_lat = to_rad(rhs.latitude - lhs.latitude);
const d_lon = to_rad(rhs.longitude - lhs.longitude);
const a =
Math.sin(d_lat / 2) ** 2 +
Math.cos(to_rad(lhs.latitude)) *
Math.cos(to_rad(rhs.latitude)) *
Math.sin(d_lon / 2) ** 2;
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c; // distance in meters
}
export function is_within_range(my_coords: Coordinates, target_coords: Coordinates, max_range: number): boolean {
const distance = distance_between_coords(my_coords, target_coords)
return distance <= max_range
}

View file

@ -1 +0,0 @@
export type FetchError = { code: number, message: string }

View file

@ -65,3 +65,11 @@ export const triggerPlayNext = async function (roomId: string): Promise<[FetchEr
})
return [null, songs, json["index"]]
}
export const getStreamingUrl = async function (uuid: string) {
let resp = await fetch("/api/song/audio?song=" + uuid)
let json = await resp.json()
return json["url"]
}

View file

@ -3,21 +3,37 @@
import { type Song } from "$lib/types"
import { onMount } from "svelte"
import type { FetchError } from "$lib/types"
import { getQueueSongs, triggerPlayNext } from "$lib/utils.js"
import { getQueueSongs, getStreamingUrl, triggerPlayNext } from "$lib/utils.js"
import Error from "$lib/components/Error.svelte"
let { data } = $props()
let queueSongs = $state<Song[]>([])
let playingIndex = $state<number>()
let playingIndex = $state<number>(0)
let returnError = $state<FetchError | null>()
let currentPlaying = $derived<Song>(queueSongs[playingIndex])
let audioController = $state<HTMLAudioElement>()
async function playOnEnd() {
let url = await getStreamingUrl(currentPlaying.uuid)
if (audioController) {
audioController.src = url
audioController.play()
}
}
onMount(async () => {
let songs, index
;[returnError, songs, index] = await getQueueSongs(data.roomId)
queueSongs = songs
playingIndex = index
if (audioController) {
audioController.src = await getStreamingUrl(currentPlaying.uuid)
audioController.play()
}
})
async function playNext() {
@ -37,5 +53,6 @@
<div class="flex w-full flex-col items-center justify-center p-4 lg:p-10">
<QueueSlider {queueSongs} {playingIndex} />
<button onclick={playNext}>Next</button>
<audio controls autoplay bind:this={audioController} onended={playOnEnd}></audio>
</div>
{/if}

View file

@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from "svelte"
import { get_coords, is_within_range, type Coordinates } from "$lib/gps"
import { get_coords, type Coordinates } from "$lib/gps"
let lido_schenna_coords: Coordinates = { latitude: 46.6769043, longitude: 11.1851585 }
@ -12,6 +12,6 @@
}
if (coords == null) return
console.log(is_within_range(coords, lido_schenna_coords, 103))
// console.log(is_within_range(coords, lido_schenna_coords, 103))
})
</script>

View file

@ -0,0 +1,7 @@
<script lang="ts">
import { Skull, Accessibility, Anvil } from "@lucide/svelte"
</script>
<Skull />
<Accessibility />
<Anvil />

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 KiB

View file

@ -1,22 +0,0 @@
import type { Config } from "tailwindcss"
const { iconsPlugin, getIconCollections } = require("@egoist/tailwindcss-icons")
export default {
content: ["./src/**/*.{html,js,svelte,ts}"],
theme: {
extend: {},
},
plugins: [
iconsPlugin({
// Select the icon collections you want to use
// You can also ignore this option to automatically discover all individual icon packages you have installed
// If you install @iconify/json, you should explicitly specify the collections you want to use, like this:
collections: getIconCollections(["lucide"]),
// If you want to use all icons from @iconify/json, you can do this:
// collections: getIconCollections("all"),
// and the more recommended way is to use `dynamicIconsPlugin`, see below.
}),
],
} satisfies Config