feat: some shit

This commit is contained in:
2023-08-08 21:50:23 +02:00
parent 6123956f08
commit c7d0e97ac0
18 changed files with 482 additions and 73 deletions

95
components/Checkbox.tsx Normal file
View File

@ -0,0 +1,95 @@
import { Signal, useSignal } from "@preact/signals";
import { useId, useState } from "preact/hooks";
interface CheckboxProps {
label: string;
isChecked?: boolean;
onChange: (isChecked: boolean) => void;
}
const Checkbox2: preact.FunctionalComponent<CheckboxProps> = (
{ label, isChecked = false, onChange },
) => {
const [checked, setChecked] = useState(isChecked);
const toggleCheckbox = () => {
const newChecked = !checked;
setChecked(newChecked);
onChange(newChecked);
};
return (
<div
class="flex items-center rounded-xl p-1 pl-4"
style={{ background: "var(--background)", color: "var(--foreground)" }}
>
<span>
{label}
</span>
<label
class="relative flex cursor-pointer items-center rounded-full p-3"
for="checkbox"
data-ripple-dark="true"
>
<input
type="checkbox"
class="before:content[''] peer relative h-5 w-5 cursor-pointer appearance-none rounded-md border border-blue-gray-200 transition-all before:absolute before:top-2/4 before:left-2/4 before:block before:h-12 before:w-12 before:-translate-y-2/4 before:-translate-x-2/4 before:rounded-full before:bg-blue-gray-500 before:opacity-0 before:transition-opacity hover:before:opacity-10"
id="checkbox"
checked
/>
<div
class={`pointer-events-none absolute top-2/4 left-2/4 -translate-y-2/4 -translate-x-2/4 text-white opacity-${
checked ? 100 : 0
} transition-opacity`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-3.5 w-3.5"
viewBox="0 0 20 20"
fill="white"
stroke="currentColor"
stroke-width="1"
>
<path
fill-rule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clip-rule="evenodd"
>
</path>
</svg>
</div>
</label>
</div>
);
};
const Checkbox = (
{ label, checked = useSignal(false) }: {
label: string;
checked?: Signal<boolean>;
},
) => {
const _id = useId();
const id = `checkbox-${_id}`;
return (
<label
className="flex items-center py-3 px-4 rounded-xl"
style={{ color: "var(--foreground)", background: "var(--background)" }}
>
<input
type="checkbox"
checked={checked.value}
name="checkbox-one"
id={id}
onChange={(ev) => {
checked.value = ev.currentTarget.checked;
}}
class="bg-gray-200 hover:bg-gray-300 cursor-pointer
w-5 h-5 border-3 border-amber-500 focus:outline-none rounded-lg"
/>
<span class="ml-3">{label}</span>
</label>
);
};
export default Checkbox;

14
components/Image.tsx Normal file
View File

@ -0,0 +1,14 @@
import { isLocalImage } from "@lib/string.ts";
export function Image(
props: { class: string; src: string; width?: number; height?: number },
) {
if (isLocalImage(props.src)) {
}
return (
<div>
<img src={props.src} width={props.width} height={props.height} />
</div>
);
}

View File

@ -1,5 +1,6 @@
import { Card } from "@components/Card.tsx";
import { Movie } from "@lib/resource/movies.ts";
import { Series } from "@lib/resource/series.ts";
export function MovieCard({ movie }: { movie: Movie }) {
const { meta: { image = "/placeholder.svg" } = {} } = movie;
@ -16,3 +17,19 @@ export function MovieCard({ movie }: { movie: Movie }) {
/>
);
}
export function SeriesCard({ series }: { series: Series }) {
const { meta: { image = "/placeholder.svg" } = {} } = series;
const imageUrl = image?.startsWith("Media/series/")
? `/api/images?image=${image}&width=200&height=200`
: image;
return (
<Card
title={series.name}
image={imageUrl}
link={`/series/${series.id}`}
/>
);
}

34
components/Rating.tsx Normal file
View File

@ -0,0 +1,34 @@
import { IconStar, IconStarFilled } from "@components/icons.tsx";
import { useSignal } from "@preact/signals";
import { useState } from "preact/hooks";
export const Rating = (
props: { max?: number; rating: number },
) => {
const [rating, setRating] = useState(props.rating);
const [hover, setHover] = useState(0);
const max = useSignal(props.max || 5);
return (
<div
class="flex gap-2 px-5 rounded-2xl bg-gray-200 z-10"
style={{ color: "var(--foreground)", background: "var(--background)" }}
>
{Array.from({ length: max.value }).map((_, i) => {
return (
<span
class={`my-5 cursor-pointer opacity-${
(i + 1) <= rating ? 100 : (i + 1) <= hover ? 20 : 100
}`}
onMouseOver={() => setHover(i + 1)}
onClick={() => setRating(i + 1)}
>
{(i + 1) <= rating || (i + 1) <= hover
? <IconStarFilled class="w-4 h-4" />
: <IconStar class="w-4 h-4" />}
</span>
);
})}
</div>
);
};