feat: add templates for buttons

This commit is contained in:
log101 2024-07-06 15:56:58 +03:00
parent 68750ad964
commit 5821818618
7 changed files with 126 additions and 64 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -26,6 +26,7 @@
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.1.0", "clsx": "^2.1.0",
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"htmx.org": "^1.9.12",
"kysely": "^0.26.0", "kysely": "^0.26.0",
"lucide-react": "^0.309.0", "lucide-react": "^0.309.0",
"nanoid": "^5.0.4", "nanoid": "^5.0.4",

View File

@ -1,4 +1,6 @@
--- ---
import { LockClosedIcon } from "@radix-ui/react-icons";
interface Props { interface Props {
contentId?: string; contentId?: string;
imageUrl: string; imageUrl: string;
@ -9,8 +11,47 @@ const { contentId = "", imageUrl = "#", location = "" } = Astro.props;
--- ---
<template id="locked-content-template"> <template id="locked-content-template">
<link rel="stylesheet" href="css/tailwind.css" /> <div
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="blur-2xl h-[450px]" />
<div class="flex flex-col justify-center gap-4 overlay">
<template id="unlock-content-button-template">
<button
id="unlock-content-button"
class="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-11 rounded-md text-lg p-6 animate-pulse bg-indigo-600 hover:bg-indigo-700 hover:animate-none border-2 border-indigo-800"
>
İçeriğin Kilidi Açıldı
</button>
</template>
<template id="unlock-content-button-template-locked">
<button
class="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 bg-primary text-primary-foreground hover:bg-primary/90 h-11 rounded-md px-8 text-md"
>
<LockClosedIcon className="mr-2 h-4 w-4" /> İçerik Kilitli
</button>
</template>
<slot name="locked-content-button" />
<unlock-content-button></unlock-content-button>
<slot name="locked-content-description">
<div
class="rounded-lg border bg-card text-card-foreground shadow-sm p-2"
>
<div class="pb-0 px-4 text-center">
İçeriği görmek için butona bas!
</div>
</div>
</slot>
</div>
</div>
</div>
<style> <style>
@import url("css/tailwind.css");
.image-wrapper { .image-wrapper {
position: relative; position: relative;
} }
@ -26,69 +67,9 @@ const { contentId = "", imageUrl = "#", location = "" } = Astro.props;
inset: 0; inset: 0;
} }
</style> </style>
<div
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 src={imageUrl} class="blur-2xl h-[450px]" />
<div class="flex flex-col justify-center gap-4 overlay">
<button
id="unlock-content-button"
class="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-11 rounded-md text-lg p-6 animate-pulse bg-indigo-600 hover:bg-indigo-700 hover:animate-none border-2 border-indigo-800"
>
İçeriğin Kilidi Açıldı
</button>
<div
class="rounded-lg border bg-card text-card-foreground shadow-sm p-2"
>
<div class="pb-0 text-center">İçeriği görmek için butona bas!</div>
</div>
</div>
</div>
</div>
</template> </template>
<locked-content contentId={contentId}></locked-content> <locked-content contentId={contentId} imageURL={imageUrl} id="locked-content"
></locked-content>
<script> <script src="../components/locked-content.ts"></script>
customElements.define(
"locked-content",
class extends HTMLElement {
constructor() {
super();
// Clone the template
let template = document.getElementById(
"locked-content-template"
) as HTMLTemplateElement;
let templateContent = template.content;
// Get attributes
const contentId = this.getAttribute("contentId");
// Attach cloned template to DOM
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(templateContent.cloneNode(true));
// Add onclick listener to unlock content button
const unlockContentButton = shadowRoot.getElementById(
"unlock-content-button"
);
const incrementCounter = async (id: string) =>
await fetch(`http://localhost:3000/api/location/increment/${id}`, {
method: "PATCH",
});
if (unlockContentButton) {
unlockContentButton.addEventListener("click", () => {
if (contentId) {
incrementCounter(contentId);
}
});
}
}
}
);
</script>

View File

@ -0,0 +1,62 @@
class LockedContent extends HTMLElement {
constructor() {
super();
// Clone the template
let template = document.getElementById(
"locked-content-template"
) as HTMLTemplateElement;
let templateContent = template.content;
// Get attributes
const contentId = this.getAttribute("contentId");
const imageURL = this.getAttribute("imageURL") ?? "#";
// Fetch functions
const incrementCounter = async (id: string) =>
await fetch(`http://localhost:3000/api/location/increment/${id}`, {
method: "PATCH",
});
// Attach cloned template to DOM
const shadowRoot = this.attachShadow({ mode: "open" });
shadowRoot.appendChild(templateContent.cloneNode(true));
// Set image source URL
const content = shadowRoot.getElementById("content") as HTMLImageElement;
content.src = imageURL;
// Add onclick listener to unlock content button
const unlockContentButton = shadowRoot.getElementById(
"unlock-content-button"
);
if (unlockContentButton) {
unlockContentButton.addEventListener("click", () => {
if (contentId) {
incrementCounter(contentId);
}
});
}
}
}
class UnlockContentButton extends HTMLElement {
constructor() {
super();
const host = document.getElementById("locked-content");
if (host) {
let template = host.shadowRoot?.getElementById(
"unlock-content-button-template"
) as HTMLTemplateElement;
let templateContent = template.content;
this.appendChild(templateContent.cloneNode(true));
}
}
}
customElements.define("locked-content", LockedContent);
customElements.define("unlock-content-button", UnlockContentButton);

6
src/env.d.ts vendored
View File

@ -2,3 +2,9 @@
/// <reference types="astro/client" /> /// <reference types="astro/client" />
/// <reference types="@types/google.maps" /> /// <reference types="@types/google.maps" />
/// <reference types="@types/leaflet" /> /// <reference types="@types/leaflet" />
export declare global {
interface Window {
htmx: any;
}
}

View File

@ -38,5 +38,11 @@
<body class="container my-8"> <body class="container my-8">
<slot /> <slot />
</body> </body>
<script>
import htmx from "htmx.org";
window.htmx = htmx;
</script>
</html> </html>
<style is:global></style> <style is:global></style>

View File

@ -67,6 +67,12 @@ const dateFromNow = dayjs.utc(data?.created_at).from(dayjs.utc());
<p>{dateFromNow}</p> <p>{dateFromNow}</p>
</CardFooter> </CardFooter>
</Card> </Card>
<WebComponentWrapper
contentId={data?.url}
imageUrl={`http://localhost:3000/images/${data?.blob_url}`}
location={data?.loc}
/>
<LockedContent <LockedContent
contentId={data?.url} contentId={data?.url}
imageUrl={`http://localhost:3000/images/${data?.blob_url}`} imageUrl={`http://localhost:3000/images/${data?.blob_url}`}