add treasures (artworks)
This commit is contained in:
parent
205f92001c
commit
2cbaca844e
5
backend/.gitignore
vendored
Normal file
5
backend/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CHANGELOG.md
|
||||||
|
LICENSE.md
|
||||||
|
*.zip
|
||||||
|
pocketbase
|
||||||
|
pb_data/
|
1
backend/.pbversion
Normal file
1
backend/.pbversion
Normal file
@ -0,0 +1 @@
|
|||||||
|
0.20.5
|
13
backend/package.json
Normal file
13
backend/package.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "backend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "./pocketbase serve",
|
||||||
|
"clean-migrations": "rm -rf pb_migrations && ./pocketbase migrate collections"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
11
backend/pb_hooks/main.pb.js
Normal file
11
backend/pb_hooks/main.pb.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
/// <reference path="../pb_data/types.d.ts" />
|
||||||
|
|
||||||
|
// artwork view hook
|
||||||
|
onRecordViewRequest((e) => {
|
||||||
|
const { record } = e;
|
||||||
|
if (record) {
|
||||||
|
record.set("views", record.getInt("views") + 1);
|
||||||
|
$app.dao().saveRecord(record);
|
||||||
|
}
|
||||||
|
}, "artworks");
|
161
backend/pb_migrations/1704899482_collections_snapshot.js
Normal file
161
backend/pb_migrations/1704899482_collections_snapshot.js
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/// <reference path="../pb_data/types.d.ts" />
|
||||||
|
migrate((db) => {
|
||||||
|
const snapshot = [
|
||||||
|
{
|
||||||
|
"id": "_pb_users_auth_",
|
||||||
|
"created": "2024-01-10 09:29:21.510Z",
|
||||||
|
"updated": "2024-01-10 09:29:21.511Z",
|
||||||
|
"name": "users",
|
||||||
|
"type": "auth",
|
||||||
|
"system": false,
|
||||||
|
"schema": [
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "users_name",
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "users_avatar",
|
||||||
|
"name": "avatar",
|
||||||
|
"type": "file",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"mimeTypes": [
|
||||||
|
"image/jpeg",
|
||||||
|
"image/png",
|
||||||
|
"image/svg+xml",
|
||||||
|
"image/gif",
|
||||||
|
"image/webp"
|
||||||
|
],
|
||||||
|
"thumbs": null,
|
||||||
|
"maxSelect": 1,
|
||||||
|
"maxSize": 5242880,
|
||||||
|
"protected": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [],
|
||||||
|
"listRule": "id = @request.auth.id",
|
||||||
|
"viewRule": "id = @request.auth.id",
|
||||||
|
"createRule": "",
|
||||||
|
"updateRule": "id = @request.auth.id",
|
||||||
|
"deleteRule": "id = @request.auth.id",
|
||||||
|
"options": {
|
||||||
|
"allowEmailAuth": true,
|
||||||
|
"allowOAuth2Auth": true,
|
||||||
|
"allowUsernameAuth": true,
|
||||||
|
"exceptEmailDomains": null,
|
||||||
|
"manageRule": null,
|
||||||
|
"minPasswordLength": 8,
|
||||||
|
"onlyEmailDomains": null,
|
||||||
|
"onlyVerified": false,
|
||||||
|
"requireEmail": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "eo6iaxf4pkeqynf",
|
||||||
|
"created": "2024-01-10 09:34:57.731Z",
|
||||||
|
"updated": "2024-01-10 15:08:00.292Z",
|
||||||
|
"name": "artworks",
|
||||||
|
"type": "base",
|
||||||
|
"system": false,
|
||||||
|
"schema": [
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "p6dor6eo",
|
||||||
|
"name": "image",
|
||||||
|
"type": "file",
|
||||||
|
"required": true,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"mimeTypes": [
|
||||||
|
"image/png",
|
||||||
|
"image/jpeg",
|
||||||
|
"image/gif",
|
||||||
|
"image/webp",
|
||||||
|
"image/tiff",
|
||||||
|
"image/bmp",
|
||||||
|
"image/svg+xml"
|
||||||
|
],
|
||||||
|
"thumbs": [
|
||||||
|
"256x192",
|
||||||
|
"256x384",
|
||||||
|
"32x48"
|
||||||
|
],
|
||||||
|
"maxSelect": 1,
|
||||||
|
"maxSize": 5242880,
|
||||||
|
"protected": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "9w1tjysa",
|
||||||
|
"name": "artistName",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "lkiiiwrt",
|
||||||
|
"name": "srcUrl",
|
||||||
|
"type": "text",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"pattern": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"system": false,
|
||||||
|
"id": "sfh7xwdb",
|
||||||
|
"name": "views",
|
||||||
|
"type": "number",
|
||||||
|
"required": false,
|
||||||
|
"presentable": false,
|
||||||
|
"unique": false,
|
||||||
|
"options": {
|
||||||
|
"min": null,
|
||||||
|
"max": null,
|
||||||
|
"noDecimal": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"indexes": [],
|
||||||
|
"listRule": "",
|
||||||
|
"viewRule": "",
|
||||||
|
"createRule": null,
|
||||||
|
"updateRule": null,
|
||||||
|
"deleteRule": null,
|
||||||
|
"options": {}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const collections = snapshot.map((item) => new Collection(item));
|
||||||
|
|
||||||
|
return Dao(db).importCollections(collections, true, null);
|
||||||
|
}, (db) => {
|
||||||
|
return null;
|
||||||
|
})
|
@ -17,9 +17,11 @@
|
|||||||
"howler": "^2.2.4",
|
"howler": "^2.2.4",
|
||||||
"lucide-react": "^0.306.0",
|
"lucide-react": "^0.306.0",
|
||||||
"pixi.js": "^7.3.3",
|
"pixi.js": "^7.3.3",
|
||||||
|
"pocketbase": "^0.20.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
|
"react-query": "^3.39.3",
|
||||||
"react-router-dom": "^6.21.1",
|
"react-router-dom": "^6.21.1",
|
||||||
"react-toastify": "^9.1.3",
|
"react-toastify": "^9.1.3",
|
||||||
"tailwind-merge": "^2.2.0",
|
"tailwind-merge": "^2.2.0",
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
import { ToastContainer } from "react-toastify";
|
import { ToastContainer } from "react-toastify";
|
||||||
import Router from "./Router";
|
import Router from "./Router";
|
||||||
import "react-toastify/dist/ReactToastify.css";
|
import "react-toastify/dist/ReactToastify.css";
|
||||||
|
import { QueryClient, QueryClientProvider } from "react-query";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
const [queryClient] = useState(new QueryClient());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
<Router />
|
<Router />
|
||||||
|
</QueryClientProvider>
|
||||||
<ToastContainer />
|
<ToastContainer />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -5,6 +5,7 @@ import ErrorBoundaryPage from "./pages/errors/error-boundary/page";
|
|||||||
|
|
||||||
const HomePage = lazy(() => import("./pages/home/page"));
|
const HomePage = lazy(() => import("./pages/home/page"));
|
||||||
const MyFurinaPage = lazy(() => import("./pages/my-furina/page"));
|
const MyFurinaPage = lazy(() => import("./pages/my-furina/page"));
|
||||||
|
const ArtworksPage = lazy(() => import("./pages/artworks/page"));
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
@ -12,6 +13,10 @@ const router = createBrowserRouter([
|
|||||||
children: [
|
children: [
|
||||||
{ index: true, Component: HomePage },
|
{ index: true, Component: HomePage },
|
||||||
{ path: "/toodle", Component: MyFurinaPage },
|
{ path: "/toodle", Component: MyFurinaPage },
|
||||||
|
{
|
||||||
|
path: "/treasures",
|
||||||
|
children: [{ index: true, Component: ArtworksPage }],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
ErrorBoundary: () => (
|
ErrorBoundary: () => (
|
||||||
<MainLayout>
|
<MainLayout>
|
||||||
|
BIN
src/assets/audio/VO_JA_Furina_Elemental_Burst_03.ogg
Normal file
BIN
src/assets/audio/VO_JA_Furina_Elemental_Burst_03.ogg
Normal file
Binary file not shown.
BIN
src/assets/audio/VO_JA_Furina_Opening_Treasure_Chest_02.ogg
Normal file
BIN
src/assets/audio/VO_JA_Furina_Opening_Treasure_Chest_02.ogg
Normal file
Binary file not shown.
@ -9,7 +9,7 @@ import { cn } from "@/utility/utils";
|
|||||||
const AppBar = () => {
|
const AppBar = () => {
|
||||||
return (
|
return (
|
||||||
<header className="w-full bg-[#111a21] shadow">
|
<header className="w-full bg-[#111a21] shadow">
|
||||||
<div className="container py-8 md:py-4 flex flex-col md:flex-row items-center gap-4">
|
<div className="mx-auto max-w-5xl md:px-4 pt-6 md:py-4 flex flex-col md:flex-row items-center gap-4">
|
||||||
<Link
|
<Link
|
||||||
to="/"
|
to="/"
|
||||||
className="flex flex-col md:flex-row items-center gap-2 md:gap-4"
|
className="flex flex-col md:flex-row items-center gap-2 md:gap-4"
|
||||||
@ -24,6 +24,7 @@ const AppBar = () => {
|
|||||||
|
|
||||||
<Navbar>
|
<Navbar>
|
||||||
<NavbarItem path="/" title="Pet the Furina" />
|
<NavbarItem path="/" title="Pet the Furina" />
|
||||||
|
<NavbarItem path="/treasures" title="Treasures‧₊˚" />
|
||||||
<NavbarItem path="/toodle" title="Toodle-oo~" />
|
<NavbarItem path="/toodle" title="Toodle-oo~" />
|
||||||
</Navbar>
|
</Navbar>
|
||||||
</div>
|
</div>
|
||||||
@ -33,7 +34,7 @@ const AppBar = () => {
|
|||||||
|
|
||||||
const Navbar = ({ children }: ComponentProps<"div">) => {
|
const Navbar = ({ children }: ComponentProps<"div">) => {
|
||||||
return (
|
return (
|
||||||
<nav className="flex-1 flex items-center justify-end gap-3 md:gap-5 overflow-x-auto md:overflow-x-hidden">
|
<nav className="md:flex-1 self-stretch md:self-center flex items-center px-2 md:px-0 md:justify-end md:gap-5 overflow-x-auto md:overflow-x-hidden">
|
||||||
{children}
|
{children}
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
@ -50,7 +51,10 @@ const NavbarItem = ({ path, title, isExact = true }: NavbarItemProps) => {
|
|||||||
const isActive = isExact ? pathname === path : pathname.startsWith(path);
|
const isActive = isExact ? pathname === path : pathname.startsWith(path);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to={path} className="group flex items-center md:py-4">
|
<Link
|
||||||
|
to={path}
|
||||||
|
className="group flex flex-shrink-0 items-center px-2 md:px-0 md:py-4 first:ml-auto last:mr-auto"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src={ahogeImg}
|
src={ahogeImg}
|
||||||
alt="ahoge"
|
alt="ahoge"
|
||||||
@ -62,8 +66,8 @@ const NavbarItem = ({ path, title, isExact = true }: NavbarItemProps) => {
|
|||||||
|
|
||||||
<p
|
<p
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-white ml-2 md:ml-4 md:text-xl border-b-2 border-dotted group-hover:border-white/80 border-transparent transition-all",
|
"text-white ml-2 md:ml-4 md:text-xl py-2 md:py-0 border-b-2 md:border-dotted group-hover:border-primary-500 border-transparent transition-all",
|
||||||
isActive ? "border-white" : ""
|
isActive ? "border-primary-500 md:border-white" : ""
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
|
@ -17,11 +17,8 @@ const MainLayout = ({ children }: ComponentProps<"div">) => {
|
|||||||
</Suspense>
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<footer className="bg-primary-700 px-4 py-8 text-center">
|
<footer className="bg-primary-700 shadow relative z-10 px-4 py-8 text-center">
|
||||||
<p className="text-sm text-white">
|
<p className="text-sm text-white">
|
||||||
<a href="http://rul.sh/">
|
|
||||||
Made with <span className="text-red-300">♡</span> by Khairul.
|
|
||||||
</a>{" "}
|
|
||||||
Artworks displayed belong to respective owners.
|
Artworks displayed belong to respective owners.
|
||||||
</p>
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
36
src/components/ui/Badge.tsx
Normal file
36
src/components/ui/Badge.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority";
|
||||||
|
|
||||||
|
import { cn } from "@/utility/utils";
|
||||||
|
|
||||||
|
const badgeVariants = cva(
|
||||||
|
"inline-flex items-center rounded border border-primary-200 px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-primary-950 focus:ring-offset-2 dark:border-primary-800 dark:focus:ring-primary-300",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default:
|
||||||
|
"border-transparent bg-primary-600 text-primary-50 hover:bg-primary-600/80 dark:bg-primary-50 dark:text-primary-900 dark:hover:bg-primary-50/80",
|
||||||
|
secondary:
|
||||||
|
"border-transparent bg-primary-100 text-primary-900 hover:bg-primary-100/80 dark:bg-primary-800 dark:text-primary-50 dark:hover:bg-primary-800/80",
|
||||||
|
destructive:
|
||||||
|
"border-transparent bg-red-500 text-primary-50 hover:bg-red-500/80 dark:bg-red-900 dark:text-primary-50 dark:hover:bg-red-900/80",
|
||||||
|
outline: "text-primary-950 dark:text-primary-50",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export interface BadgeProps
|
||||||
|
extends React.HTMLAttributes<HTMLDivElement>,
|
||||||
|
VariantProps<typeof badgeVariants> {}
|
||||||
|
|
||||||
|
function Badge({ className, variant, ...props }: BadgeProps) {
|
||||||
|
return (
|
||||||
|
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Badge;
|
42
src/components/ui/LazyImage.tsx
Normal file
42
src/components/ui/LazyImage.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { cn } from "@/utility/utils";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
type Props = React.ComponentProps<"img"> & {
|
||||||
|
lazySrc: string;
|
||||||
|
containerClassName?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const LazyImage = ({
|
||||||
|
lazySrc,
|
||||||
|
src,
|
||||||
|
containerClassName,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Props) => {
|
||||||
|
const [isLoaded, setLoaded] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"bg-no-repeat bg-cover",
|
||||||
|
!isLoaded ? "blur-md" : "",
|
||||||
|
containerClassName
|
||||||
|
)}
|
||||||
|
style={{ backgroundImage: `url('${lazySrc}')` }}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
loading="lazy"
|
||||||
|
onLoad={() => setLoaded(true)}
|
||||||
|
className={cn(
|
||||||
|
"transition-all",
|
||||||
|
isLoaded ? "opacity-100" : "opacity-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LazyImage;
|
156
src/components/ui/Sheet.tsx
Normal file
156
src/components/ui/Sheet.tsx
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority";
|
||||||
|
import { X } from "lucide-react";
|
||||||
|
|
||||||
|
import { cn } from "@/utility/utils";
|
||||||
|
|
||||||
|
const SheetRoot = SheetPrimitive.Root;
|
||||||
|
|
||||||
|
const SheetPortal = SheetPrimitive.Portal;
|
||||||
|
|
||||||
|
const SheetOverlay = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SheetPrimitive.Overlay
|
||||||
|
className={cn(
|
||||||
|
"fixed inset-0 z-50 bg-black/20 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
ref={ref}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
||||||
|
|
||||||
|
const sheetVariants = cva(
|
||||||
|
"fixed z-50 gap-4 bg-white shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500 dark:bg-slate-950",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
side: {
|
||||||
|
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
||||||
|
bottom:
|
||||||
|
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
||||||
|
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
||||||
|
right:
|
||||||
|
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
side: "right",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
interface SheetContentProps
|
||||||
|
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
||||||
|
VariantProps<typeof sheetVariants> {}
|
||||||
|
|
||||||
|
const SheetContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SheetPrimitive.Content>,
|
||||||
|
SheetContentProps
|
||||||
|
>(({ side = "right", className, children, ...props }, ref) => (
|
||||||
|
<SheetPortal>
|
||||||
|
<SheetOverlay />
|
||||||
|
<SheetPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
className={cn(sheetVariants({ side }), className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-slate-950 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-slate-100 dark:ring-offset-slate-950 dark:focus:ring-slate-300 dark:data-[state=open]:bg-slate-800">
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
<span className="sr-only">Close</span>
|
||||||
|
</SheetPrimitive.Close>
|
||||||
|
</SheetPrimitive.Content>
|
||||||
|
</SheetPortal>
|
||||||
|
));
|
||||||
|
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
||||||
|
|
||||||
|
const SheetHeader = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col p-4 space-y-2 text-center sm:text-left",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
SheetHeader.displayName = "SheetHeader";
|
||||||
|
|
||||||
|
const SheetFooter = ({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
SheetFooter.displayName = "SheetFooter";
|
||||||
|
|
||||||
|
const SheetTitle = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SheetPrimitive.Title>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SheetPrimitive.Title
|
||||||
|
ref={ref}
|
||||||
|
className={cn(
|
||||||
|
"text-lg font-semibold text-slate-950 dark:text-slate-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
||||||
|
|
||||||
|
const SheetDescription = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SheetPrimitive.Description>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SheetPrimitive.Description
|
||||||
|
ref={ref}
|
||||||
|
className={cn("text-sm text-slate-500 dark:text-slate-400", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
||||||
|
|
||||||
|
type SheetProps = React.ComponentProps<typeof SheetRoot> & {
|
||||||
|
isOpen?: boolean;
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
position?: SheetContentProps["side"];
|
||||||
|
};
|
||||||
|
|
||||||
|
const Sheet = ({
|
||||||
|
isOpen,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
children,
|
||||||
|
position,
|
||||||
|
...props
|
||||||
|
}: SheetProps) => {
|
||||||
|
return (
|
||||||
|
<SheetRoot open={isOpen} {...props}>
|
||||||
|
<SheetContent side={position} className="rounded-t-2xl">
|
||||||
|
<SheetHeader>
|
||||||
|
{title ? <SheetTitle>{title}</SheetTitle> : null}
|
||||||
|
{description ? (
|
||||||
|
<SheetDescription>{description}</SheetDescription>
|
||||||
|
) : null}
|
||||||
|
</SheetHeader>
|
||||||
|
<div className="max-h-[90vh] overflow-y-auto">{children}</div>
|
||||||
|
</SheetContent>
|
||||||
|
</SheetRoot>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Sheet;
|
@ -1,12 +1,15 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
const useModal = () => {
|
const useModal = <T = unknown>() => {
|
||||||
const [isOpen, setOpen] = useState(false);
|
const [isOpen, setOpen] = useState(false);
|
||||||
|
const [data, setData] = useState<T | undefined | null>(null);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isOpen,
|
isOpen,
|
||||||
onOpen() {
|
data,
|
||||||
|
onOpen(_data?: T | null) {
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
|
setData(_data);
|
||||||
},
|
},
|
||||||
onClose() {
|
onClose() {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
71
src/pages/artworks/page.tsx
Normal file
71
src/pages/artworks/page.tsx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import pb from "@/utility/api";
|
||||||
|
import { Howl } from "howler";
|
||||||
|
import { useQuery } from "react-query";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import playIcon from "@/assets/icons/play-outline.svg";
|
||||||
|
import openingSfx from "@/assets/audio/VO_JA_Furina_Opening_Treasure_Chest_02.ogg";
|
||||||
|
import ViewSheet from "./viewSheet";
|
||||||
|
import useModal from "@/hooks/useModal";
|
||||||
|
import LazyImage from "@/components/ui/LazyImage";
|
||||||
|
|
||||||
|
const openingChestSfx = new Howl({
|
||||||
|
src: openingSfx,
|
||||||
|
preload: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const ArtworksPage = () => {
|
||||||
|
const { data } = useQuery({
|
||||||
|
queryKey: ["artworks"],
|
||||||
|
queryFn: () =>
|
||||||
|
pb.collection("artworks").getList(1, 100, { sort: "-created" }),
|
||||||
|
});
|
||||||
|
const viewItemModal = useModal<string>();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container py-16">
|
||||||
|
<h1 className="text-2xl">Treasures</h1>
|
||||||
|
<div>
|
||||||
|
<p className="italic inline">Take it. Ahem... I allow you!</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="bg-white rounded border-2 border-primary-300 hover:bg-gray-200 p-1 md:p-0.5 ml-2"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={playIcon}
|
||||||
|
alt="play"
|
||||||
|
className="h-4"
|
||||||
|
onClick={() => openingChestSfx.play()}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-4 mt-8">
|
||||||
|
{data?.items.map((item) => (
|
||||||
|
<Link
|
||||||
|
key={item.id}
|
||||||
|
// to={`/treasures/${item.id}`}
|
||||||
|
to="#"
|
||||||
|
className="bg-white rounded-lg shadow border border-gray-300 overflow-hidden hover:scale-105 transition-all relative"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
viewItemModal.onOpen(item.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LazyImage
|
||||||
|
lazySrc={pb.files.getUrl(item, item.image, { thumb: "32x48" })}
|
||||||
|
src={pb.files.getUrl(item, item.image)}
|
||||||
|
className="w-full aspect-[0.8] object-cover"
|
||||||
|
/>
|
||||||
|
<div className="absolute bottom-2 left-2 px-3 py-1 rounded-md bg-black/20 backdrop-blur-sm">
|
||||||
|
<p className="text-white">{item.artistName}</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ViewSheet modal={viewItemModal} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ArtworksPage;
|
75
src/pages/artworks/viewSheet.tsx
Normal file
75
src/pages/artworks/viewSheet.tsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import Sheet from "@/components/ui/Sheet";
|
||||||
|
import useModal from "@/hooks/useModal";
|
||||||
|
import pb from "@/utility/api";
|
||||||
|
import { useQuery } from "react-query";
|
||||||
|
import loadingIllust from "@/assets/images/l9fsdoa2j7vb1.gif";
|
||||||
|
import Badge from "@/components/ui/Badge";
|
||||||
|
import Button from "@/components/ui/Button";
|
||||||
|
import { ChevronLeft } from "lucide-react";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
modal: ReturnType<typeof useModal<string>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ViewSheet = ({ modal }: Props) => {
|
||||||
|
const id = modal.data;
|
||||||
|
const { data, isLoading, isError } = useQuery({
|
||||||
|
queryKey: ["artwork", id],
|
||||||
|
queryFn: () => pb.collection("artworks").getOne(id || ""),
|
||||||
|
enabled: !!id,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Sheet {...modal} title="View Item" position="bottom">
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="min-h-[320px] flex flex-col items-center justify-center text-center">
|
||||||
|
<img src={loadingIllust} className="h-40 animate-bounce" />
|
||||||
|
<p className="mt-2">Please wait a moment...</p>
|
||||||
|
</div>
|
||||||
|
) : isError || !data ? (
|
||||||
|
<div className="min-h-[320px] flex flex-col items-center justify-center text-center">
|
||||||
|
<h1 className="text-2xl">An error occured.</h1>
|
||||||
|
<p className="mt-2">Cannot load item</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col md:flex-row">
|
||||||
|
<div className="flex-1 bg-gray-50">
|
||||||
|
<a href={data.srcUrl} target="_blank">
|
||||||
|
<img
|
||||||
|
src={pb.files.getUrl(data, data.image)}
|
||||||
|
className="w-full max-h-[80vh] object-contain"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="md:w-1/3 border-t md:border-l md:border-t-0 py-4 md:pt-0 pl-4 lg:pl-8 overflow-y-auto overflow-x-hidden truncate">
|
||||||
|
<Button
|
||||||
|
className="hidden md:flex pl-2 md:mb-6"
|
||||||
|
onClick={modal.onClose}
|
||||||
|
>
|
||||||
|
<ChevronLeft /> Back
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Badge>Artist Name</Badge>
|
||||||
|
<p className="mt-1 truncate">{data.artistName}</p>
|
||||||
|
|
||||||
|
<Badge className="mt-4">Source</Badge>
|
||||||
|
<a
|
||||||
|
href={data.srcUrl}
|
||||||
|
target="_blank"
|
||||||
|
className="block mt-1 text-primary-500 font-medium hover:underline truncate"
|
||||||
|
>
|
||||||
|
{cleanUrl(data.srcUrl)}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Sheet>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const cleanUrl = (url: string) => {
|
||||||
|
return url.replace("https://", "").replace("http://", "").replace("www.", "");
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ViewSheet;
|
@ -65,7 +65,7 @@ const Credits = () => {
|
|||||||
const modal = useModal();
|
const modal = useModal();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container pt-4 pb-16 border-t">
|
<div className="container pt-4 pb-16">
|
||||||
<Button onClick={modal.onOpen}>Assets Credits</Button>
|
<Button onClick={modal.onOpen}>Assets Credits</Button>
|
||||||
|
|
||||||
<Modal {...modal} title="Big Thanks to:" size="xl">
|
<Modal {...modal} title="Big Thanks to:" size="xl">
|
||||||
|
@ -4,13 +4,18 @@ import buildImg from "@/assets/images/furina-build.webp";
|
|||||||
import furinaChibiImg from "@/assets/images/113932900_p0_master1200.webp";
|
import furinaChibiImg from "@/assets/images/113932900_p0_master1200.webp";
|
||||||
import copyIcon from "@/assets/icons/copy-outline.svg";
|
import copyIcon from "@/assets/icons/copy-outline.svg";
|
||||||
import playIcon from "@/assets/icons/play-outline.svg";
|
import playIcon from "@/assets/icons/play-outline.svg";
|
||||||
import skillAudio from "@/assets/audio/VO_JA_Furina_Elemental_Skill_1_04.ogg";
|
import skillAudio from "@/assets/audio/VO_JA_Furina_Elemental_Burst_03.ogg";
|
||||||
import { cn, copyToClipboard, showToast } from "@/utility/utils";
|
import { cn, copyToClipboard, showToast } from "@/utility/utils";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { Howl } from "howler";
|
||||||
import styles from "./style.module.css";
|
import styles from "./style.module.css";
|
||||||
import PageMetadata from "@/components/containers/PageMetadata";
|
import PageMetadata from "@/components/containers/PageMetadata";
|
||||||
|
|
||||||
const gameUID = "828243224";
|
const gameUID = "828243224";
|
||||||
|
const skillAudioSfx = new Howl({
|
||||||
|
src: skillAudio,
|
||||||
|
preload: true,
|
||||||
|
});
|
||||||
|
|
||||||
const FurinaBelovedPage = () => {
|
const FurinaBelovedPage = () => {
|
||||||
const onCopyUID = () => {
|
const onCopyUID = () => {
|
||||||
@ -132,47 +137,22 @@ const HeroBackground = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const SkillAudioPlayer = () => {
|
const SkillAudioPlayer = () => {
|
||||||
const skillAudioRef = useRef<HTMLAudioElement>(null);
|
|
||||||
const playingTimeout = useRef<any>(null);
|
|
||||||
const [isPlaying, setPlaying] = useState(false);
|
|
||||||
|
|
||||||
const onPlayAudio = () => {
|
|
||||||
skillAudioRef.current?.play();
|
|
||||||
setPlaying(true);
|
|
||||||
|
|
||||||
if (playingTimeout.current) {
|
|
||||||
clearTimeout(playingTimeout.current);
|
|
||||||
}
|
|
||||||
|
|
||||||
playingTimeout.current = setTimeout(() => {
|
|
||||||
setPlaying(false);
|
|
||||||
playingTimeout.current = null;
|
|
||||||
}, 4000);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`group flex flex-col items-center justify-center text-center border border-transparent hover:border-primary-500
|
className={`group flex flex-col items-center justify-center text-center border border-transparent hover:border-primary-500
|
||||||
rounded-xl px-6 py-4 hover:shadow transition-all hover:text-orange-500 hover:scale-105 active:scale-100 active:translate-y-5`}
|
rounded-xl px-6 py-4 hover:shadow transition-all hover:text-orange-500 hover:scale-105 active:scale-100 active:translate-y-5`}
|
||||||
onClick={onPlayAudio}
|
onClick={() => skillAudioSfx.play()}
|
||||||
>
|
>
|
||||||
<img
|
<img src={playIcon} className="h-8" />
|
||||||
src={playIcon}
|
|
||||||
className={cn("h-8", isPlaying ? styles.playAnims : "")}
|
|
||||||
/>
|
|
||||||
<p className="text-xl font-light mt-4">
|
<p className="text-xl font-light mt-4">
|
||||||
✮⋆{" "}
|
✮⋆{" "}
|
||||||
<span className="group-hover:text-purple-500">The curtain rises</span>{" "}
|
<span className="group-hover:text-purple-500">
|
||||||
|
Let my name echo in song!
|
||||||
|
</span>{" "}
|
||||||
✩ ₊˚
|
✩ ₊˚
|
||||||
</p>
|
</p>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<audio ref={skillAudioRef}>
|
|
||||||
<source src={skillAudio} type="audio/ogg" />
|
|
||||||
</audio>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
6
src/utility/api.ts
Normal file
6
src/utility/api.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import PocketBase from "pocketbase";
|
||||||
|
|
||||||
|
export const baseUrl = "http://127.0.0.1:8090";
|
||||||
|
const pb = new PocketBase(baseUrl);
|
||||||
|
|
||||||
|
export default pb;
|
90
yarn.lock
90
yarn.lock
@ -184,6 +184,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.22.5"
|
"@babel/helper-plugin-utils" "^7.22.5"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2":
|
||||||
|
version "7.23.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650"
|
||||||
|
integrity sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.14.0"
|
||||||
|
|
||||||
"@babel/runtime@^7.13.10", "@babel/runtime@^7.23.5":
|
"@babel/runtime@^7.13.10", "@babel/runtime@^7.23.5":
|
||||||
version "7.23.7"
|
version "7.23.7"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.7.tgz#dd7c88deeb218a0f8bd34d5db1aa242e0f203193"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.7.tgz#dd7c88deeb218a0f8bd34d5db1aa242e0f203193"
|
||||||
@ -1209,6 +1216,11 @@ balanced-match@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||||
|
|
||||||
|
big-integer@^1.6.16:
|
||||||
|
version "1.6.52"
|
||||||
|
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85"
|
||||||
|
integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==
|
||||||
|
|
||||||
binary-extensions@^2.0.0:
|
binary-extensions@^2.0.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||||
@ -1236,6 +1248,20 @@ braces@^3.0.2, braces@~3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.0.1"
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
|
broadcast-channel@^3.4.1:
|
||||||
|
version "3.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937"
|
||||||
|
integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.7.2"
|
||||||
|
detect-node "^2.1.0"
|
||||||
|
js-sha3 "0.8.0"
|
||||||
|
microseconds "0.2.0"
|
||||||
|
nano-time "1.0.0"
|
||||||
|
oblivious-set "1.0.0"
|
||||||
|
rimraf "3.0.2"
|
||||||
|
unload "2.2.0"
|
||||||
|
|
||||||
browserslist@^4.21.10, browserslist@^4.22.2:
|
browserslist@^4.21.10, browserslist@^4.22.2:
|
||||||
version "4.22.2"
|
version "4.22.2"
|
||||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b"
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b"
|
||||||
@ -1408,6 +1434,11 @@ detect-node-es@^1.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
|
resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
|
||||||
integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
|
integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
|
||||||
|
|
||||||
|
detect-node@^2.0.4, detect-node@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
|
||||||
|
integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
|
||||||
|
|
||||||
didyoumean@^1.2.2:
|
didyoumean@^1.2.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
|
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
|
||||||
@ -1938,6 +1969,11 @@ jiti@^1.19.1:
|
|||||||
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
|
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
|
||||||
integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
|
integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
|
||||||
|
|
||||||
|
js-sha3@0.8.0:
|
||||||
|
version "0.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
|
||||||
|
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
|
||||||
|
|
||||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
@ -2048,6 +2084,14 @@ lucide-react@^0.306.0:
|
|||||||
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.306.0.tgz#07e427c1c0e6c6d50712b746b889ff807606131c"
|
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.306.0.tgz#07e427c1c0e6c6d50712b746b889ff807606131c"
|
||||||
integrity sha512-eShuk2PI3vxN4YN8kNPmhAsroSvPXbtaxU/UX/zrBcLLg8FeFH9MG7C2EYzYsT2rNrPVjbP7rpBz3mOviZYN3A==
|
integrity sha512-eShuk2PI3vxN4YN8kNPmhAsroSvPXbtaxU/UX/zrBcLLg8FeFH9MG7C2EYzYsT2rNrPVjbP7rpBz3mOviZYN3A==
|
||||||
|
|
||||||
|
match-sorter@^6.0.2:
|
||||||
|
version "6.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda"
|
||||||
|
integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
remove-accents "0.4.2"
|
||||||
|
|
||||||
merge2@^1.3.0, merge2@^1.4.1:
|
merge2@^1.3.0, merge2@^1.4.1:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||||
@ -2061,6 +2105,11 @@ micromatch@^4.0.4, micromatch@^4.0.5:
|
|||||||
braces "^3.0.2"
|
braces "^3.0.2"
|
||||||
picomatch "^2.3.1"
|
picomatch "^2.3.1"
|
||||||
|
|
||||||
|
microseconds@0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39"
|
||||||
|
integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==
|
||||||
|
|
||||||
minimatch@9.0.3, minimatch@^9.0.1:
|
minimatch@9.0.3, minimatch@^9.0.1:
|
||||||
version "9.0.3"
|
version "9.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
|
||||||
@ -2094,6 +2143,13 @@ mz@^2.7.0:
|
|||||||
object-assign "^4.0.1"
|
object-assign "^4.0.1"
|
||||||
thenify-all "^1.0.0"
|
thenify-all "^1.0.0"
|
||||||
|
|
||||||
|
nano-time@1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef"
|
||||||
|
integrity sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==
|
||||||
|
dependencies:
|
||||||
|
big-integer "^1.6.16"
|
||||||
|
|
||||||
nanoid@^3.3.7:
|
nanoid@^3.3.7:
|
||||||
version "3.3.7"
|
version "3.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||||
@ -2134,6 +2190,11 @@ object-inspect@^1.9.0:
|
|||||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
|
||||||
integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
|
integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
|
||||||
|
|
||||||
|
oblivious-set@1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566"
|
||||||
|
integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==
|
||||||
|
|
||||||
once@^1.3.0:
|
once@^1.3.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
@ -2263,6 +2324,11 @@ pixi.js@^7.3.3:
|
|||||||
"@pixi/text-bitmap" "7.3.3"
|
"@pixi/text-bitmap" "7.3.3"
|
||||||
"@pixi/text-html" "7.3.3"
|
"@pixi/text-html" "7.3.3"
|
||||||
|
|
||||||
|
pocketbase@^0.20.1:
|
||||||
|
version "0.20.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/pocketbase/-/pocketbase-0.20.1.tgz#e34a0113306322f9382a8b775de3b83f7304929f"
|
||||||
|
integrity sha512-Gl51UBc1U03JlwmwMkUIa1OHbcTmmdhyMPV1aJyHp9HuY5VUlh0t4hcx6D1fdhYsJcoh3kc6mpwhTBfXDoyn8w==
|
||||||
|
|
||||||
postcss-import@^15.1.0:
|
postcss-import@^15.1.0:
|
||||||
version "15.1.0"
|
version "15.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70"
|
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70"
|
||||||
@ -2380,6 +2446,15 @@ react-is@^16.13.1:
|
|||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||||
|
|
||||||
|
react-query@^3.39.3:
|
||||||
|
version "3.39.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.39.3.tgz#4cea7127c6c26bdea2de5fb63e51044330b03f35"
|
||||||
|
integrity sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.5.5"
|
||||||
|
broadcast-channel "^3.4.1"
|
||||||
|
match-sorter "^6.0.2"
|
||||||
|
|
||||||
react-refresh@^0.14.0:
|
react-refresh@^0.14.0:
|
||||||
version "0.14.0"
|
version "0.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
|
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
|
||||||
@ -2466,6 +2541,11 @@ regenerator-runtime@^0.14.0:
|
|||||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
|
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
|
||||||
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
|
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
|
||||||
|
|
||||||
|
remove-accents@0.4.2:
|
||||||
|
version "0.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5"
|
||||||
|
integrity sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==
|
||||||
|
|
||||||
resolve-from@^4.0.0:
|
resolve-from@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||||
@ -2485,7 +2565,7 @@ reusify@^1.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||||
|
|
||||||
rimraf@^3.0.2:
|
rimraf@3.0.2, rimraf@^3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||||
@ -2764,6 +2844,14 @@ undici-types@~5.26.4:
|
|||||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||||
|
|
||||||
|
unload@2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7"
|
||||||
|
integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.6.2"
|
||||||
|
detect-node "^2.0.4"
|
||||||
|
|
||||||
update-browserslist-db@^1.0.13:
|
update-browserslist-db@^1.0.13:
|
||||||
version "1.0.13"
|
version "1.0.13"
|
||||||
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
|
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user