150 lines
4.5 KiB
TypeScript
150 lines
4.5 KiB
TypeScript
import furinaImg from "@/assets/furina.webp";
|
|
import hydroElement from "@/assets/hydro.svg";
|
|
import dotPattern from "@/assets/dotpattern.svg";
|
|
import logo from "@/assets/logo.svg";
|
|
import ParallaxView from "./components/parallax-view";
|
|
import ChatWindow from "./components/chat-window";
|
|
import { useEffect, useState } from "react";
|
|
import dayjs from "dayjs";
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { CloudSun, GitPullRequest } from "lucide-react";
|
|
|
|
const App = () => {
|
|
return (
|
|
<div
|
|
className="bg-[#353771] min-h-screen max-h-[100dvh] overflow-hidden relative"
|
|
style={{
|
|
background: "linear-gradient(145deg, #353771 30%, #8ea6f4 150%)",
|
|
}}
|
|
>
|
|
<ParallaxView
|
|
depth={0.005}
|
|
className="absolute inset-0 bg-white"
|
|
style={{
|
|
maskImage: `url(${dotPattern})`,
|
|
maskRepeat: "repeat",
|
|
background:
|
|
"radial-gradient(circle, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0) 90%)",
|
|
transform: "scale(1.2)",
|
|
}}
|
|
/>
|
|
{/* <ParallaxView
|
|
depth={0.01}
|
|
className="absolute w-[90vw] max-w-[800px] bottom-[10%] left-1/2"
|
|
>
|
|
<div className="animate-[wiggle_10s_ease-in-out_infinite] pointer-events-none">
|
|
<div className="-translate-x-[46%] rotate-6 w-full aspect-video bg-[#d0ecf7] drop-shadow-[-40px_-40px_0px_#869de8]" />
|
|
</div>
|
|
</ParallaxView> */}
|
|
<ParallaxView
|
|
depth={0.015}
|
|
className="absolute right-[10%] top-[10%] md:top-[10%]"
|
|
>
|
|
<img
|
|
src={hydroElement}
|
|
className="h-[80vw] md:h-[40vw] blur-sm opacity-20 pointer-events-none"
|
|
/>
|
|
</ParallaxView>
|
|
<ParallaxView
|
|
depth={0.005}
|
|
className="absolute left-1/2 -bottom-[5%] w-full"
|
|
>
|
|
<div className="animate-[updown_8s_ease-in-out_infinite] w-full">
|
|
<img
|
|
src={furinaImg}
|
|
className="max-h-screen w-full aspect-[0.666] object-contain -translate-x-1/2"
|
|
/>
|
|
</div>
|
|
</ParallaxView>
|
|
|
|
<div className="absolute left-1/2 -translate-x-1/2 top-0 h-full w-full max-w-3xl">
|
|
<ParallaxView
|
|
depth={0.01}
|
|
className="absolute top-0 md:top-[10%] left-[10%] md:left-[1%]"
|
|
>
|
|
<div className="animate-[wiggle_10s_ease-in-out_infinite] pointer-events-none">
|
|
<img src={logo} className="w-[120px] md:w-[200px]" />
|
|
</div>
|
|
</ParallaxView>
|
|
|
|
<p className="absolute left-4 md:left-0 bottom-10 text-white text-sm">
|
|
Furina artwork by{" "}
|
|
<a
|
|
href="https://www.pixiv.net/en/users/98144454"
|
|
target="_blank"
|
|
rel="nofollow"
|
|
className="font-bold"
|
|
>
|
|
Rine
|
|
</a>
|
|
</p>
|
|
|
|
<p className="absolute left-4 md:left-auto md:right-0 bottom-4 md:bottom-10 text-white text-sm">
|
|
<GitPullRequest className="inline mr-2" size={16} />
|
|
Fork{" "}
|
|
<a
|
|
href="https://git.rul.sh/khairul169/furina.id"
|
|
target="_blank"
|
|
className="font-bold"
|
|
>
|
|
Repo
|
|
</a>
|
|
</p>
|
|
|
|
<Clock />
|
|
</div>
|
|
|
|
<ChatWindow />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const Clock = () => {
|
|
const [time, setTime] = useState(new Date());
|
|
const { data: weather } = useQuery({
|
|
queryKey: ["forecast"],
|
|
queryFn: async () => {
|
|
const url =
|
|
"https://api.open-meteo.com/v1/forecast?latitude=-6.2297401&longitude=106.7469453¤t_weather=true";
|
|
const res = await fetch(url);
|
|
if (!res.ok) {
|
|
throw new Error(res.statusText);
|
|
}
|
|
const data = await res.json();
|
|
return data?.current_weather;
|
|
},
|
|
});
|
|
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
setTime(new Date());
|
|
}, 1000);
|
|
return () => clearInterval(interval);
|
|
}, []);
|
|
|
|
return (
|
|
<ParallaxView
|
|
depth={0.01}
|
|
className="bg-white/10 border border-white/40 backdrop-blur-sm text-white p-4 rounded-lg absolute right-4 md:right-0 bottom-24 md:bottom-[10%]"
|
|
>
|
|
<p className="text-right">{dayjs(time).format("dddd, DD MMM YYYY")}</p>
|
|
|
|
<p className="text-3xl md:text-5xl font-mono mt-1">
|
|
{dayjs(time).format("hh:mm:ss")}
|
|
</p>
|
|
|
|
{weather ? (
|
|
<div className="flex flex-row items-center gap-2 mt-0.5 justify-end md:text-2xl">
|
|
<CloudSun size={20} />
|
|
<p>
|
|
{weather?.temperature}
|
|
<span className="text-sm"> °C</span>
|
|
</p>
|
|
</div>
|
|
) : null}
|
|
</ParallaxView>
|
|
);
|
|
};
|
|
|
|
export default App;
|