feat/generator: start working in the web page. Add data caching

This commit is contained in:
Kentai Radiquum 2025-02-20 20:15:56 +05:00
parent 1020dc8ae8
commit 383abce65d
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
7 changed files with 165 additions and 25 deletions

View file

@ -6,6 +6,7 @@ import { renderToString } from "react-dom/server";
import fs from "fs";
import exec from "child_process";
import Base from "./templates/Base";
import Header from "./templates/Header";
const log = new Log();
@ -40,8 +41,10 @@ interface Image {
date: number;
}
const tags: string[] = [];
const items: Image[] = [];
type Years = Record<string, Image[]>;
let tags: string[] = [];
let items: Years = {};
function addTag(tag: string) {
if (tags.includes(tag)) {
@ -50,6 +53,12 @@ function addTag(tag: string) {
tags.push(tag);
}
if (
!fs.existsSync("data") ||
!fs.existsSync("data/tags.json") ||
!fs.existsSync("data/items.json")
) {
log.warn("data/tags.json or data/items.json does not exist");
await db
.collection(process.env.FIREBASE_COLLECTION as string)
.get()
@ -59,7 +68,13 @@ await db
data.tags.forEach((tag: string) => {
addTag(tag);
});
items.push({
const year: string = new Date(data.date).getFullYear().toString();
if (!(year in items)) {
items[year] = [];
}
items[year].push({
id: doc.id,
alt: data.alt,
tags: data.tags,
@ -71,10 +86,18 @@ await db
});
});
});
if (!fs.existsSync("data")) fs.mkdirSync("data");
fs.writeFileSync("data/tags.json", JSON.stringify(tags));
fs.writeFileSync("data/items.json", JSON.stringify(items));
} else {
log.warn("using cached data");
tags = JSON.parse(fs.readFileSync("data/tags.json", "utf-8"));
items = JSON.parse(fs.readFileSync("data/items.json", "utf-8"));
}
const html = renderToString(
<Base isDev={ENVIRONMENT == "dev"}>
<p>Paragraph.</p>
<Header />
</Base>
);

1
generate/data/items.json Normal file
View file

@ -0,0 +1 @@
{"2021":[{"id":"IMG_20210324_205508.jpg","alt":"Sleeping kitten kat","tags":["cat","night","phone","weeee","tag"],"urls":[{"name":"example","value":"https://example.com"}],"mimetype":"image/jpeg","width":2160,"height":3840,"date":1612897200000}],"2025":[{"id":"83_7d3519266ea930d5.jpg","alt":"Protogens are in the park","tags":["protogen","tag"],"urls":[{"name":"example","value":"https://example.com"}],"mimetype":"image/jpeg","width":1632,"height":987,"date":1739818800000},{"id":"mohamed-elsayed-DWpR-BpKlw0-unsplash.jpg","alt":"Grumpy red panda in the snow","tags":["red_panda","testimage","snow","winter"],"urls":[],"mimetype":"image/jpeg","width":3386,"height":4233,"date":1739991600000}]}

1
generate/data/tags.json Normal file
View file

@ -0,0 +1 @@
["protogen","tag","cat","night","phone","weeee","red_panda","testimage","snow","winter"]

View file

@ -527,9 +527,33 @@
.static {
position: static;
}
.container {
width: 100%;
@media (width >= 40rem) {
max-width: 40rem;
}
@media (width >= 48rem) {
max-width: 48rem;
}
@media (width >= 64rem) {
max-width: 64rem;
}
@media (width >= 80rem) {
max-width: 80rem;
}
@media (width >= 96rem) {
max-width: 96rem;
}
}
.mx-auto {
margin-inline: auto;
}
.block {
display: block;
}
.flex {
display: flex;
}
.inline-flex {
display: inline-flex;
}
@ -539,6 +563,15 @@
.table {
display: table;
}
.h-16 {
height: calc(var(--spacing) * 16);
}
.w-16 {
width: calc(var(--spacing) * 16);
}
.w-full {
width: 100%;
}
.border-collapse {
border-collapse: collapse;
}
@ -548,10 +581,43 @@
.resize {
resize: both;
}
.items-center {
align-items: center;
}
.gap-4 {
gap: calc(var(--spacing) * 4);
}
.rounded-lg {
border-radius: var(--radius-lg);
}
.rounded-b-lg {
border-bottom-right-radius: var(--radius-lg);
border-bottom-left-radius: var(--radius-lg);
}
.border {
border-style: var(--tw-border-style);
border-width: 1px;
}
.bg-\[\#121B2C\] {
background-color: #121B2C;
}
.bg-\[\#FF478B\] {
background-color: #FF478B;
}
.p-4 {
padding: calc(var(--spacing) * 4);
}
.text-2xl {
font-size: var(--text-2xl);
line-height: var(--tw-leading, var(--text-2xl--line-height));
}
.font-bold {
--tw-font-weight: var(--font-weight-bold);
font-weight: var(--font-weight-bold);
}
.text-white {
color: var(--color-white);
}
.underline {
text-decoration-line: underline;
}
@ -559,6 +625,24 @@
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.xl\:text-3xl {
@media (width >= 80rem) {
font-size: var(--text-3xl);
line-height: var(--tw-leading, var(--text-3xl--line-height));
}
}
.\32 xl\:text-4xl {
@media (width >= 96rem) {
font-size: var(--text-4xl);
line-height: var(--tw-leading, var(--text-4xl--line-height));
}
}
}
.inter-semibold {
font-family: "Inter", serif;
font-optical-sizing: auto;
font-weight: 600;
font-style: normal;
}
@keyframes spin {
to {
@ -616,6 +700,10 @@
inherits: false;
initial-value: solid;
}
@property --tw-font-weight {
syntax: "*";
inherits: false;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;

View file

@ -1 +1,8 @@
@import "tailwindcss";
.inter-semibold {
font-family: "Inter", serif;
font-optical-sizing: auto;
font-weight: 600;
font-style: normal;
}

View file

@ -10,11 +10,21 @@ export default function Base({ children, isDev }: BaseProps) {
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Radiquum/Photos</title>
<link rel="stylesheet" href="/static/css/tailwind.css" />
{isDev ? <script src="/static/js/hotreload.js"></script> : ""}
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossOrigin="anonymous"
/>
<link
href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"
rel="stylesheet"
/>
</head>
<body>
{children}
</body>
<body className="bg-[#121B2C] text-white">{children}</body>
</html>
);
}

View file

@ -0,0 +1,10 @@
export default function Header() {
return (
<header className="bg-[#FF478B] text-white w-full rounded-b-lg">
<div className="flex items-center container mx-auto p-4 gap-4">
<img src="https://radiquum.wah.su/static/avatar_512.jpg" alt="" className="w-16 h-16 rounded-lg" />
<h1 className="text-2xl font-bold xl:text-3xl 2xl:text-4xl inter-semibold">RADIQUUM/PHOTOS</h1>
</div>
</header>
);
}