All checks were successful
/ Build (push) Successful in 34s
feat: automatically start watching if gelocation permission is given
189 lines
6.7 KiB
Plaintext
189 lines
6.7 KiB
Plaintext
---
|
||
// Styles
|
||
import "@/styles/globals.css"
|
||
import "@/styles/locked-page.css"
|
||
import "@/styles/locked-content.css"
|
||
|
||
// Components
|
||
import Layout from "@/layouts/Layout.astro"
|
||
import ShareButton from "@/components/ShareButton"
|
||
import {
|
||
Card,
|
||
CardContent,
|
||
CardFooter,
|
||
CardHeader,
|
||
CardTitle,
|
||
} from "@/components/ui/card"
|
||
import { CalendarIcon } from "@radix-ui/react-icons"
|
||
---
|
||
|
||
<Layout>
|
||
<main class='flex flex-col gap-4'>
|
||
<div class='flex flex-col'>
|
||
<h1
|
||
class='scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl hover:underline'>
|
||
<a href=`${import.meta.env.SITE}`> Konulu Konum</a>
|
||
</h1>
|
||
<p class='[&:not(:first-child)]:mt-6 text-2xl'>
|
||
Size bir konulu konum bırakıldı, görüntüleyebilmek için haritadaki
|
||
konuma gitmeniz gerekiyor.
|
||
</p>
|
||
</div>
|
||
|
||
<Card className='w-full'>
|
||
<CardHeader>
|
||
<CardTitle className='text-2xl' id='card-title' />
|
||
</CardHeader>
|
||
<CardContent className='text-xl'>
|
||
<p id='card-description'></p>
|
||
</CardContent>
|
||
<CardFooter className='gap-2 text-lg'>
|
||
<CalendarIcon />
|
||
<p id='card-footer'></p>
|
||
</CardFooter>
|
||
</Card>
|
||
|
||
<div
|
||
id='locked-content-container'
|
||
class='w-full h-[475px] overflow-hidden border border-zinc-200 shadow-sm p-4 rounded'>
|
||
<div class='flex flex-col justify-center items-center image-wrapper'>
|
||
<img
|
||
id='content'
|
||
src='#'
|
||
class='h-[450px] blur-2xl transition-all duration-1000'
|
||
/>
|
||
<div
|
||
id='unlock-button-container'
|
||
class='flex flex-col justify-center gap-4 overlay'>
|
||
<button
|
||
id='unlock-content-button'
|
||
class='transition-[background-color] duration-1000 inline-flex items-center justify-center gap-2 whitespace-nowrap font-medium ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-11 rounded-md text-lg p-6 text-md'>
|
||
<svg
|
||
id='lock-icon'
|
||
xmlns='http://www.w3.org/2000/svg'
|
||
width='28'
|
||
height='28'
|
||
fill='#ffffff'
|
||
viewBox='0 0 256 256'>
|
||
<path
|
||
d='M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Zm-68-56a12,12,0,1,1-12-12A12,12,0,0,1,140,152Z'
|
||
></path>
|
||
</svg>
|
||
<svg
|
||
id='unlock-icon'
|
||
class='hidden'
|
||
xmlns='http://www.w3.org/2000/svg'
|
||
width='24'
|
||
height='24'
|
||
fill='#ffffff'
|
||
viewBox='0 0 256 256'>
|
||
<path
|
||
d='M208,80H96V56a32,32,0,0,1,32-32c15.37,0,29.2,11,32.16,25.59a8,8,0,0,0,15.68-3.18C171.32,24.15,151.2,8,128,8A48.05,48.05,0,0,0,80,56V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80Zm0,128H48V96H208V208Zm-68-56a12,12,0,1,1-12-12A12,12,0,0,1,140,152Z'
|
||
></path>
|
||
</svg>
|
||
<p id='button-text' class='text-xl'>İçerik Kilitli</p>
|
||
</button>
|
||
<div
|
||
class='rounded-lg border bg-card text-card-foreground shadow-sm p-2'>
|
||
<div class='pb-0 text-center flex flex-col gap-4'>
|
||
<p id='locked-content-description' class='text-xl'>
|
||
Ne kadar yaklaştığını görmek için aşağıdaki butona bas.
|
||
</p>
|
||
<button
|
||
id='location-permission-button'
|
||
class='text-xl inline-flex items-center justify-center whitespace-nowrap font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 text-primary-foreground h-10 rounded-md px-3 bg-green-700 hover:bg-green-600 text-md'>
|
||
Konum İzni Ver
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id='map' class='w-full h-[450px] rounded'></div>
|
||
<ShareButton client:only />
|
||
<div class='flex justify-center'>
|
||
<p class='text-muted-foreground'>
|
||
Fotoğrafın kilidi şu ana dek <b id='counter'></b> kez açıldı
|
||
</p>
|
||
</div>
|
||
</main>
|
||
<script>
|
||
import type { ContentTable } from "@/lib/db"
|
||
import { updateText } from "@/lib/domUtils"
|
||
|
||
// Dayjs
|
||
import dayjs from "dayjs"
|
||
import relativeTime from "dayjs/plugin/relativeTime"
|
||
import utc from "dayjs/plugin/utc"
|
||
import "dayjs/locale/tr"
|
||
|
||
// Map
|
||
import { initMap } from "@/scripts/initMap"
|
||
import { startWatchingLocation } from "@/scripts/lockedContent"
|
||
|
||
const url = new URL(document.URL).searchParams
|
||
const id = url.get("id")
|
||
|
||
type Content = ContentTable
|
||
|
||
const res = await fetch(
|
||
`${import.meta.env.PUBLIC_BACKEND_URL}/api/location/${id}`
|
||
)
|
||
|
||
const data: Content | null = res.status === 200 ? await res.json() : null
|
||
|
||
dayjs.extend(relativeTime)
|
||
dayjs.extend(utc)
|
||
dayjs.locale("tr")
|
||
|
||
const dateFromNow = dayjs.utc(data?.created_at).from(dayjs.utc())
|
||
|
||
updateText("card-title", data?.author ?? "")
|
||
updateText("card-description", data?.description ?? "")
|
||
updateText("card-footer", dateFromNow)
|
||
|
||
const lockedContentContainer = document.getElementById(
|
||
"locked-content-container"
|
||
)
|
||
if (lockedContentContainer) {
|
||
lockedContentContainer.dataset.targetPosition = data?.loc
|
||
}
|
||
|
||
const leafletMap = document.getElementById("map")
|
||
if (leafletMap) {
|
||
leafletMap.dataset.targetLocation = data?.loc
|
||
leafletMap.dataset.targetRadius = data?.radius.toString() ?? "50"
|
||
}
|
||
|
||
initMap()
|
||
|
||
const content = document.getElementById(
|
||
"content"
|
||
) as HTMLImageElement | null
|
||
if (content)
|
||
content.src = `${import.meta.env.PUBLIC_BACKEND_URL}/images/${data?.blob_url}`
|
||
|
||
const counter = document.getElementById("counter")
|
||
if (counter) counter.innerText = data?.unlocked_counter.toString() ?? ""
|
||
|
||
// When the web page is loaded, check if user has given geolocation
|
||
// permission before
|
||
navigator.permissions
|
||
.query({ name: "geolocation" })
|
||
.then((permissionStatus) => {
|
||
switch (permissionStatus.state) {
|
||
case "granted":
|
||
startWatchingLocation()
|
||
break
|
||
case "denied":
|
||
case "prompt":
|
||
default:
|
||
break
|
||
}
|
||
})
|
||
</script>
|
||
<script src='@/scripts/initMap.ts'></script>
|
||
<script src='@/scripts/lockedContent.ts'></script>
|
||
</Layout>
|