feat: show counter at the bottom of the page
This commit is contained in:
parent
3060afa59a
commit
75a403ddf2
|
@ -6,8 +6,18 @@ import { LockClosedIcon, LockOpen1Icon } from "@radix-ui/react-icons"
|
|||
import { useEffect, useState } from "react"
|
||||
|
||||
import "../styles/locked-content.css"
|
||||
import type { Generated } from "kysely"
|
||||
|
||||
const LocationButton = ({ imageUrl = "#" }: { imageUrl?: string }) => {
|
||||
const incrementCounter = async (id: string | Generated<string>) =>
|
||||
await fetch(`${import.meta.env.PUBLIC_HOME_URL}/api/content/increment?id=${id}`)
|
||||
|
||||
const LocationButton = ({
|
||||
contentId = "",
|
||||
imageUrl = "#"
|
||||
}: {
|
||||
contentId?: string | Generated<string>
|
||||
imageUrl?: string
|
||||
}) => {
|
||||
const [atTarget, setAtTarget] = useState(false)
|
||||
const [contentVisible, setContentVisible] = useState(false)
|
||||
const [hasPermission, setHasPermission] = useState(false)
|
||||
|
@ -37,6 +47,11 @@ const LocationButton = ({ imageUrl = "#" }: { imageUrl?: string }) => {
|
|||
}
|
||||
}
|
||||
|
||||
const handleUnlock = async () => {
|
||||
setContentVisible(true)
|
||||
await incrementCounter(contentId)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
navigator.permissions.query({ name: "geolocation" }).then(permissionStatus => {
|
||||
if (permissionStatus.state === "granted") {
|
||||
|
@ -60,7 +75,7 @@ const LocationButton = ({ imageUrl = "#" }: { imageUrl?: string }) => {
|
|||
<img src={imageUrl} className='blur-lg h-[450px]' />
|
||||
|
||||
<div className='flex flex-col justify-center gap-4 overlay'>
|
||||
<Button size='lg' className='text-md' onClick={() => setContentVisible(true)}>
|
||||
<Button size='lg' className='text-md' onClick={handleUnlock}>
|
||||
<LockOpen1Icon className='mr-2 h-4 w-4' />
|
||||
İçeriğin Kilidi Açıldı
|
||||
</Button>
|
||||
|
|
|
@ -12,4 +12,5 @@ export interface ContentTable {
|
|||
author: string
|
||||
description: string
|
||||
created_at: Generated<string>
|
||||
unlocked_counter: Generated<number>
|
||||
}
|
||||
|
|
|
@ -19,11 +19,13 @@ import dayjs from 'dayjs';
|
|||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import localeTR from 'dayjs/locale/tr';
|
||||
|
||||
type Content = Omit<ContentTable, 'id' | 'url'>;
|
||||
type Content = Omit<ContentTable, 'url'>;
|
||||
|
||||
const { id } = Astro.params;
|
||||
|
||||
const res = await fetch(`${import.meta.env.HOME_URL}/api/content?id=${id}`);
|
||||
const res = await fetch(
|
||||
`${import.meta.env.PUBLIC_HOME_URL}/api/content?id=${id}`
|
||||
);
|
||||
|
||||
const data: Content | null = res.status === 200 ? await res.json() : null;
|
||||
|
||||
|
@ -65,7 +67,7 @@ const dateFromNow = dayjs(data?.created_at).fromNow();
|
|||
</CardFooter>
|
||||
</Card>
|
||||
|
||||
<LockedContent imageUrl={data?.blob_url} client:load />
|
||||
<LockedContent contentId={data?.id} imageUrl={data?.blob_url} client:load />
|
||||
|
||||
<div
|
||||
id="map"
|
||||
|
@ -77,7 +79,7 @@ const dateFromNow = dayjs(data?.created_at).fromNow();
|
|||
<Button className="w-full text-lg" size="lg">Paylaş</Button>
|
||||
<div class="flex justify-center">
|
||||
<p class="text-muted-foreground">
|
||||
Fotoğrafın kilidi şu ana dek <b>2</b> kez açıldı
|
||||
Fotoğrafın kilidi şu ana dek <b>{data?.unlocked_counter}</b> kez açıldı
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
|
|
39
src/pages/api/content/increment.ts
Normal file
39
src/pages/api/content/increment.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
import type { Database } from "@/lib/db"
|
||||
import { createKysely } from "@vercel/postgres-kysely"
|
||||
import type { APIRoute } from "astro"
|
||||
|
||||
export const GET: APIRoute = async ({ request }) => {
|
||||
const contentId = new URL(request.url).searchParams.get("id")
|
||||
|
||||
if (!contentId) {
|
||||
return new Response(null, {
|
||||
status: 400,
|
||||
statusText: "Content id is required"
|
||||
})
|
||||
}
|
||||
|
||||
const db = createKysely<Database>({ connectionString: import.meta.env.POSTGRES_URL })
|
||||
|
||||
try {
|
||||
const result = await db
|
||||
.updateTable("contents")
|
||||
.set(eb => ({ unlocked_counter: eb("unlocked_counter", "+", 1) }))
|
||||
.where("id", "=", contentId)
|
||||
.executeTakeFirst()
|
||||
|
||||
if (result) {
|
||||
return new Response(JSON.stringify({ counter: Number(result) }))
|
||||
} else {
|
||||
return new Response(null, {
|
||||
status: 404,
|
||||
statusText: "Could not increment the counter"
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching content:", error)
|
||||
return new Response(null, {
|
||||
status: 500,
|
||||
statusText: "Error while fetching content"
|
||||
})
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ import type { APIRoute } from "astro"
|
|||
import { createKysely } from "@vercel/postgres-kysely"
|
||||
import { customAlphabet } from "nanoid"
|
||||
|
||||
import type { Database } from "../../lib/db"
|
||||
import type { Database } from "@/lib/db"
|
||||
|
||||
export const POST: APIRoute = async ({ request }) => {
|
||||
const data = await request.formData()
|
||||
|
@ -79,11 +79,13 @@ export const GET: APIRoute = async ({ request }) => {
|
|||
const content = await db
|
||||
.selectFrom("contents")
|
||||
.select(({ fn }) => [
|
||||
"id",
|
||||
"blob_url",
|
||||
fn<string>("ST_AsGeoJSON", ["loc"]).as("loc"),
|
||||
"description",
|
||||
"author",
|
||||
"created_at"
|
||||
"created_at",
|
||||
"unlocked_counter"
|
||||
])
|
||||
.where("url", "=", contentId)
|
||||
.executeTakeFirst()
|
Loading…
Reference in New Issue
Block a user