feat: middle save
This commit is contained in:
parent
d9280bdead
commit
a2f00ac83e
10 changed files with 303 additions and 84 deletions
3
bun.lock
3
bun.lock
|
@ -5,6 +5,7 @@
|
||||||
"name": "kuma-archive",
|
"name": "kuma-archive",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "^5.3.3",
|
"bootstrap": "^5.3.3",
|
||||||
|
"lucide-react": "^0.482.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router": "^7.3.0",
|
"react-router": "^7.3.0",
|
||||||
|
@ -359,6 +360,8 @@
|
||||||
|
|
||||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||||
|
|
||||||
|
"lucide-react": ["lucide-react@0.482.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-XM8PzHzSrg8ATmmO+fzf+JyYlVVdQnJjuyLDj2p4V2zEtcKeBNAqAoJIGFv1x2HSBa7kT8gpYUxwdQ0g7nypfw=="],
|
||||||
|
|
||||||
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||||
|
|
||||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||||
|
|
11
package.json
11
package.json
|
@ -4,17 +4,18 @@
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"build:view": "tsc -b && vite build",
|
||||||
"dev:server": "go run ./app.go daemon -d --api-only",
|
|
||||||
"dev:all": "bun run build && go run ./app.go daemon -d",
|
|
||||||
"build": "tsc -b && vite build",
|
|
||||||
"build:server": "go build -o kuma-archive",
|
"build:server": "go build -o kuma-archive",
|
||||||
"build:all": "bun run build && bun run build-server",
|
"build": "bun run build:view && bun run build:server",
|
||||||
|
"dev:view": "vite",
|
||||||
|
"dev:server": "go run ./app.go daemon -d --api-only",
|
||||||
|
"dev": "bun run build:view && go run ./app.go daemon -d",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "^5.3.3",
|
"bootstrap": "^5.3.3",
|
||||||
|
"lucide-react": "^0.482.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router": "^7.3.0",
|
"react-router": "^7.3.0",
|
||||||
|
|
1
public/assets/index-EHS3EQtg.css
Normal file
1
public/assets/index-EHS3EQtg.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
:root{font-family:system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;display:flex;place-items:center;min-width:320px;min-height:100vh}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}#root{max-width:1280px;margin:0 auto;padding:2rem;text-align:center}.logo{height:6em;padding:1.5em;will-change:filter;transition:filter .3s}.logo:hover{filter:drop-shadow(0 0 2em rgba(100,108,255,.6666666667))}.logo.react:hover{filter:drop-shadow(0 0 2em rgba(97,218,251,.6666666667))}@keyframes logo-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media (prefers-reduced-motion: no-preference){a:nth-of-type(2) .logo{animation:logo-spin infinite 20s linear}}.card{padding:2em}.read-the-docs{color:#888}
|
60
public/assets/index-T1mLj9f8.js
Normal file
60
public/assets/index-T1mLj9f8.js
Normal file
File diff suppressed because one or more lines are too long
13
public/index.html
Normal file
13
public/index.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Kuma Archive</title>
|
||||||
|
<script type="module" crossorigin src="/assets/index-T1mLj9f8.js"></script>
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/index-EHS3EQtg.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
28
src/App.scss
28
src/App.scss
|
@ -0,0 +1,28 @@
|
||||||
|
.ka-view {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ka-nav {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-content {
|
||||||
|
margin: 0 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
src/App.tsx
47
src/App.tsx
|
@ -1,7 +1,10 @@
|
||||||
import { BrowserRouter, Route, Routes } from "react-router";
|
import { BrowserRouter, Route, Routes, useLocation } from "react-router";
|
||||||
import Dashboard from "./components/dashboard";
|
import { usePath } from "./store/path";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import "./App.scss";
|
import "./App.scss";
|
||||||
|
import kuma from "./assets/kuma.png";
|
||||||
|
import { Menu } from "lucide-react";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
|
@ -13,4 +16,44 @@ function App() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Dashboard() {
|
||||||
|
const path = usePath();
|
||||||
|
const location = useLocation();
|
||||||
|
const [load, setLoad] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!load) {
|
||||||
|
path.update(location.pathname.substring(1, location.pathname.length));
|
||||||
|
setLoad(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = setInterval(() => {
|
||||||
|
path.update(location.pathname.substring(1, location.pathname.length));
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
return () => clearInterval(id);
|
||||||
|
}, [load, path, location]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="container-md ka-view">
|
||||||
|
<Header />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Header() {
|
||||||
|
return (
|
||||||
|
<nav className="ka-nav">
|
||||||
|
<div className="title">
|
||||||
|
<img src={kuma} alt="" />
|
||||||
|
<h4 className="title-content">Kuma Archive</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button>
|
||||||
|
<Menu />
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import Directory from "../directory";
|
|
||||||
import { usePath } from "../../store/path";
|
|
||||||
import { useLocation } from "react-router";
|
|
||||||
|
|
||||||
import "./dashboard.scss";
|
|
||||||
|
|
||||||
function Dashboard() {
|
|
||||||
const path = usePath();
|
|
||||||
const location = useLocation();
|
|
||||||
const [load, setLoad] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!load) {
|
|
||||||
path.update(location.pathname.substring(1, location.pathname.length));
|
|
||||||
setLoad(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const id = setInterval(() => {
|
|
||||||
path.update(location.pathname.substring(1, location.pathname.length));
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
return () => clearInterval(id);
|
|
||||||
}, [load, path, location]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Directory />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Dashboard;
|
|
187
src/index.scss
187
src/index.scss
|
@ -1,11 +1,50 @@
|
||||||
|
@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css");
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
--background: #242424;
|
||||||
|
--foreground: rgba(255, 255, 255, 0.87);
|
||||||
|
--sidebar-color: #2a2a2a;
|
||||||
|
|
||||||
|
--stroke: #3c3c3c;
|
||||||
|
--nav-color: #191919;
|
||||||
|
--nav-hover: #101010;
|
||||||
|
--profile-color: #3a3a3a;
|
||||||
|
|
||||||
|
--hover: rgba(255, 255, 255, 0.7);
|
||||||
|
--focus: rgba(255, 255, 255, 0.55);
|
||||||
|
|
||||||
|
--form-color: #151515;
|
||||||
|
|
||||||
|
--btn-primary: #0069d9;
|
||||||
|
--btn-secondary: #859099;
|
||||||
|
--btn-success: #28a745;
|
||||||
|
--btn-danger: #dc3545;
|
||||||
|
|
||||||
|
--btn-primary-hover: #0254ac;
|
||||||
|
--btn-secondary-hover: #596066;
|
||||||
|
--btn-success-hover: #208a39;
|
||||||
|
--btn-danger-hover: #b32735;
|
||||||
|
|
||||||
|
--btn-primary-focus: #034fa0;
|
||||||
|
--btn-secondary-focus: #50565c;
|
||||||
|
--btn-success-focus: #1d7c33;
|
||||||
|
--btn-danger-focus: #a72532;
|
||||||
|
|
||||||
|
--font-family: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
font-size: 11pt;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
color-scheme: light dark;
|
color-scheme: light dark;
|
||||||
color: rgba(255, 255, 255, 0.87);
|
color: var(--foreground);
|
||||||
background-color: #242424;
|
background-color: var(--background);
|
||||||
|
|
||||||
font-synthesis: none;
|
font-synthesis: none;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
|
@ -13,57 +52,119 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
* {
|
||||||
font-weight: 500;
|
|
||||||
color: #646cff;
|
|
||||||
text-decoration: inherit;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #535bf2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
padding: 0;
|
||||||
place-items: center;
|
box-sizing: border-box;
|
||||||
min-width: 320px;
|
|
||||||
min-height: 100vh;
|
font-family: var(--font-family);
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 3.2em;
|
font-size: 32pt;
|
||||||
line-height: 1.1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
h2 {
|
||||||
border-radius: 8px;
|
font-size: 24pt;
|
||||||
border: 1px solid transparent;
|
}
|
||||||
padding: 0.6em 1.2em;
|
|
||||||
font-size: 1em;
|
h3 {
|
||||||
font-weight: 500;
|
font-size: 18pt;
|
||||||
font-family: inherit;
|
}
|
||||||
background-color: #1a1a1a;
|
|
||||||
|
h4 {
|
||||||
|
font-size: 16pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 15pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size: 12pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: border-color 0.25s;
|
user-select: none;
|
||||||
}
|
text-decoration: none;
|
||||||
button:hover {
|
transition-duration: 0.3s;
|
||||||
border-color: #646cff;
|
color: var(--foreground);
|
||||||
}
|
|
||||||
button:focus,
|
&:hover {
|
||||||
button:focus-visible {
|
color: var(--hover);
|
||||||
outline: 4px auto -webkit-focus-ring-color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
&:focus {
|
||||||
:root {
|
color: var(--focus);
|
||||||
color: #213547;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
}
|
||||||
a:hover {
|
|
||||||
color: #747bff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
background-color: var(--background);
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
background-color: #f9f9f9;
|
cursor: pointer;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition-duration: 0.3s;
|
||||||
|
background-color: var(--background);
|
||||||
|
|
||||||
|
&.primary {
|
||||||
|
background-color: var(--btn-primary);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--btn-primary-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
background-color: var(--btn-primary-focus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.secondary {
|
||||||
|
background-color: var(--btn-secondary);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--btn-secondary-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
background-color: var(--btn-secondary-focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
background-color: var(--btn-success);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--btn-success-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
background-color: var(--btn-success-focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
background-color: var(--btn-danger);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--btn-danger-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
background-color: var(--btn-danger-focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input, button {
|
||||||
|
height: 40px;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
font-size: 12pt;
|
||||||
|
border-radius: 25px;
|
||||||
|
padding: 0.25rem 15px;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue