Compare commits
10 Commits
2eabca5a31
...
aa00542a03
Author | SHA1 | Date | |
---|---|---|---|
|
aa00542a03 | ||
ff650ec3b8 | |||
f8aa293413 | |||
cafcd0a467 | |||
9e247eb2a1 | |||
469a6b9031 | |||
|
89dec1c194 | ||
|
f3af64923c | ||
|
44b09a9d1a | ||
|
c311cc2fd7 |
22
.gitignore
vendored
22
.gitignore
vendored
@ -1,23 +1 @@
|
|||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
node_modules
|
node_modules
|
||||||
/.pnp
|
|
||||||
.pnp.js
|
|
||||||
|
|
||||||
# testing
|
|
||||||
/coverage
|
|
||||||
|
|
||||||
# production
|
|
||||||
/build
|
|
||||||
|
|
||||||
# misc
|
|
||||||
.DS_Store
|
|
||||||
.env.local
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
|
56
.woodpecker/workflow.yaml
Normal file
56
.woodpecker/workflow.yaml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
variables:
|
||||||
|
- &node_image 'node:18-alpine3.18'
|
||||||
|
- &branch 'master'
|
||||||
|
|
||||||
|
when:
|
||||||
|
- event: push
|
||||||
|
branch: *branch
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Install server dependencies
|
||||||
|
image: *node_image
|
||||||
|
commands:
|
||||||
|
- cd server
|
||||||
|
- yarn install --frozen-lockfile
|
||||||
|
- name: Install client dependencies
|
||||||
|
image: *node_image
|
||||||
|
commands:
|
||||||
|
- cd client
|
||||||
|
- yarn install --frozen-lockfile
|
||||||
|
- name: Build server
|
||||||
|
depends_on: [Install server dependencies]
|
||||||
|
image: *node_image
|
||||||
|
commands:
|
||||||
|
- cd server
|
||||||
|
- yarn build
|
||||||
|
- name: Build client
|
||||||
|
depends_on: [Install client dependencies]
|
||||||
|
image: *node_image
|
||||||
|
commands:
|
||||||
|
- cd client
|
||||||
|
- yarn build
|
||||||
|
- name: Build Docker image
|
||||||
|
depends_on: [Build server, Build client]
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
settings:
|
||||||
|
dockerfile: Dockerfile-Woodpecker
|
||||||
|
platforms: linux/amd64
|
||||||
|
registry:
|
||||||
|
from_secret: REPO_URL
|
||||||
|
username:
|
||||||
|
from_secret: REPO_USERNAME
|
||||||
|
password:
|
||||||
|
from_secret: REPO_PASSWORD
|
||||||
|
repo:
|
||||||
|
from_secret: REPO_NAME
|
||||||
|
- name: Discord notification - build
|
||||||
|
image: appleboy/drone-discord
|
||||||
|
depends_on: [Build Docker image]
|
||||||
|
when:
|
||||||
|
- status: [success, failure]
|
||||||
|
settings:
|
||||||
|
webhook_id:
|
||||||
|
from_secret: DISCORD_WEBHOOK_ID
|
||||||
|
webhook_token:
|
||||||
|
from_secret: DISCORD_WEBHOOK_TOKEN
|
||||||
|
message: "{{#success build.status}}✅ Sestavení {{build.number}} proběhlo úspěšně.{{else}}❌ Sestavení {{build.number}} selhalo.{{/success}}\n\nPipeline: {{build.link}}\nPoslední commit: {{commit.message}}Autor: {{commit.author}}"
|
@ -54,7 +54,6 @@ WORKDIR /app
|
|||||||
# Vykopírování sestaveného serveru
|
# Vykopírování sestaveného serveru
|
||||||
COPY --from=builder /build/server/node_modules ./server/node_modules
|
COPY --from=builder /build/server/node_modules ./server/node_modules
|
||||||
COPY --from=builder /build/server/dist ./
|
COPY --from=builder /build/server/dist ./
|
||||||
COPY server/resources ./server/resources
|
|
||||||
|
|
||||||
# Vykopírování sestaveného klienta
|
# Vykopírování sestaveného klienta
|
||||||
COPY --from=builder /build/client/dist ./public
|
COPY --from=builder /build/client/dist ./public
|
||||||
@ -63,8 +62,10 @@ COPY --from=builder /build/client/dist ./public
|
|||||||
COPY /server/.env.production ./server/src
|
COPY /server/.env.production ./server/src
|
||||||
|
|
||||||
# Zkopírování konfigurace easter eggů
|
# Zkopírování konfigurace easter eggů
|
||||||
# TODO tohle spadne když nebude existovat!
|
RUN if [ -f /server/.easter-eggs.json ]; then cp /server/.easter-eggs.json ./server/; fi
|
||||||
COPY /server/.easter-eggs.json ./server/
|
|
||||||
|
# Export /data/db.json do složky /data
|
||||||
|
VOLUME ["/data"]
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
|
21
Dockerfile-Woodpecker
Normal file
21
Dockerfile-Woodpecker
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
FROM node:18-alpine3.18
|
||||||
|
ENV LANG=cs_CZ.UTF-8
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Vykopírování sestaveného serveru
|
||||||
|
COPY ./server/node_modules ./server/node_modules
|
||||||
|
COPY ./server/dist ./
|
||||||
|
# TODO tohle není dobře, má to být součástí serveru
|
||||||
|
# COPY ./server/resources ./resources
|
||||||
|
|
||||||
|
# Vykopírování sestaveného klienta
|
||||||
|
COPY ./client/dist ./public
|
||||||
|
|
||||||
|
# Zkopírování konfigurace easter eggů
|
||||||
|
RUN if [ -f ./server/.easter-eggs.json ]; then cp ./server/.easter-eggs.json ./server/; fi
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD [ "node", "./server/src/index.js" ]
|
1
client/.gitignore
vendored
1
client/.gitignore
vendored
@ -1,3 +1,2 @@
|
|||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
src/types
|
|
@ -31,9 +31,8 @@
|
|||||||
"vite-tsconfig-paths": "^5.1.4"
|
"vite-tsconfig-paths": "^5.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"copy-types": "cp -r ../types ./src",
|
"start": "yarn vite",
|
||||||
"start": "yarn copy-types && vite",
|
"build": "yarn vite build"
|
||||||
"build": "yarn copy-types && vite build"
|
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
|
@ -8,13 +8,12 @@ import { Alert, Button, Col, Form, Row, Table } from 'react-bootstrap';
|
|||||||
import Header from './components/Header';
|
import Header from './components/Header';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
import PizzaOrderList from './components/PizzaOrderList';
|
import PizzaOrderList from './components/PizzaOrderList';
|
||||||
import SelectSearch, { SelectedOptionValue } from 'react-select-search';
|
import SelectSearch, {SelectedOptionValue, SelectSearchOption} from 'react-select-search';
|
||||||
import 'react-select-search/style.css';
|
import 'react-select-search/style.css';
|
||||||
import './App.scss';
|
import './App.scss';
|
||||||
import { SelectSearchOption } from 'react-select-search';
|
|
||||||
import { faCircleCheck, faNoteSticky, faTrashCan } from '@fortawesome/free-regular-svg-icons';
|
import { faCircleCheck, faNoteSticky, faTrashCan } from '@fortawesome/free-regular-svg-icons';
|
||||||
import { useSettings } from './context/settings';
|
import { useSettings } from './context/settings';
|
||||||
import { ClientData, Restaurants, Food, Order, Locations, PizzaOrder, PizzaDayState, FoodChoices, DayMenu, DepartureTime, LocationKey } from './types';
|
import { ClientData, Restaurants, Food, Order, Locations, PizzaOrder, PizzaDayState, FoodChoices, DayMenu, DepartureTime, LocationKey } from '../../types';
|
||||||
import Footer from './components/Footer';
|
import Footer from './components/Footer';
|
||||||
import { faChainBroken, faChevronLeft, faChevronRight, faGear, faSatelliteDish, faSearch } from '@fortawesome/free-solid-svg-icons';
|
import { faChainBroken, faChevronLeft, faChevronRight, faGear, faSatelliteDish, faSearch } from '@fortawesome/free-solid-svg-icons';
|
||||||
import Loader from './components/Loader';
|
import Loader from './components/Loader';
|
||||||
@ -190,6 +189,13 @@ function App() {
|
|||||||
}
|
}
|
||||||
}, [auth?.login, easterEgg?.duration, easterEgg?.url, eggImage]);
|
}, [auth?.login, easterEgg?.duration, easterEgg?.url, eggImage]);
|
||||||
|
|
||||||
|
const doAddClickFoodChoice = async (location: Locations, foodIndex: number) => {
|
||||||
|
const locationKey = Object.keys(Locations).find(key => Locations[key as keyof typeof Locations] === location) as LocationKey;
|
||||||
|
if (auth?.login) {
|
||||||
|
await errorHandler(() => addChoice(locationKey, foodIndex, dayIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const doAddChoice = async (event: React.ChangeEvent<HTMLSelectElement>) => {
|
const doAddChoice = async (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
const locationKey = event.target.value as LocationKey;
|
const locationKey = event.target.value as LocationKey;
|
||||||
if (auth?.login) {
|
if (auth?.login) {
|
||||||
@ -332,15 +338,15 @@ function App() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderFoodTable = (name: string, menu: DayMenu) => {
|
const renderFoodTable = (name: string, location: Locations, menu: DayMenu) => {
|
||||||
let content;
|
let content;
|
||||||
if (menu?.closed) {
|
if (menu?.closed) {
|
||||||
content = <h3>Zavřeno</h3>
|
content = <h3>Zavřeno</h3>
|
||||||
} else if (menu?.food?.length > 0) {
|
} else if (menu?.food?.length > 0) {
|
||||||
content = <Table striped bordered hover>
|
content = <Table striped bordered hover>
|
||||||
<tbody>
|
<tbody style={{ cursor: 'pointer' }}>
|
||||||
{menu.food.filter(f => (settings?.hideSoups ? !f.isSoup : true)).map((f: any, index: number) =>
|
{menu.food.filter(f => (settings?.hideSoups ? !f.isSoup : true)).map((f: any, index: number) =>
|
||||||
<tr key={index}>
|
<tr key={index} onClick={() => doAddClickFoodChoice(location, index)}>
|
||||||
<td>{f.amount}</td>
|
<td>{f.amount}</td>
|
||||||
<td>{f.name}</td>
|
<td>{f.name}</td>
|
||||||
<td>{f.price}</td>
|
<td>{f.price}</td>
|
||||||
@ -402,8 +408,8 @@ function App() {
|
|||||||
<img src='snowman.png' style={{ position: "absolute", height: "110px", right: 10, top: 5 }} />
|
<img src='snowman.png' style={{ position: "absolute", height: "110px", right: 10, top: 5 }} />
|
||||||
Poslední změny:
|
Poslední změny:
|
||||||
<ul>
|
<ul>
|
||||||
<li>Přidání restaurace Zastávka u Michala</li>
|
<li>Přidání restaurací Zastávka u Michala a Pivovarský šenk Šeříková</li>
|
||||||
<li>Přidání restaurace Pivovarský šenk Šeříková</li>
|
<li>Možnost výběru restaurace a jídel kliknutím v tabulce</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Alert>
|
</Alert>
|
||||||
{dayIndex != null &&
|
{dayIndex != null &&
|
||||||
@ -414,11 +420,11 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<Row className='food-tables'>
|
<Row className='food-tables'>
|
||||||
{food[Restaurants.SLADOVNICKA] && renderFoodTable('Sladovnická', food[Restaurants.SLADOVNICKA])}
|
{food[Restaurants.SLADOVNICKA] && renderFoodTable('Sladovnická', Locations.SLADOVNICKA, food[Restaurants.SLADOVNICKA])}
|
||||||
{/* {food[Restaurants.UMOTLIKU] && renderFoodTable('U Motlíků', food[Restaurants.UMOTLIKU])} */}
|
{/* {food[Restaurants.UMOTLIKU] && renderFoodTable('U Motlíků', food[Restaurants.UMOTLIKU])} */}
|
||||||
{food[Restaurants.TECHTOWER] && renderFoodTable('TechTower', food[Restaurants.TECHTOWER])}
|
{food[Restaurants.TECHTOWER] && renderFoodTable('TechTower', Locations.TECHTOWER, food[Restaurants.TECHTOWER])}
|
||||||
{food[Restaurants.ZASTAVKAUMICHALA] && renderFoodTable('Zastávka u Michala', food[Restaurants.ZASTAVKAUMICHALA])}
|
{food[Restaurants.ZASTAVKAUMICHALA] && renderFoodTable('Zastávka u Michala', Locations.ZASTAVKAUMICHALA, food[Restaurants.ZASTAVKAUMICHALA])}
|
||||||
{food[Restaurants.SENKSERIKOVA] && renderFoodTable('Pivovarský šenk Šeříková', food[Restaurants.SENKSERIKOVA])}
|
{food[Restaurants.SENKSERIKOVA] && renderFoodTable('Pivovarský šenk Šeříková', Locations.SENKSERIKOVA, food[Restaurants.SENKSERIKOVA])}
|
||||||
</Row>
|
</Row>
|
||||||
<div className='content-wrapper'>
|
<div className='content-wrapper'>
|
||||||
<div className='content'>
|
<div className='content'>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { EasterEgg } from "../types";
|
import { EasterEgg } from "../../../types";
|
||||||
import { api } from "./Api";
|
import { api } from "./Api";
|
||||||
|
|
||||||
const EASTER_EGGS_API_PREFIX = '/api/easterEggs';
|
const EASTER_EGGS_API_PREFIX = '/api/easterEggs';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { AddChoiceRequest, ChangeDepartureTimeRequest, LocationKey, RemoveChoiceRequest, RemoveChoicesRequest, UpdateNoteRequest } from "../types";
|
import { AddChoiceRequest, ChangeDepartureTimeRequest, LocationKey, RemoveChoiceRequest, RemoveChoicesRequest, UpdateNoteRequest } from "../../../types";
|
||||||
import { api } from "./Api";
|
import { api } from "./Api";
|
||||||
|
|
||||||
const FOOD_API_PREFIX = '/api/food';
|
const FOOD_API_PREFIX = '/api/food';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { AddPizzaRequest, FinishDeliveryRequest, PizzaOrder, RemovePizzaRequest, UpdatePizzaDayNoteRequest, UpdatePizzaFeeRequest } from "../types";
|
import { AddPizzaRequest, FinishDeliveryRequest, PizzaOrder, RemovePizzaRequest, UpdatePizzaDayNoteRequest, UpdatePizzaFeeRequest } from "../../../types";
|
||||||
import { api } from "./Api";
|
import { api } from "./Api";
|
||||||
|
|
||||||
const PIZZADAY_API_PREFIX = '/api/pizzaDay';
|
const PIZZADAY_API_PREFIX = '/api/pizzaDay';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { FeatureRequest, UpdateFeatureVoteRequest } from "../types";
|
import { FeatureRequest, UpdateFeatureVoteRequest } from "../../../types";
|
||||||
import { api } from "./Api";
|
import { api } from "./Api";
|
||||||
|
|
||||||
const VOTING_API_PREFIX = '/api/voting';
|
const VOTING_API_PREFIX = '/api/voting';
|
||||||
|
@ -4,7 +4,7 @@ import { useAuth } from "../context/auth";
|
|||||||
import SettingsModal from "./modals/SettingsModal";
|
import SettingsModal from "./modals/SettingsModal";
|
||||||
import { useSettings } from "../context/settings";
|
import { useSettings } from "../context/settings";
|
||||||
import FeaturesVotingModal from "./modals/FeaturesVotingModal";
|
import FeaturesVotingModal from "./modals/FeaturesVotingModal";
|
||||||
import { FeatureRequest } from "../types";
|
import { FeatureRequest } from "../../../types";
|
||||||
import { errorHandler } from "../api/Api";
|
import { errorHandler } from "../api/Api";
|
||||||
import { getFeatureVotes, updateFeatureVote } from "../api/VotingApi";
|
import { getFeatureVotes, updateFeatureVote } from "../api/VotingApi";
|
||||||
import PizzaCalculatorModal from "./modals/PizzaCalculatorModal";
|
import PizzaCalculatorModal from "./modals/PizzaCalculatorModal";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Table } from "react-bootstrap";
|
import { Table } from "react-bootstrap";
|
||||||
import { Order, PizzaDayState, PizzaOrder } from "../types";
|
import { Order, PizzaDayState, PizzaOrder } from "../../../types";
|
||||||
import PizzaOrderRow from "./PizzaOrderRow";
|
import PizzaOrderRow from "./PizzaOrderRow";
|
||||||
import { updatePizzaFee } from "../api/PizzaDayApi";
|
import { updatePizzaFee } from "../api/PizzaDayApi";
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import React, { useState } from "react";
|
|||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { faMoneyBill1, faTrashCan } from "@fortawesome/free-regular-svg-icons";
|
import { faMoneyBill1, faTrashCan } from "@fortawesome/free-regular-svg-icons";
|
||||||
import { useAuth } from "../context/auth";
|
import { useAuth } from "../context/auth";
|
||||||
import { Order, PizzaDayState, PizzaOrder } from "../types";
|
import { Order, PizzaDayState, PizzaOrder } from "../../../types";
|
||||||
import PizzaAdditionalFeeModal from "./modals/PizzaAdditionalFeeModal";
|
import PizzaAdditionalFeeModal from "./modals/PizzaAdditionalFeeModal";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Modal, Button, Form } from "react-bootstrap"
|
import { Modal, Button, Form } from "react-bootstrap"
|
||||||
import { FeatureRequest } from "../../types";
|
import { FeatureRequest } from "../../../../types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean,
|
isOpen: boolean,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { getEasterEgg } from "../api/EasterEggApi";
|
import { getEasterEgg } from "../api/EasterEggApi";
|
||||||
import { AuthContextProps } from "./auth";
|
import { AuthContextProps } from "./auth";
|
||||||
import { EasterEgg } from "../types";
|
import { EasterEgg } from "../../../types";
|
||||||
|
|
||||||
export const useEasterEgg = (auth?: AuthContextProps | null): [EasterEgg | undefined, boolean] => {
|
export const useEasterEgg = (auth?: AuthContextProps | null): [EasterEgg | undefined, boolean] => {
|
||||||
const [result, setResult] = useState<EasterEgg | undefined>();
|
const [result, setResult] = useState<EasterEgg | undefined>();
|
||||||
|
4
server/.gitignore
vendored
4
server/.gitignore
vendored
@ -1,7 +1,5 @@
|
|||||||
/node_modules
|
|
||||||
/dist
|
/dist
|
||||||
data.json
|
/resources/easterEggs
|
||||||
.env.production
|
.env.production
|
||||||
.env.development
|
.env.development
|
||||||
.easter-eggs.json
|
.easter-eggs.json
|
||||||
/resources/easterEggs
|
|
@ -100,7 +100,9 @@ app.use("/api/", (req, res, next) => {
|
|||||||
const emailHeader = req.header('remote-email');
|
const emailHeader = req.header('remote-email');
|
||||||
if (userHeader !== undefined && nameHeader !== undefined) {
|
if (userHeader !== undefined && nameHeader !== undefined) {
|
||||||
const remoteName = Buffer.from(nameHeader, 'latin1').toString();
|
const remoteName = Buffer.from(nameHeader, 'latin1').toString();
|
||||||
console.log("Tvuj username, name a email: %s, %s, %s.", userHeader, remoteName, emailHeader);
|
if (ENVIRONMENT !== "production"){
|
||||||
|
console.log("Tvuj username, name a email: %s, %s, %s.", userHeader, remoteName, emailHeader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!req.headers.authorization) {
|
if (!req.headers.authorization) {
|
||||||
|
@ -268,14 +268,19 @@ export async function removeChoice(login: string, trusted: boolean, locationKey:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Odstraní kompletně volbu uživatele.
|
* Odstraní kompletně volbu uživatele, vyjma ignoredLocationKey (pokud byla předána a existuje).
|
||||||
*
|
*
|
||||||
* @param login login uživatele
|
* @param login login uživatele
|
||||||
|
* @param date datum, ke kterému se volby vztahují
|
||||||
|
* @param ignoredLocationKey volba, která nebude odstraněna, pokud existuje
|
||||||
*/
|
*/
|
||||||
async function removeChoiceIfPresent(login: string, date: string) {
|
async function removeChoiceIfPresent(login: string, date: string, ignoredLocationKey?: LocationKey) {
|
||||||
let data: DayData = await storage.getData(date);
|
let data: DayData = await storage.getData(date);
|
||||||
for (const key of Object.keys(data.choices)) {
|
for (const key of Object.keys(data.choices)) {
|
||||||
const locationKey = key as LocationKey;
|
const locationKey = key as LocationKey;
|
||||||
|
if (ignoredLocationKey != null && ignoredLocationKey == locationKey) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (data.choices[locationKey] && login in data.choices[locationKey]) {
|
if (data.choices[locationKey] && login in data.choices[locationKey]) {
|
||||||
delete data.choices[locationKey][login];
|
delete data.choices[locationKey][login];
|
||||||
if (Object.keys(data.choices[locationKey]).length === 0) {
|
if (Object.keys(data.choices[locationKey]).length === 0) {
|
||||||
@ -329,6 +334,9 @@ export async function addChoice(login: string, trusted: boolean, locationKey: Lo
|
|||||||
// Pokud měníme pouze lokaci, mažeme případné předchozí
|
// Pokud měníme pouze lokaci, mažeme případné předchozí
|
||||||
if (foodIndex == null) {
|
if (foodIndex == null) {
|
||||||
data = await removeChoiceIfPresent(login, selectedDate);
|
data = await removeChoiceIfPresent(login, selectedDate);
|
||||||
|
} else {
|
||||||
|
// Mažeme případné ostatní volby (měla by být maximálně jedna)
|
||||||
|
removeChoiceIfPresent(login, selectedDate, locationKey);
|
||||||
}
|
}
|
||||||
// TODO vytáhnout inicializaci "prázdné struktury" do vlastní funkce
|
// TODO vytáhnout inicializaci "prázdné struktury" do vlastní funkce
|
||||||
if (!(data.choices[locationKey])) {
|
if (!(data.choices[locationKey])) {
|
||||||
|
@ -1,8 +1,17 @@
|
|||||||
import JSONdb from 'simple-json-db';
|
import JSONdb from 'simple-json-db';
|
||||||
import { StorageInterface } from "./StorageInterface";
|
import { StorageInterface } from "./StorageInterface";
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
const db = new JSONdb('./data.json');
|
const dbPath = path.resolve(__dirname, '../../data/db.json');
|
||||||
|
const dbDir = path.dirname(dbPath);
|
||||||
|
|
||||||
|
// Zajistěte, že adresář existuje
|
||||||
|
if (!fs.existsSync(dbDir)) {
|
||||||
|
fs.mkdirSync(dbDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = new JSONdb(dbPath);
|
||||||
/**
|
/**
|
||||||
* Implementace úložiště používající JSON soubor.
|
* Implementace úložiště používající JSON soubor.
|
||||||
*/
|
*/
|
||||||
|
@ -111,6 +111,7 @@ export type Food = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO tohle je dost špatné pojmenování, vzhledem k tomu co to obsahuje
|
// TODO tohle je dost špatné pojmenování, vzhledem k tomu co to obsahuje
|
||||||
|
// TODO pokud by se použilo ovládáni výběru obědu kliknutím, pak bych restaurace z tohoto výčtu vyhodil
|
||||||
export enum Locations {
|
export enum Locations {
|
||||||
SLADOVNICKA = 'Sladovnická',
|
SLADOVNICKA = 'Sladovnická',
|
||||||
// UMOTLIKU = 'U Motlíků',
|
// UMOTLIKU = 'U Motlíků',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user