This commit is contained in:
@@ -12,6 +12,7 @@ import pizzaDayRoutes from "./routes/pizzaDayRoutes";
|
||||
import foodRoutes from "./routes/foodRoutes";
|
||||
import votingRoutes from "./routes/votingRoutes";
|
||||
import easterEggRoutes from "./routes/easterEggRoutes";
|
||||
import statsRoutes from "./routes/statsRoutes";
|
||||
|
||||
const ENVIRONMENT = process.env.NODE_ENV || 'production';
|
||||
dotenv.config({ path: path.resolve(__dirname, `./.env.${ENVIRONMENT}`) });
|
||||
@@ -132,6 +133,7 @@ app.use("/api/pizzaDay", pizzaDayRoutes);
|
||||
app.use("/api/food", foodRoutes);
|
||||
app.use("/api/voting", votingRoutes);
|
||||
app.use("/api/easterEggs", easterEggRoutes);
|
||||
app.use("/api/stats", statsRoutes);
|
||||
app.use(express.static('public'))
|
||||
|
||||
// Middleware pro zpracování chyb
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getDayOfWeekIndex } from "./utils";
|
||||
import { WeeklyStats, Locations } from "../../types";
|
||||
|
||||
// Mockovací data pro podporované podniky, na jeden týden
|
||||
const MOCK_DATA = {
|
||||
@@ -1383,4 +1383,80 @@ export const getMenuSenkSerikovaMock = () => {
|
||||
|
||||
export const getPizzaListMock = () => {
|
||||
return MOCK_PIZZA_LIST;
|
||||
}
|
||||
|
||||
export const getStatsMock = (): WeeklyStats => {
|
||||
// TODO stačilo by iterovat ten enum, jako to už děláme jinde
|
||||
return [
|
||||
{
|
||||
date: '24.02.',
|
||||
locations: {
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SLADOVNICKA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.TECHTOWER)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ZASTAVKAUMICHALA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SENKSERIKOVA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SPSE)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.PIZZA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.OBJEDNAVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.NEOBEDVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ROZHODUJI)]]: Math.floor(Math.random() * 10),
|
||||
}
|
||||
},
|
||||
{
|
||||
date: '25.02.',
|
||||
locations: {
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SLADOVNICKA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.TECHTOWER)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ZASTAVKAUMICHALA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SENKSERIKOVA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SPSE)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.PIZZA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.OBJEDNAVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.NEOBEDVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ROZHODUJI)]]: Math.floor(Math.random() * 10),
|
||||
}
|
||||
},
|
||||
{
|
||||
date: '26.02.',
|
||||
locations: {
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SLADOVNICKA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.TECHTOWER)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ZASTAVKAUMICHALA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SENKSERIKOVA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SPSE)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.PIZZA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.OBJEDNAVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.NEOBEDVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ROZHODUJI)]]: Math.floor(Math.random() * 10),
|
||||
}
|
||||
},
|
||||
{
|
||||
date: '27.02.',
|
||||
locations: {
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SLADOVNICKA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.TECHTOWER)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ZASTAVKAUMICHALA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SENKSERIKOVA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SPSE)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.PIZZA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.OBJEDNAVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.NEOBEDVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ROZHODUJI)]]: Math.floor(Math.random() * 10),
|
||||
}
|
||||
},
|
||||
{
|
||||
date: '28.02.',
|
||||
locations: {
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SLADOVNICKA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.TECHTOWER)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ZASTAVKAUMICHALA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SENKSERIKOVA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.SPSE)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.PIZZA)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.OBJEDNAVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.NEOBEDVAM)]]: Math.floor(Math.random() * 10),
|
||||
[Object.keys(Locations)[Object.values(Locations).indexOf(Locations.ROZHODUJI)]]: Math.floor(Math.random() * 10),
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
22
server/src/routes/statsRoutes.ts
Normal file
22
server/src/routes/statsRoutes.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import express, { Request, Response } from "express";
|
||||
import { getLogin } from "../auth";
|
||||
import { parseToken } from "../utils";
|
||||
import { WeeklyStats } from "../../../types";
|
||||
import { getStats } from "../stats";
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/", async (req: Request<{}, any, undefined>, res: Response<WeeklyStats>) => {
|
||||
getLogin(parseToken(req));
|
||||
if (typeof req.query.startDate === 'string' && typeof req.query.endDate === 'string') {
|
||||
try {
|
||||
const data = await getStats(req.query.startDate, req.query.endDate);
|
||||
return res.status(200).json(data);
|
||||
} catch (e) {
|
||||
// necháme to zatím spadnout na 400
|
||||
}
|
||||
}
|
||||
res.sendStatus(400);
|
||||
});
|
||||
|
||||
export default router;
|
||||
44
server/src/stats.ts
Normal file
44
server/src/stats.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { WeeklyStats, DayData, Locations, DailyStats, LocationKey } from "../../types";
|
||||
import { getStatsMock } from "./mock";
|
||||
import getStorage from "./storage";
|
||||
import { formatDate } from "./utils";
|
||||
|
||||
const storage = getStorage();
|
||||
|
||||
/**
|
||||
* Vypočte a vrátí statistiky jednotlivých možností pro předaný rozsah dat.
|
||||
*
|
||||
* @param startDate počáteční datum
|
||||
* @param endDate koncové datum
|
||||
* @returns statistiky pro zadaný rozsah dat
|
||||
*/
|
||||
export async function getStats(startDate: string, endDate: string): Promise<WeeklyStats> {
|
||||
if (process.env.MOCK_DATA === 'true') {
|
||||
return getStatsMock();
|
||||
}
|
||||
const start = new Date(startDate);
|
||||
const end = new Date(endDate);
|
||||
|
||||
// Dočasná validace, aby to někdo ručně neshodil
|
||||
const daysDiff = ((end as any) - (start as any)) / (1000 * 60 * 60 * 24);
|
||||
if (daysDiff > 4) {
|
||||
throw Error('Neplatný rozsah');
|
||||
}
|
||||
|
||||
const result = [];
|
||||
for (const date = start; date <= end; date.setDate(date.getDate() + 1)) {
|
||||
const locationsStats: DailyStats = {
|
||||
// TODO vytáhnout do utils funkce
|
||||
date: `${String(date.getDate()).padStart(2, "0")}.${String(date.getMonth() + 1).padStart(2, "0")}.`,
|
||||
locations: {}
|
||||
}
|
||||
const data: DayData = await storage.getData(formatDate(date));
|
||||
if (data?.choices) {
|
||||
Object.keys(data.choices).forEach(locationKey => {
|
||||
locationsStats.locations[locationKey as LocationKey] = Object.keys(data.choices[locationKey as LocationKey]!).length;
|
||||
})
|
||||
}
|
||||
result.push(locationsStats);
|
||||
}
|
||||
return result as WeeklyStats;
|
||||
}
|
||||
Reference in New Issue
Block a user