chore: first build
5
.dockerignore
Normal file
@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
.git
|
||||
.gitignore
|
||||
*.md
|
||||
dist
|
1
.gitignore
vendored
@ -25,3 +25,4 @@ dist-ssr
|
||||
|
||||
.env*
|
||||
!.env.example
|
||||
docker-compose.*.yml
|
||||
|
34
Dockerfile
Normal file
@ -0,0 +1,34 @@
|
||||
FROM node:20-slim AS base
|
||||
WORKDIR /app
|
||||
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
RUN corepack enable
|
||||
|
||||
FROM base AS frontend
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
|
||||
|
||||
COPY . .
|
||||
RUN pnpm run build
|
||||
|
||||
FROM base AS backend-deps
|
||||
COPY backend/package.json backend/pnpm-lock.yaml ./
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install -prod --frozen-lockfile
|
||||
COPY backend .
|
||||
|
||||
FROM oven/bun:alpine AS backend
|
||||
WORKDIR /app
|
||||
COPY --from=backend-deps /app .
|
||||
RUN bun run build
|
||||
|
||||
FROM oven/bun:alpine
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV=production
|
||||
ENV DIST_ROOT=./dist
|
||||
|
||||
COPY --from=frontend /app/dist /app/dist
|
||||
COPY --from=backend /app/dist /app
|
||||
|
||||
ENTRYPOINT [ "bun" , "run", "main.js" ]
|
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Khairul Hidayat
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
148
README.md
@ -1,50 +1,122 @@
|
||||
# React + TypeScript + Vite
|
||||
# Garage Web UI
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
[](misc/img/garage-webui.png)
|
||||
|
||||
Currently, two official plugins are available:
|
||||
A simple admin web UI for [Garage](https://garagehq.deuxfleurs.fr/), a self-hosted, S3-compatible, distributed object storage service.
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
[ [Screenshots](misc/SCREENSHOTS.md) | [Install Garage](https://garagehq.deuxfleurs.fr/documentation/quick-start/) | [Garage Git](https://git.deuxfleurs.fr/Deuxfleurs/garage) ]
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
## Installation
|
||||
|
||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||
The Garage Web UI is available as a Docker image. You can install it using the command line or with Docker Compose.
|
||||
|
||||
- Configure the top-level `parserOptions` property like this:
|
||||
### Docker CLI
|
||||
|
||||
```js
|
||||
export default tseslint.config({
|
||||
languageOptions: {
|
||||
// other options...
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
})
|
||||
```sh
|
||||
$ docker run -p 3909:3909 -v ./garage.toml:/etc/garage.toml --restart unless-stopped --name garage-webui khairul169/garage-webui:latest
|
||||
```
|
||||
|
||||
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
|
||||
- Optionally add `...tseslint.configs.stylisticTypeChecked`
|
||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
|
||||
### Docker Compose
|
||||
|
||||
```js
|
||||
// eslint.config.js
|
||||
import react from 'eslint-plugin-react'
|
||||
If you install Garage using Docker, you can install this web UI alongside Garage as follows:
|
||||
|
||||
export default tseslint.config({
|
||||
// Set the react version
|
||||
settings: { react: { version: '18.3' } },
|
||||
plugins: {
|
||||
// Add the react plugin
|
||||
react,
|
||||
},
|
||||
rules: {
|
||||
// other rules...
|
||||
// Enable its recommended rules
|
||||
...react.configs.recommended.rules,
|
||||
...react.configs['jsx-runtime'].rules,
|
||||
},
|
||||
})
|
||||
```yml
|
||||
services:
|
||||
garage:
|
||||
image: dxflrs/garage:v1.0.0
|
||||
container_name: garage
|
||||
volumes:
|
||||
- ./garage.toml:/etc/garage.toml
|
||||
- ./meta:/var/lib/garage/meta
|
||||
- ./data:/var/lib/garage/data
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
|
||||
webui:
|
||||
image: khairul169/garage-webui:latest
|
||||
container_name: garage-webui
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./garage.toml:/etc/garage.toml
|
||||
ports:
|
||||
- 3909:3909
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
To simplify installation, the Garage Web UI uses values from the Garage configuration, such as `rpc_public_addr`, `admin.admin_token`, `s3_web.root_domain`, etc.
|
||||
|
||||
Example content of `config.toml`:
|
||||
|
||||
```toml
|
||||
metadata_dir = "/var/lib/garage/meta"
|
||||
data_dir = "/var/lib/garage/data"
|
||||
db_engine = "sqlite"
|
||||
metadata_auto_snapshot_interval = "6h"
|
||||
|
||||
replication_factor = 3
|
||||
compression_level = 2
|
||||
|
||||
rpc_bind_addr = "[::]:3901"
|
||||
rpc_public_addr = "localhost:3901" # Required
|
||||
rpc_secret = "YOUR_RPC_SECRET_HERE"
|
||||
|
||||
[s3_api]
|
||||
s3_region = "garage"
|
||||
api_bind_addr = "[::]:3900"
|
||||
root_domain = ".s3.domain.com"
|
||||
|
||||
[s3_web] # Optional, if you want to expose bucket as web
|
||||
bind_addr = "[::]:3902"
|
||||
root_domain = ".web.domain.com"
|
||||
index = "index.html"
|
||||
|
||||
[admin] # Required
|
||||
api_bind_addr = "[::]:3903"
|
||||
admin_token = "YOUR_ADMIN_TOKEN_HERE"
|
||||
metrics_token = "YOUR_METRICS_TOKEN_HERE"
|
||||
```
|
||||
|
||||
However, if it fails to load, you can set these environment variables instead:
|
||||
|
||||
- `CONFIG_PATH`: Path to the Garage `config.toml` file. Defaults to `/etc/garage.toml`.
|
||||
- `API_BASE_URL`: Garage admin API endpoint URL.
|
||||
- `API_ADMIN_KEY`: Admin API key.
|
||||
|
||||
### Running
|
||||
|
||||
Once your instance of Garage Web UI is started, you can open the web UI at http://your-ip:3909. You can place it behind a reverse proxy to secure it with SSL.
|
||||
|
||||
## Development
|
||||
|
||||
This project is bootstrapped using TypeScript, Bun, React, and Hono. If you want to build it yourself or add additional features, follow these steps:
|
||||
|
||||
### Setup
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/khairul169/garage-webui.git
|
||||
$ cd garage-webui && pnpm install
|
||||
$ cd backend && pnpm install && cd ..
|
||||
```
|
||||
|
||||
### Running
|
||||
|
||||
Start both the client and server concurrently:
|
||||
|
||||
```sh
|
||||
$ pnpm run dev # or npm run dev
|
||||
```
|
||||
|
||||
Or start each instance separately:
|
||||
|
||||
```sh
|
||||
$ pnpm run dev:client
|
||||
$ cd backend
|
||||
$ pnpm run dev:server
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Make sure you are using the latest version of Garage. If the data cannot be loaded, please check whether your instance of Garage has the admin API enabled and the ports are accessible.
|
||||
|
||||
If you encounter any problems, please do not hesitate to submit an issue [here](https://github.com/khairul169/garage-webui/issues). You can describe the problem and attach the error logs.
|
||||
|
2
backend/lib/consts.ts
Normal file
@ -0,0 +1,2 @@
|
||||
//
|
||||
export const __PROD = import.meta.env.NODE_ENV === "production";
|
@ -1,4 +1,16 @@
|
||||
import type { Config } from "../types/garage";
|
||||
import { readTomlFile } from "./utils";
|
||||
|
||||
export const config = readTomlFile<Config>(process.env.CONFIG_PATH);
|
||||
const CONFIG_PATH = process.env.CONFIG_PATH || "/etc/garage.toml";
|
||||
|
||||
export const config = await readTomlFile<Config>(CONFIG_PATH);
|
||||
|
||||
if (!config?.rpc_public_addr) {
|
||||
throw new Error(
|
||||
"Cannot load garage config! Missing `rpc_public_addr` in config file."
|
||||
);
|
||||
}
|
||||
|
||||
if (!config?.admin?.admin_token) {
|
||||
throw new Error("Missing `admin.admin_token` in config.");
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ import { API_ADMIN_KEY, API_BASE_URL } from "./api";
|
||||
|
||||
export const proxyApi = async (c: Context) => {
|
||||
const url = new URL(c.req.url);
|
||||
const reqUrl = new URL(API_BASE_URL + url.pathname + url.search);
|
||||
const pathname = url.pathname.replace(/\/api\//, "/");
|
||||
const reqUrl = new URL(API_BASE_URL + pathname + url.search);
|
||||
|
||||
try {
|
||||
const headers = c.req.raw.headers;
|
||||
|
@ -1,9 +1,14 @@
|
||||
import fs from "node:fs";
|
||||
import toml from "toml";
|
||||
|
||||
export const readTomlFile = <T = any>(path?: string | null) => {
|
||||
if (!path || !fs.existsSync(path)) {
|
||||
export const readTomlFile = async <T = any>(path?: string | null) => {
|
||||
if (!path) {
|
||||
return undefined;
|
||||
}
|
||||
return toml.parse(fs.readFileSync(path, "utf8")) as T;
|
||||
|
||||
const file = Bun.file(path);
|
||||
if (!(await file.exists())) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return toml.parse(await file.text()) as T;
|
||||
};
|
||||
|
@ -1,20 +1,34 @@
|
||||
import { Hono } from "hono";
|
||||
import { logger } from "hono/logger";
|
||||
import { serveStatic } from "hono/bun";
|
||||
import router from "./routes";
|
||||
import { proxyApi } from "./lib/proxy-api";
|
||||
import { __PROD } from "./lib/consts";
|
||||
|
||||
const HOST = import.meta.env.HOST || "0.0.0.0";
|
||||
const PORT = Number(import.meta.env.PORT) || 3909;
|
||||
const DIST_ROOT = import.meta.env.DIST_ROOT || "./dist";
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
app.use(logger());
|
||||
|
||||
// API router
|
||||
app.route("/", router);
|
||||
app.route("/api", router);
|
||||
|
||||
// Proxy to garage admin API
|
||||
app.all("*", proxyApi);
|
||||
if (__PROD) {
|
||||
// Serve client dist
|
||||
app.use(serveStatic({ root: DIST_ROOT }));
|
||||
app.use(async (c, next) => {
|
||||
try {
|
||||
const file = Bun.file(DIST_ROOT + "/index.html");
|
||||
return c.html(await file.text());
|
||||
} catch (err) {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Listening on http://${HOST}:${PORT}`);
|
||||
}
|
||||
|
||||
export default {
|
||||
fetch: app.fetch,
|
||||
|
@ -3,7 +3,9 @@
|
||||
"module": "main.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "bun --watch main.ts"
|
||||
"dev": "bun --watch main.ts",
|
||||
"build": "bun build main.ts --minify --sourcemap --outdir ./dist",
|
||||
"start": "NODE_ENV=production bun run ./dist/main.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
|
10
backend/pnpm-lock.yaml
generated
@ -14,6 +14,9 @@ importers:
|
||||
toml:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
typescript:
|
||||
specifier: ^5.0.0
|
||||
version: 5.5.4
|
||||
devDependencies:
|
||||
'@types/bun':
|
||||
specifier: latest
|
||||
@ -40,6 +43,11 @@ packages:
|
||||
toml@3.0.0:
|
||||
resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==}
|
||||
|
||||
typescript@5.5.4:
|
||||
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
undici-types@5.26.5:
|
||||
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
|
||||
|
||||
@ -66,4 +74,6 @@ snapshots:
|
||||
|
||||
toml@3.0.0: {}
|
||||
|
||||
typescript@5.5.4: {}
|
||||
|
||||
undici-types@5.26.5: {}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import { Hono } from "hono";
|
||||
import { buckets } from "./buckets";
|
||||
import { configRoute } from "./config";
|
||||
import { proxyApi } from "../lib/proxy-api";
|
||||
|
||||
const router = new Hono()
|
||||
//
|
||||
.route("/config", configRoute)
|
||||
.route("/buckets", buckets);
|
||||
.route("/buckets", buckets)
|
||||
|
||||
.all("*", proxyApi);
|
||||
|
||||
export default router;
|
||||
|
21
docker-compose.yml
Normal file
@ -0,0 +1,21 @@
|
||||
services:
|
||||
garage:
|
||||
image: dxflrs/garage:v1.0.0
|
||||
container_name: garage
|
||||
volumes:
|
||||
- ./garage.toml:/etc/garage.toml
|
||||
- ./meta:/var/lib/garage/meta
|
||||
- ./data:/var/lib/garage/data
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
|
||||
webui:
|
||||
image: khairul169/garage-webui:latest
|
||||
container_name: garage-webui
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- CONFIG_PATH=/etc/garage.toml
|
||||
volumes:
|
||||
- ./garage.toml:/etc/garage.toml
|
||||
ports:
|
||||
- 3909:3909
|
11
index.html
@ -1,10 +1,15 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="pastel">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
|
||||
<title>Garage Web UI</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
8
misc/SCREENSHOTS.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Garage Web UI Screenshots
|
||||
|
||||
[](img/home.png)
|
||||
[](img/cluster.png)
|
||||
[](img/buckets.png)
|
||||
[](img/buckets-overview.png)
|
||||
[](img/buckets-permissions.png)
|
||||
[](img/keys.png)
|
11
misc/build.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
IMAGE_NAME="khairul169/garage-webui"
|
||||
PACKAGE_VERSION=$(cat package.json | grep \"version\" | cut -d'"' -f 4)
|
||||
|
||||
echo "Building version $PACKAGE_VERSION"
|
||||
|
||||
docker buildx build --platform linux/amd64,linux/arm64 \
|
||||
-t "$IMAGE_NAME:latest" -t "$IMAGE_NAME:$PACKAGE_VERSION" --push .
|
BIN
misc/img/buckets-overview.png
Executable file
After Width: | Height: | Size: 52 KiB |
BIN
misc/img/buckets-permissions.png
Executable file
After Width: | Height: | Size: 39 KiB |
BIN
misc/img/buckets.png
Executable file
After Width: | Height: | Size: 44 KiB |
BIN
misc/img/cluster.png
Executable file
After Width: | Height: | Size: 86 KiB |
BIN
misc/img/garage-webui.png
Executable file
After Width: | Height: | Size: 208 KiB |
BIN
misc/img/home.png
Executable file
After Width: | Height: | Size: 49 KiB |
BIN
misc/img/keys.png
Executable file
After Width: | Height: | Size: 39 KiB |
@ -1,13 +1,15 @@
|
||||
{
|
||||
"name": "garage-webui",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"dev:client": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"dev:server": "cd backend && npm run dev",
|
||||
"dev": "concurrently \"npm run dev:client\" \"npm run dev:server\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.9.0",
|
||||
@ -32,6 +34,7 @@
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"concurrently": "^8.2.2",
|
||||
"daisyui": "^4.12.10",
|
||||
"eslint": "^9.8.0",
|
||||
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
||||
|
117
pnpm-lock.yaml
generated
@ -69,6 +69,9 @@ importers:
|
||||
autoprefixer:
|
||||
specifier: ^10.4.20
|
||||
version: 10.4.20(postcss@8.4.41)
|
||||
concurrently:
|
||||
specifier: ^8.2.2
|
||||
version: 8.2.2
|
||||
daisyui:
|
||||
specifier: ^4.12.10
|
||||
version: 4.12.10(postcss@8.4.41)
|
||||
@ -772,6 +775,10 @@ packages:
|
||||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
||||
cliui@8.0.1:
|
||||
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
clsx@2.1.1:
|
||||
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
||||
engines: {node: '>=6'}
|
||||
@ -796,6 +803,11 @@ packages:
|
||||
concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
concurrently@8.2.2:
|
||||
resolution: {integrity: sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==}
|
||||
engines: {node: ^14.13.0 || >=16.0.0}
|
||||
hasBin: true
|
||||
|
||||
convert-source-map@1.9.0:
|
||||
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
|
||||
|
||||
@ -826,6 +838,10 @@ packages:
|
||||
resolution: {integrity: sha512-jp1RAuzbHhGdXmn957Z2XsTZStXGHzFfF0FgIOZj3Wv9sH7OZgLfXTRZNfKVYxltGUOBsG1kbWAdF5SrqjebvA==}
|
||||
engines: {node: '>=16.9.0'}
|
||||
|
||||
date-fns@2.30.0:
|
||||
resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
|
||||
engines: {node: '>=0.11'}
|
||||
|
||||
debug@4.3.6:
|
||||
resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
|
||||
engines: {node: '>=6.0'}
|
||||
@ -992,6 +1008,10 @@ packages:
|
||||
function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
get-caller-file@2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
|
||||
glob-parent@5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
@ -1140,6 +1160,9 @@ packages:
|
||||
lodash.merge@4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
|
||||
lodash@4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||
hasBin: true
|
||||
@ -1380,6 +1403,10 @@ packages:
|
||||
regenerator-runtime@0.14.1:
|
||||
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
|
||||
|
||||
require-directory@2.1.1:
|
||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
resolve-from@4.0.0:
|
||||
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
||||
engines: {node: '>=4'}
|
||||
@ -1400,6 +1427,9 @@ packages:
|
||||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
rxjs@7.8.1:
|
||||
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
|
||||
|
||||
scheduler@0.23.2:
|
||||
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
|
||||
|
||||
@ -1416,6 +1446,9 @@ packages:
|
||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
shell-quote@1.8.1:
|
||||
resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
|
||||
|
||||
signal-exit@4.1.0:
|
||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||
engines: {node: '>=14'}
|
||||
@ -1438,6 +1471,9 @@ packages:
|
||||
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
spawn-command@0.0.2:
|
||||
resolution: {integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
@ -1474,6 +1510,10 @@ packages:
|
||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
supports-color@8.1.1:
|
||||
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
supports-preserve-symlinks-flag@1.0.0:
|
||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -1504,6 +1544,10 @@ packages:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
||||
tree-kill@1.2.2:
|
||||
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
||||
hasBin: true
|
||||
|
||||
ts-api-utils@1.3.0:
|
||||
resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
|
||||
engines: {node: '>=16'}
|
||||
@ -1513,6 +1557,9 @@ packages:
|
||||
ts-interface-checker@0.1.13:
|
||||
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
||||
|
||||
tslib@2.6.3:
|
||||
resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
|
||||
|
||||
type-check@0.4.0:
|
||||
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@ -1608,6 +1655,10 @@ packages:
|
||||
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
yaml@1.10.2:
|
||||
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
|
||||
engines: {node: '>= 6'}
|
||||
@ -1617,6 +1668,14 @@ packages:
|
||||
engines: {node: '>= 14'}
|
||||
hasBin: true
|
||||
|
||||
yargs-parser@21.1.1:
|
||||
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
yargs@17.7.2:
|
||||
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
yocto-queue@0.1.0:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
@ -2260,6 +2319,12 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
cliui@8.0.1:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 7.0.0
|
||||
|
||||
clsx@2.1.1: {}
|
||||
|
||||
color-convert@1.9.3:
|
||||
@ -2278,6 +2343,18 @@ snapshots:
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
||||
concurrently@8.2.2:
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
date-fns: 2.30.0
|
||||
lodash: 4.17.21
|
||||
rxjs: 7.8.1
|
||||
shell-quote: 1.8.1
|
||||
spawn-command: 0.0.2
|
||||
supports-color: 8.1.1
|
||||
tree-kill: 1.2.2
|
||||
yargs: 17.7.2
|
||||
|
||||
convert-source-map@1.9.0: {}
|
||||
|
||||
cosmiconfig@7.1.0:
|
||||
@ -2314,6 +2391,10 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- postcss
|
||||
|
||||
date-fns@2.30.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.25.0
|
||||
|
||||
debug@4.3.6:
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
@ -2507,6 +2588,8 @@ snapshots:
|
||||
|
||||
function-bind@1.1.2: {}
|
||||
|
||||
get-caller-file@2.0.5: {}
|
||||
|
||||
glob-parent@5.1.2:
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
@ -2631,6 +2714,8 @@ snapshots:
|
||||
|
||||
lodash.merge@4.6.2: {}
|
||||
|
||||
lodash@4.17.21: {}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
dependencies:
|
||||
js-tokens: 4.0.0
|
||||
@ -2853,6 +2938,8 @@ snapshots:
|
||||
|
||||
regenerator-runtime@0.14.1: {}
|
||||
|
||||
require-directory@2.1.1: {}
|
||||
|
||||
resolve-from@4.0.0: {}
|
||||
|
||||
resolve@1.22.8:
|
||||
@ -2889,6 +2976,10 @@ snapshots:
|
||||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
|
||||
rxjs@7.8.1:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
|
||||
scheduler@0.23.2:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
@ -2901,6 +2992,8 @@ snapshots:
|
||||
|
||||
shebang-regex@3.0.0: {}
|
||||
|
||||
shell-quote@1.8.1: {}
|
||||
|
||||
signal-exit@4.1.0: {}
|
||||
|
||||
slash@3.0.0: {}
|
||||
@ -2914,6 +3007,8 @@ snapshots:
|
||||
|
||||
source-map@0.5.7: {}
|
||||
|
||||
spawn-command@0.0.2: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
@ -2956,6 +3051,10 @@ snapshots:
|
||||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
|
||||
supports-color@8.1.1:
|
||||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
|
||||
supports-preserve-symlinks-flag@1.0.0: {}
|
||||
|
||||
tailwind-merge@2.5.2: {}
|
||||
@ -3003,12 +3102,16 @@ snapshots:
|
||||
dependencies:
|
||||
is-number: 7.0.0
|
||||
|
||||
tree-kill@1.2.2: {}
|
||||
|
||||
ts-api-utils@1.3.0(typescript@5.5.4):
|
||||
dependencies:
|
||||
typescript: 5.5.4
|
||||
|
||||
ts-interface-checker@0.1.13: {}
|
||||
|
||||
tslib@2.6.3: {}
|
||||
|
||||
type-check@0.4.0:
|
||||
dependencies:
|
||||
prelude-ls: 1.2.1
|
||||
@ -3077,10 +3180,24 @@ snapshots:
|
||||
string-width: 5.1.2
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
||||
yaml@1.10.2: {}
|
||||
|
||||
yaml@2.5.0: {}
|
||||
|
||||
yargs-parser@21.1.1: {}
|
||||
|
||||
yargs@17.7.2:
|
||||
dependencies:
|
||||
cliui: 8.0.1
|
||||
escalade: 3.1.2
|
||||
get-caller-file: 2.0.5
|
||||
require-directory: 2.1.1
|
||||
string-width: 4.2.3
|
||||
y18n: 5.0.8
|
||||
yargs-parser: 21.1.1
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
zod@3.23.8: {}
|
||||
|
BIN
public/android-chrome-192x192.png
Executable file
After Width: | Height: | Size: 16 KiB |
BIN
public/android-chrome-512x512.png
Executable file
After Width: | Height: | Size: 63 KiB |
BIN
public/apple-touch-icon.png
Executable file
After Width: | Height: | Size: 14 KiB |
BIN
public/favicon-16x16.png
Executable file
After Width: | Height: | Size: 735 B |
BIN
public/favicon-32x32.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
public/favicon.ico
Executable file
After Width: | Height: | Size: 15 KiB |
1
public/site.webmanifest
Executable file
@ -0,0 +1 @@
|
||||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
Before Width: | Height: | Size: 1.5 KiB |
131
src/assets/garage-logo.svg
Executable file
@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="30mm"
|
||||
height="30mm"
|
||||
viewBox="0 0 30 30"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="garage-logo.svg"
|
||||
inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="5.0701029"
|
||||
inkscape:cx="75.738107"
|
||||
inkscape:cy="78.20354"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg5" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<path
|
||||
id="path6"
|
||||
d="m 18.252345,9.0579502 c -0.218792,0.024311 -0.461894,0 -0.680691,-0.072931 L 9.1116177,6.6998396 C 8.8928239,6.6269083 8.6740302,6.5296667 8.4795464,6.4081145 Z"
|
||||
style="stroke-width:0.243104" />
|
||||
<path
|
||||
id="path26"
|
||||
class="st3"
|
||||
d="m 18.422521,12.558652 4.643297,-1.871904 c 0.09724,-0.04862 0.145863,-0.145862 0.121552,-0.267414 -0.02432,-0.04862 -0.04862,-0.09724 -0.121552,-0.121554 -0.534828,-0.218791 -1.215524,-0.4862076 -1.871903,-0.7536217 -0.121557,-0.04862 -1.264147,0.7779337 -1.361387,0.8508647 l -1.993457,1.604487 c -0.4619,0.437588 -0.04862,0.826556 0.58345,0.559142 z"
|
||||
style="stroke-width:0.243104" />
|
||||
<ellipse
|
||||
id="circle28"
|
||||
class="st3"
|
||||
cx="15.067682"
|
||||
cy="14.381929"
|
||||
rx="2.4310451"
|
||||
ry="2.4310422"
|
||||
style="stroke-width:0.243104" />
|
||||
<path
|
||||
id="path6-0"
|
||||
d="m 18.252345,9.0579502 c -0.218792,0.024311 -0.461894,0 -0.680691,-0.072931 L 9.1116177,6.6998396 C 8.8928239,6.6269083 8.6740302,6.5296667 8.4795464,6.4081145 Z"
|
||||
style="stroke-width:0.243104" />
|
||||
<g
|
||||
id="g1"
|
||||
style="stroke:#ffffff;stroke-opacity:1;stroke-linejoin:round;stroke-linecap:butt;paint-order:markers stroke fill;stroke-width:0.8;stroke-dasharray:none">
|
||||
<path
|
||||
id="path8"
|
||||
class="st0"
|
||||
d="m 5.3921192,23.425409 c 0.4836869,0.0057 0.9683846,-0.0121 1.4513623,0.01026 0.2797376,0.01631 0.5246598,0.244204 0.5357045,0.528822 0.014525,0.715514 0.00242,1.431989 0.00639,2.147882 0.00975,0.18178 -0.2937553,0.13971 -0.4176027,0.217322 C 6.2505828,26.527076 5.4892337,26.60307 4.7516897,26.487383 4.1256342,26.381378 3.5905644,25.93667 3.3273915,25.364822 2.9915288,24.650787 2.9376085,23.833058 3.020282,23.057781 c 0.07389,-0.647851 0.3650579,-1.282203 0.8753663,-1.70056 0.5504884,-0.483741 1.319811,-0.660967 2.0361625,-0.553729 0.5196872,0.06538 1.0240239,0.255395 1.4537643,0.555533 -0.049017,0.302734 -0.2236719,0.59045 -0.4862094,0.753622 -0.4701824,-0.345013 -1.0720551,-0.534813 -1.6553823,-0.471769 -0.5097053,0.0798 -0.9483078,0.472324 -1.0796061,0.972454 -0.1679185,0.593908 -0.1684748,1.229968 -0.063593,1.835175 0.08495,0.484701 0.3735586,0.980534 0.8684921,1.132012 0.468823,0.153492 0.9695032,0.05737 1.4438802,-0.0158 0.00585,-0.413445 -0.014399,-0.828053 0.016284,-1.240543 0.011286,-0.09692 -0.1751,-0.02652 -0.2530503,-0.04791 -0.2543952,-0.01394 -0.533292,0.04887 -0.7599644,-0.09724 -0.2168052,-0.202613 -0.082489,-0.513657 -0.024311,-0.753622 z"
|
||||
style="stroke-width:0.8;stroke:#ffffff;stroke-opacity:1;stroke-linejoin:round;stroke-linecap:butt;paint-order:markers stroke fill;stroke-dasharray:none" />
|
||||
<path
|
||||
id="path10"
|
||||
class="st0"
|
||||
d="m 11.639907,25.953692 c -0.02432,0.09724 -0.07293,0.194483 -0.145865,0.291725 -0.04862,0.09724 -0.121552,0.170174 -0.194481,0.218794 -0.316036,-0.02432 -0.583453,-0.194482 -0.753627,-0.486208 -0.291725,0.316034 -0.7293107,0.51052 -1.1668987,0.51052 -0.4132803,0 -0.7293157,-0.121554 -0.9481099,-0.364657 -0.1944835,-0.243105 -0.3160359,-0.534831 -0.3160359,-0.850865 0,-0.461899 0.1458627,-0.802245 0.4375883,-1.021039 0.3403461,-0.243102 0.7293149,-0.364656 1.1425891,-0.340345 0.2431078,0 0.4862111,0 0.7050071,0.02432 v -0.243105 c 0,-0.437588 -0.194485,-0.632071 -0.6077645,-0.632071 -0.2917228,0 -0.7050023,0.09724 -1.2398317,0.291726 -0.1701732,-0.194483 -0.2674151,-0.4619 -0.2674151,-0.729314 0.5591402,-0.243103 1.1425926,-0.364656 1.7503523,-0.364656 0.364659,-0.02432 0.705004,0.09724 0.99673,0.340347 0.243105,0.218794 0.388965,0.55914 0.388965,1.021037 v 1.653109 c -0.02432,0.364657 0.04862,0.55914 0.218797,0.680691 z M 9.5978268,25.759209 c 0.3160366,-0.02432 0.6077622,-0.145862 0.8022472,-0.388968 v -0.705002 c -0.194485,-0.02432 -0.4132792,-0.02432 -0.6077645,-0.02432 -0.1944827,-0.02432 -0.3646542,0.04862 -0.5105168,0.170171 -0.1215542,0.121554 -0.170175,0.267417 -0.170175,0.437588 0,0.145863 0.048621,0.291726 0.1458637,0.413277 0.097243,0.04862 0.218794,0.09724 0.3403454,0.09724 z"
|
||||
style="stroke-width:0.8;stroke:#ffffff;stroke-opacity:1;stroke-linejoin:round;stroke-linecap:butt;paint-order:markers stroke fill;stroke-dasharray:none" />
|
||||
<path
|
||||
id="path12"
|
||||
class="st0"
|
||||
d="m 12.296286,22.866269 c 0.02432,-0.09724 0.07293,-0.194482 0.145863,-0.291725 0.04862,-0.09724 0.121554,-0.170174 0.194483,-0.218794 0.413276,0.04862 0.729313,0.340345 0.850867,0.729313 0.218794,-0.486208 0.559139,-0.729313 1.04535,-0.729313 0.145863,0 0.316032,0.02432 0.461897,0.04862 0,0.340348 -0.07293,0.656382 -0.243103,0.948108 -0.121554,-0.02432 -0.243105,-0.04862 -0.364657,-0.04862 -0.340348,0 -0.58345,0.170172 -0.802247,0.534829 v 2.576905 c -0.170171,0.02432 -0.340345,0.04862 -0.48621,0.04862 -0.170169,0 -0.340343,-0.02432 -0.510517,-0.04862 v -2.722768 c 0,-0.388966 -0.09724,-0.656382 -0.291726,-0.826554 z"
|
||||
style="stroke-width:0.8;stroke:#ffffff;stroke-opacity:1;stroke-linejoin:round;stroke-linecap:butt;paint-order:markers stroke fill;stroke-dasharray:none" />
|
||||
<path
|
||||
id="path14"
|
||||
class="st0"
|
||||
d="m 18.762867,25.953692 c -0.02432,0.09724 -0.07293,0.194483 -0.145863,0.291725 -0.04862,0.09724 -0.121551,0.170174 -0.194483,0.218794 -0.316036,-0.02432 -0.58345,-0.194482 -0.753627,-0.486208 -0.291723,0.316034 -0.729311,0.51052 -1.166901,0.51052 -0.413275,0 -0.729314,-0.121554 -0.948105,-0.364657 -0.194485,-0.243105 -0.316037,-0.534831 -0.316037,-0.850865 0,-0.461899 0.145863,-0.802245 0.437588,-1.021039 0.316034,-0.243102 0.729314,-0.364656 1.118282,-0.340345 0.243102,0 0.48621,0 0.705002,0.02432 v -0.243105 c 0,-0.437588 -0.194481,-0.632071 -0.607762,-0.632071 -0.291726,0 -0.705002,0.09724 -1.239833,0.291726 -0.170174,-0.194483 -0.267414,-0.4619 -0.267414,-0.729314 0.559139,-0.243103 1.14259,-0.364656 1.750352,-0.364656 0.364657,-0.02432 0.705005,0.09724 0.99673,0.340347 0.243103,0.218794 0.388965,0.55914 0.388965,1.021037 v 1.653109 c 0,0.364657 0.09724,0.55914 0.243106,0.680691 z m -2.042078,-0.194483 c 0.316034,-0.02432 0.607762,-0.145862 0.802245,-0.388968 v -0.705002 c -0.194483,-0.02432 -0.413279,-0.02432 -0.607762,-0.02432 -0.194483,-0.02432 -0.364659,0.04862 -0.510519,0.170171 -0.121552,0.121554 -0.170172,0.267417 -0.170172,0.437588 0,0.145863 0.04862,0.291726 0.145863,0.413277 0.09724,0.04862 0.218791,0.09724 0.340345,0.09724 z"
|
||||
style="stroke-width:0.8;stroke:#ffffff;stroke-opacity:1;stroke-linejoin:round;stroke-linecap:butt;paint-order:markers stroke fill;stroke-dasharray:none" />
|
||||
<path
|
||||
id="path16"
|
||||
class="st0"
|
||||
d="m 19.759597,25.929383 c -0.243106,-0.364657 -0.364659,-0.875176 -0.364659,-1.531558 0,-0.656382 0.145865,-1.166899 0.461899,-1.531556 0.267416,-0.340345 0.680693,-0.559139 1.118281,-0.559139 0.413279,0 0.802245,0.145863 1.09397,0.413277 0.145863,-0.194483 0.388971,-0.316037 0.632071,-0.340346 0.09724,0.04862 0.170174,0.145863 0.218797,0.218794 0.04862,0.09724 0.09724,0.170172 0.145862,0.291723 -0.145862,0.121554 -0.218796,0.364657 -0.218796,0.705005 v 2.285178 c 0,0.850864 -0.145863,1.458626 -0.413275,1.823281 -0.267416,0.364656 -0.753627,0.53483 -1.385697,0.53483 -0.486211,0 -0.996728,-0.09724 -1.458627,-0.267414 0,-0.267416 0.07293,-0.534831 0.243105,-0.729313 0.340345,0.170174 0.705002,0.243105 1.093968,0.243105 0.364659,0 0.607764,-0.09724 0.729316,-0.267417 0.145862,-0.218794 0.218794,-0.486208 0.194482,-0.753622 v -0.316036 c -0.291725,0.243105 -0.63207,0.388968 -1.021038,0.388968 -0.437589,-0.02432 -0.850868,-0.243106 -1.069659,-0.60776 z m 2.066389,-0.656382 v -1.871903 c -0.170174,-0.194483 -0.437589,-0.316035 -0.705005,-0.340346 -0.218794,0 -0.437586,0.145863 -0.534831,0.340346 -0.145862,0.316036 -0.218794,0.656382 -0.194483,0.996727 0,0.437588 0.04862,0.753625 0.170172,0.948107 0.07293,0.170172 0.267417,0.291726 0.461899,0.316035 0.340348,0 0.632074,-0.145863 0.802248,-0.388966 z"
|
||||
style="stroke-width:0.8;stroke:#ffffff;stroke-opacity:1;stroke-linejoin:round;stroke-linecap:butt;paint-order:markers stroke fill;stroke-dasharray:none" />
|
||||
<path
|
||||
id="path18-7"
|
||||
class="st0"
|
||||
d="m 26.979799,24.73817 h -2.260871 c 0,0.267417 0.07293,0.51052 0.218794,0.729314 0.121551,0.170174 0.340345,0.267414 0.656379,0.267414 0.36466,-0.02432 0.729316,-0.121551 1.069662,-0.291725 0.170174,0.170174 0.267414,0.388968 0.291725,0.607762 -0.461897,0.316034 -0.996727,0.486208 -1.555869,0.461896 -0.60776,0 -1.04535,-0.194482 -1.312762,-0.583448 -0.267419,-0.388968 -0.388968,-0.899487 -0.388968,-1.531558 0,-0.632071 0.14586,-1.14259 0.437588,-1.531556 0.291723,-0.388968 0.753622,-0.607762 1.23983,-0.58345 0.534833,0 0.94811,0.170174 1.239836,0.486208 0.291725,0.340345 0.461896,0.777933 0.437588,1.239833 0,0.243102 -0.02432,0.486208 -0.07293,0.72931 z M 25.42393,23.012132 c -0.437588,0 -0.680693,0.340346 -0.705002,0.996728 h 1.410004 v -0.09724 c 0,-0.218794 -0.04862,-0.461897 -0.170171,-0.656382 -0.121552,-0.170172 -0.340348,-0.243103 -0.534831,-0.243103 z"
|
||||
style="stroke-width:0.8;stroke:#ffffff;stroke-opacity:1;stroke-linejoin:round;stroke-linecap:butt;paint-order:markers stroke fill;stroke-dasharray:none" />
|
||||
</g>
|
||||
<path
|
||||
id="path24-3-6-9"
|
||||
class="st4"
|
||||
d="m 14.970437,1.7648241 c -0.364657,0 -0.729316,0.072931 -1.045352,0.2187938 L 3.179868,6.7484604 c -0.1944833,0.072931 -0.2917252,0.3160354 -0.2187938,0.5105189 0,0 0,0 0,0 0,0.024311 0,0.024311 0.024311,0.048621 L 4.7114273,10.71106 H 6.2186752 L 5.9998812,9.519847 C 5.9755699,9.4226069 5.8297079,8.7419148 5.6838453,8.2557065 l 5.0322627,1.5801772 c 0.07293,0.3160363 0.145863,0.6077593 0.267417,0.8751763 h 8.143998 c 0.09724,-0.267417 0.170172,-0.55914 0.218794,-0.8751763 l 5.007952,-1.5558669 c -0.145861,0.4862083 -0.291723,1.1669014 -0.316035,1.2641415 l -0.218796,1.1912097 h 1.507249 l 1.701732,-3.3791471 0.02432,-0.024311 0.02432,-0.048621 c 0,0 0,0 0,0 0.02432,-0.048621 0.02432,-0.072931 0.02432,-0.1215521 0,-0.170173 -0.09724,-0.3160354 -0.243105,-0.3889668 L 16.113047,2.0079277 C 15.724077,1.8377547 15.35942,1.7405131 14.970455,1.7648234 Z"
|
||||
style="stroke-width:0.243104" />
|
||||
<path
|
||||
id="path24-3-2"
|
||||
class="st0"
|
||||
d="m 14.970437,4.0013828 c -0.364657,0 -0.729316,0.072931 -1.045352,0.2187938 L 3.179868,8.9850191 c -0.1944833,0.072931 -0.2917252,0.3160364 -0.2187938,0.5105192 0,0 0,0 0,0 0,0.024321 0,0.024321 0.024311,0.04862 L 3.9091823,11.391751 H 5.9026395 C 5.8297079,11.124336 5.7567764,10.8083 5.6595347,10.492266 l 2.844323,0.899485 H 21.485638 l 2.844319,-0.899485 c -0.09724,0.291725 -0.170169,0.63207 -0.2431,0.899485 h 1.993452 l 0.923799,-1.8232814 0.02432,-0.024321 0.02432,-0.04862 c 0,0 0,0 0,0 0.02432,-0.04862 0.02432,-0.072931 0.02432,-0.1215514 0,-0.170174 -0.09724,-0.3160367 -0.243105,-0.3889677 L 16.088718,4.2201766 C 15.724059,4.0743142 15.359403,4.0013828 14.970437,4.0013828 Z"
|
||||
style="stroke-width:0.243104" />
|
||||
<path
|
||||
id="path24-0"
|
||||
class="st4"
|
||||
d="m 27.077039,11.659165 c 0,0.04862 0,0.07293 -0.02432,0.121554 0,0 0,0 0,0 l -0.02432,0.04862 v 0 l -0.02432,0.02432 -2.601219,5.153809 c -0.364654,0.705002 -1.021034,0.680691 -0.923791,-0.02432 l 0.534825,-2.917251 c 0.02432,-0.09724 0.170174,-0.777933 0.316037,-1.264141 l -5.007969,1.555867 c -0.777933,5.1295 -7.536236,5.202431 -8.630209,0 l -5.0322664,-1.58018 c 0.1458629,0.486211 0.2917256,1.166902 0.3160361,1.264145 l 0.5348297,2.917248 c 0.1215524,0.729313 -0.5591402,0.753625 -0.9237969,0.02432 l -2.6254813,-5.17813 c 0,-0.0243 -0.024311,-0.0243 -0.024311,-0.04862 -0.097242,-0.194482 0,-0.437588 0.1944835,-0.510519 0,0 0,0 0,0 L 13.876467,6.4810456 c 0.680691,-0.2917249 1.482936,-0.2917249 2.163629,0 l 10.745218,4.7648424 c 0.194485,0.09724 0.291725,0.243105 0.291725,0.413277 z"
|
||||
style="stroke-width:0.243104" />
|
||||
<path
|
||||
id="path26-2"
|
||||
class="st0"
|
||||
d="m 18.422521,12.558652 4.643297,-1.871904 c 0.09724,-0.04862 0.145863,-0.145862 0.121552,-0.267414 -0.02432,-0.04862 -0.04862,-0.09724 -0.121552,-0.121554 -0.534828,-0.218791 -1.215524,-0.4862076 -1.871903,-0.7536217 -0.121557,-0.04862 -1.264147,0.7779337 -1.361387,0.8508647 l -1.993457,1.604487 c -0.4619,0.437588 -0.04862,0.826556 0.58345,0.559142 z"
|
||||
style="stroke-width:0.243104" />
|
||||
<ellipse
|
||||
id="circle28-3"
|
||||
class="st0"
|
||||
cx="15.067682"
|
||||
cy="14.381929"
|
||||
rx="2.4310451"
|
||||
ry="2.4310422"
|
||||
style="stroke-width:0.243104" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2346">
|
||||
.st0{fill:#4E4E4E;}
|
||||
.st1{fill:#FFD952;}
|
||||
.st2{fill:#49C8FA;}
|
||||
.st3{fill:#45C8FF;}
|
||||
.st4{fill:#FF9329;}
|
||||
.st5{fill:#3B2100;}
|
||||
.st6{fill:#C3C3C3;}
|
||||
</style>
|
||||
</svg>
|
After Width: | Height: | Size: 13 KiB |
@ -11,6 +11,7 @@ import { Link, useLocation } from "react-router-dom";
|
||||
import Button from "../ui/button";
|
||||
import { themes } from "@/app/themes";
|
||||
import appStore from "@/stores/app-store";
|
||||
import garageLogo from "@/assets/garage-logo.svg";
|
||||
|
||||
const pages = [
|
||||
{ icon: LayoutDashboard, title: "Dashboard", path: "/", exact: true },
|
||||
@ -26,7 +27,7 @@ const Sidebar = () => {
|
||||
<aside className="bg-base-100 border-r border-base-300/30 w-[80%] md:w-[250px] flex flex-col items-stretch overflow-hidden h-full">
|
||||
<div className="p-4">
|
||||
<img
|
||||
src="https://garagehq.deuxfleurs.fr/images/garage-logo.svg"
|
||||
src={garageLogo}
|
||||
alt="logo"
|
||||
className="w-full max-w-[100px] mx-auto"
|
||||
/>
|
||||
|
@ -18,7 +18,6 @@ export default defineConfig(({ mode }) => {
|
||||
"/api": {
|
||||
target: process.env.VITE_API_URL,
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, ""),
|
||||
},
|
||||
},
|
||||
},
|
||||
|