adding sk1
This commit is contained in:
parent
56e08dbe7b
commit
38dd167159
1
sk1/.env.example
Normal file
1
sk1/.env.example
Normal file
@ -0,0 +1 @@
|
|||||||
|
POSTGRES_PASSWORD=changeme
|
||||||
2
sk1/.gitignore
vendored
Normal file
2
sk1/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.env
|
||||||
|
node_modules
|
||||||
13
sk1/backend/Dockerfile
Normal file
13
sk1/backend/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
FROM node:20
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json .
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
CMD ["npm", "start"]
|
||||||
11
sk1/backend/db.js
Normal file
11
sk1/backend/db.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
const { Pool } = require("pg");
|
||||||
|
|
||||||
|
const pool = new Pool({
|
||||||
|
user: "budget_user",
|
||||||
|
host: "postgres",
|
||||||
|
database: "budget_db",
|
||||||
|
password: process.env.POSTGRES_PASSWORD,
|
||||||
|
port: 5432,
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = pool;
|
||||||
14
sk1/backend/package.json
Normal file
14
sk1/backend/package.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "budget-backend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "server.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"express": "^4.19.2",
|
||||||
|
"pg": "^8.11.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
65
sk1/backend/server.js
Normal file
65
sk1/backend/server.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const cors = require("cors");
|
||||||
|
const dotenv = require("dotenv");
|
||||||
|
const pool = require("./db");
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
app.use(cors());
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
app.get("/transactions", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result = await pool.query(
|
||||||
|
"SELECT * FROM transactions ORDER BY created_at DESC"
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json(result.rows);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.post("/transactions", async (req, res) => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const { title, amount, type } = req.body;
|
||||||
|
|
||||||
|
const result = await pool.query(
|
||||||
|
"INSERT INTO transactions (title, amount, type) VALUES ($1, $2, $3) RETURNING *",
|
||||||
|
[title, amount, type]
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json(result.rows[0]);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.delete("/transactions/:id", async (req, res) => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
await pool.query(
|
||||||
|
"DELETE FROM transactions WHERE id = $1",
|
||||||
|
[id]
|
||||||
|
);
|
||||||
|
|
||||||
|
res.json("transaction deleted");
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(5000, () => {
|
||||||
|
console.log("server running on port 5000");
|
||||||
|
});
|
||||||
|
|
||||||
9
sk1/backup/backup.sh
Executable file
9
sk1/backup/backup.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
DATE=$(date +%Y-%m-%d_%H-%M-%S)
|
||||||
|
|
||||||
|
mkdir -p backups
|
||||||
|
|
||||||
|
docker exec budget_postgres pg_dump -U budget_user budget_db > backups/backup_$DATE.sql
|
||||||
|
|
||||||
|
echo "backup created: backups/backup_$DATE.sql"
|
||||||
98
sk1/backups/backup_2026-05-19_12-37-24.sql
Normal file
98
sk1/backups/backup_2026-05-19_12-37-24.sql
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
--
|
||||||
|
-- PostgreSQL database dump
|
||||||
|
--
|
||||||
|
|
||||||
|
\restrict TBO5p6lvhgQlVM1tXKahkrIRa7cGMBX5CXBrOfkVAQUoFQjgAIX2DM2f2jG00du
|
||||||
|
|
||||||
|
-- Dumped from database version 16.14 (Debian 16.14-1.pgdg13+1)
|
||||||
|
-- Dumped by pg_dump version 16.14 (Debian 16.14-1.pgdg13+1)
|
||||||
|
|
||||||
|
SET statement_timeout = 0;
|
||||||
|
SET lock_timeout = 0;
|
||||||
|
SET idle_in_transaction_session_timeout = 0;
|
||||||
|
SET client_encoding = 'UTF8';
|
||||||
|
SET standard_conforming_strings = on;
|
||||||
|
SELECT pg_catalog.set_config('search_path', '', false);
|
||||||
|
SET check_function_bodies = false;
|
||||||
|
SET xmloption = content;
|
||||||
|
SET client_min_messages = warning;
|
||||||
|
SET row_security = off;
|
||||||
|
|
||||||
|
SET default_tablespace = '';
|
||||||
|
|
||||||
|
SET default_table_access_method = heap;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: transactions; Type: TABLE; Schema: public; Owner: budget_user
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public.transactions (
|
||||||
|
id integer NOT NULL,
|
||||||
|
title text NOT NULL,
|
||||||
|
amount numeric NOT NULL,
|
||||||
|
type text NOT NULL,
|
||||||
|
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE public.transactions OWNER TO budget_user;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: transactions_id_seq; Type: SEQUENCE; Schema: public; Owner: budget_user
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.transactions_id_seq
|
||||||
|
AS integer
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
|
ALTER SEQUENCE public.transactions_id_seq OWNER TO budget_user;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: transactions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: budget_user
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER SEQUENCE public.transactions_id_seq OWNED BY public.transactions.id;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: transactions id; Type: DEFAULT; Schema: public; Owner: budget_user
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.transactions ALTER COLUMN id SET DEFAULT nextval('public.transactions_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Data for Name: transactions; Type: TABLE DATA; Schema: public; Owner: budget_user
|
||||||
|
--
|
||||||
|
|
||||||
|
COPY public.transactions (id, title, amount, type, created_at) FROM stdin;
|
||||||
|
1 asd 4 expense 2026-05-19 06:56:50.824855
|
||||||
|
\.
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: transactions_id_seq; Type: SEQUENCE SET; Schema: public; Owner: budget_user
|
||||||
|
--
|
||||||
|
|
||||||
|
SELECT pg_catalog.setval('public.transactions_id_seq', 1, true);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: transactions transactions_pkey; Type: CONSTRAINT; Schema: public; Owner: budget_user
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.transactions
|
||||||
|
ADD CONSTRAINT transactions_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- PostgreSQL database dump complete
|
||||||
|
--
|
||||||
|
|
||||||
|
\unrestrict TBO5p6lvhgQlVM1tXKahkrIRa7cGMBX5CXBrOfkVAQUoFQjgAIX2DM2f2jG00du
|
||||||
|
|
||||||
7
sk1/db/init.sql
Normal file
7
sk1/db/init.sql
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
CREATE TABLE transactions (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
amount NUMERIC NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
50
sk1/docker-compose.yaml
Normal file
50
sk1/docker-compose.yaml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
services:
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
build: ./frontend
|
||||||
|
container_name: budget_frontend
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
depends_on:
|
||||||
|
- backend
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build: ./backend
|
||||||
|
container_name: budget_backend
|
||||||
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:16
|
||||||
|
container_name: budget_postgres
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: budget_user
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
POSTGRES_DB: budget_db
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
image: nginx:latest
|
||||||
|
container_name: budget_nginx
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
volumes:
|
||||||
|
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
|
||||||
|
depends_on:
|
||||||
|
- frontend
|
||||||
|
- backend
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
13
sk1/frontend/Dockerfile
Normal file
13
sk1/frontend/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
FROM node:20
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json .
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["npm", "start"]
|
||||||
14
sk1/frontend/package.json
Normal file
14
sk1/frontend/package.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "budget-frontend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.7.2",
|
||||||
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1",
|
||||||
|
"react-scripts": "^5.0.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "react-scripts start"
|
||||||
|
}
|
||||||
|
}
|
||||||
10
sk1/frontend/public/index.html
Normal file
10
sk1/frontend/public/index.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Budget Tracker</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
111
sk1/frontend/src/App.css
Normal file
111
sk1/frontend/src/App.css
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background-color: #0f172a;
|
||||||
|
font-family: Arial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 40px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-card {
|
||||||
|
background-color: #1e293b;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 15px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.income-card {
|
||||||
|
flex: 1;
|
||||||
|
background-color: #00c853;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-card {
|
||||||
|
flex: 1;
|
||||||
|
background-color: #ff1744;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
background-color: #1e293b;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input,
|
||||||
|
.select {
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-button {
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #2563eb;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transactions-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction-card {
|
||||||
|
background-color: #1e293b;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.income-border {
|
||||||
|
border-left: 5px solid #00c853;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expense-border {
|
||||||
|
border-left: 5px solid #ff1744;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-button {
|
||||||
|
background-color: #ff1744;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
color: #cbd5e1;
|
||||||
|
}
|
||||||
186
sk1/frontend/src/App.js
Normal file
186
sk1/frontend/src/App.js
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import axios from "axios";
|
||||||
|
import "./App.css";
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
|
||||||
|
const [transactions, setTransactions] = useState([]);
|
||||||
|
const [title, setTitle] = useState("");
|
||||||
|
const [amount, setAmount] = useState("");
|
||||||
|
const [type, setType] = useState("expense");
|
||||||
|
|
||||||
|
const fetchTransactions = async () => {
|
||||||
|
|
||||||
|
const res = await axios.get("/api/transactions");
|
||||||
|
|
||||||
|
setTransactions(res.data);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchTransactions();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const addTransaction = async (e) => {
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
await axios.post("/api/transactions", {
|
||||||
|
title,
|
||||||
|
amount,
|
||||||
|
type
|
||||||
|
});
|
||||||
|
|
||||||
|
setTitle("");
|
||||||
|
setAmount("");
|
||||||
|
|
||||||
|
fetchTransactions();
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteTransaction = async (id) => {
|
||||||
|
|
||||||
|
await axios.delete(`/api/transactions/${id}`);
|
||||||
|
|
||||||
|
fetchTransactions();
|
||||||
|
};
|
||||||
|
|
||||||
|
const income = transactions
|
||||||
|
.filter(t => t.type === "income")
|
||||||
|
.reduce((acc, t) => acc + Number(t.amount), 0);
|
||||||
|
|
||||||
|
const expenses = transactions
|
||||||
|
.filter(t => t.type === "expense")
|
||||||
|
.reduce((acc, t) => acc + Number(t.amount), 0);
|
||||||
|
|
||||||
|
const balance = income - expenses;
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
<div className="page">
|
||||||
|
|
||||||
|
<div className="container">
|
||||||
|
|
||||||
|
<h1 className="title">
|
||||||
|
Budget Tracker
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div className="balance-card">
|
||||||
|
|
||||||
|
<h2>Balance</h2>
|
||||||
|
|
||||||
|
<h1>{balance} €</h1>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="stats-container">
|
||||||
|
|
||||||
|
<div className="income-card">
|
||||||
|
|
||||||
|
<h3>Income</h3>
|
||||||
|
|
||||||
|
<p>{income} €</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="expense-card">
|
||||||
|
|
||||||
|
<h3>Expenses</h3>
|
||||||
|
|
||||||
|
<p>{expenses} €</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form
|
||||||
|
onSubmit={addTransaction}
|
||||||
|
className="form"
|
||||||
|
>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="transaction title"
|
||||||
|
value={title}
|
||||||
|
onChange={(e) => setTitle(e.target.value)}
|
||||||
|
required
|
||||||
|
className="input"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
placeholder="amount"
|
||||||
|
value={amount}
|
||||||
|
onChange={(e) => setAmount(e.target.value)}
|
||||||
|
required
|
||||||
|
className="input"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<select
|
||||||
|
value={type}
|
||||||
|
onChange={(e) => setType(e.target.value)}
|
||||||
|
className="select"
|
||||||
|
>
|
||||||
|
|
||||||
|
<option value="expense">
|
||||||
|
expense
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="income">
|
||||||
|
income
|
||||||
|
</option>
|
||||||
|
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="add-button"
|
||||||
|
>
|
||||||
|
Add Transaction
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div className="transactions-container">
|
||||||
|
|
||||||
|
{transactions.map(transaction => (
|
||||||
|
|
||||||
|
<div
|
||||||
|
key={transaction.id}
|
||||||
|
className={`transaction-card ${
|
||||||
|
transaction.type === "income"
|
||||||
|
? "income-border"
|
||||||
|
: "expense-border"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<h3>{transaction.title}</h3>
|
||||||
|
|
||||||
|
<p>{transaction.amount} €</p>
|
||||||
|
|
||||||
|
<small>
|
||||||
|
{new Date(transaction.created_at).toLocaleString()}
|
||||||
|
</small>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={() => deleteTransaction(transaction.id)}
|
||||||
|
className="delete-button"
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
))}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
13
sk1/frontend/src/index.js
Normal file
13
sk1/frontend/src/index.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom/client";
|
||||||
|
import App from "./App";
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(
|
||||||
|
document.getElementById("root")
|
||||||
|
);
|
||||||
|
|
||||||
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
12
sk1/nginx/default.conf
Normal file
12
sk1/nginx/default.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
server {
|
||||||
|
|
||||||
|
listen 80;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://frontend:3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://backend:5000/;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
sk1/prepare-app.sh
Executable file
3
sk1/prepare-app.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
docker compose up -d --build
|
||||||
3
sk1/remove-app.sh
Executable file
3
sk1/remove-app.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
docker compose down -v
|
||||||
Loading…
Reference in New Issue
Block a user