Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a2afc3f1b | ||
|
|
d824844ae5 | ||
|
|
f95a26acbb | ||
| e0618e431f | |||
| 1b93a8e2bb | |||
| b8dc15cbc6 | |||
|
|
949416d2a3 | ||
|
|
1ec9f1a7ec | ||
|
|
17c63e6fe0 | ||
|
|
87c1cbb19e | ||
| c86f84d037 | |||
| b8bc2c83a3 | |||
| 552457b5cb | |||
|
|
909f7e4de9 | ||
|
|
86b79a7f49 | ||
|
|
d2d8b63aba | ||
|
|
0dcf961cce |
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "multi-stub",
|
"name": "multi-stub",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "multi-stub",
|
"name": "multi-stub",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "multi-stub",
|
"name": "multi-stub",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,9 +1,21 @@
|
|||||||
const router = require('express').Router()
|
const router = require('express').Router()
|
||||||
|
const { OrderModel } = require('./model/order')
|
||||||
|
|
||||||
router.post('/orders', (req, res) => {
|
router.post('/orders', async (req, res, next) => {
|
||||||
res
|
const {startDate, endDate} = req.body
|
||||||
.status(200)
|
|
||||||
.send(require(`./json/arm-orders/success.json`))
|
if (!startDate || !endDate) {
|
||||||
|
throw new Error('startDate and endDate are required')
|
||||||
|
}
|
||||||
|
|
||||||
|
const orders = await OrderModel.find({
|
||||||
|
$or: [
|
||||||
|
{startWashTime: { $gte: new Date(startDate), $lte: new Date(endDate) }},
|
||||||
|
{endWashTime: { $gte: new Date(startDate), $lte: new Date(endDate) }},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
res.status(200).send({ success: true, body: orders })
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
const router = require('express').Router()
|
const router = require('express').Router()
|
||||||
const armMasterRouter = require('./arm-master')
|
const armMasterRouter = require('./arm-master')
|
||||||
const armOrdersRouter = require('./arm-orders')
|
const armOrdersRouter = require('./arm-orders')
|
||||||
|
const orderRouter = require('./order')
|
||||||
|
|
||||||
|
|
||||||
router.use('/arm', armMasterRouter)
|
router.use('/arm', armMasterRouter)
|
||||||
router.use('/arm', armOrdersRouter)
|
router.use('/arm', armOrdersRouter)
|
||||||
|
router.use('/order', orderRouter)
|
||||||
|
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|||||||
@@ -2,24 +2,59 @@
|
|||||||
"success": true,
|
"success": true,
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"id": "order1",
|
"phone": "+79876543210",
|
||||||
"carNumber": "A123BC",
|
"carNumber": "А123ВЕ16",
|
||||||
"startWashTime": "2024-11-24T10:30:00.000Z",
|
"carBody": 1,
|
||||||
"endWashTime": "2024-11-24T16:30:00.000Z",
|
"carColor": "#ffff00",
|
||||||
"orderDate": "2024-11-24T08:41:46.366Z",
|
"startWashTime": "2025-05-12T08:21:00.000Z",
|
||||||
|
"endWashTime": "2025-05-12T08:22:00.000Z",
|
||||||
|
"location": "55.792799704829854,49.11034340707925 Республика Татарстан (Татарстан), Казань, улица Чернышевского",
|
||||||
"status": "progress",
|
"status": "progress",
|
||||||
"phone": "79001234563",
|
"notes": "",
|
||||||
"location": "Казань, ул. Баумана, 1"
|
"created": "2025-01-18T17:43:21.488Z",
|
||||||
|
"updated": "2025-01-18T17:43:21.492Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "order2",
|
"phone": "89876543210",
|
||||||
"carNumber": "A245BC",
|
"carNumber": "К456МН23",
|
||||||
"startWashTime": "2024-11-24T11:30:00.000Z",
|
"carBody": 2,
|
||||||
"endWashTime": "2024-11-24T17:30:00.000Z",
|
"carColor": "#ffffff",
|
||||||
"orderDate": "2024-11-24T07:40:46.366Z",
|
"startWashTime": "2025-01-12T08:21:00Z",
|
||||||
|
"endWashTime": "2025-01-12T08:22:00Z",
|
||||||
|
"location": "55.808430668108585,49.198608125449255 Республика Татарстан (Татарстан), Казань, улица Академика Губкина, 50/1",
|
||||||
|
"status": "pending",
|
||||||
|
"notes": "заметки заметки заметки заметки заметки заметки заметки заметки заметки заметки заметки заметки заметки заметки заметки",
|
||||||
|
"created": "2025-01-18T17:46:10.388Z",
|
||||||
|
"updated": "2025-01-18T17:46:10.395Z",
|
||||||
|
"id": "678be8e211e62f4a61790cca"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phone": "4098765432105",
|
||||||
|
"carNumber": "О789РС777",
|
||||||
|
"carBody": 3,
|
||||||
|
"carColor": "красный",
|
||||||
|
"startWashTime": "2025-08-12T08:21:00.000Z",
|
||||||
|
"endWashTime": "2025-08-12T08:22:00.000Z",
|
||||||
|
"location": "55.78720449830353,49.12111640202319 Республика Татарстан (Татарстан), Казань, улица Пушкина, 5/43",
|
||||||
|
"status": "cancelled",
|
||||||
|
"notes": "Заказ отменен по запросу самого клиента",
|
||||||
|
"created": "2025-01-18T17:47:46.294Z",
|
||||||
|
"updated": "2025-01-18T17:47:46.295Z",
|
||||||
|
"id": "678be8e211e62f4a61790ccb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"phone": "+79876543210",
|
||||||
|
"carNumber": "Т123УХ716",
|
||||||
|
"carBody": 99,
|
||||||
|
"carColor": "чайная роза",
|
||||||
|
"startWashTime": "2025-01-11T11:21:00.000Z",
|
||||||
|
"endWashTime": "2025-01-12T11:22:00.000Z",
|
||||||
|
"location": "55.77063673480112,49.22182909159608 Республика Татарстан (Татарстан), Казань, Советский район, микрорайон Азино-2",
|
||||||
"status": "progress",
|
"status": "progress",
|
||||||
"phone": "79001234567",
|
"notes": "Клиент остался доволен, предложить в следующий раз акцию",
|
||||||
"location": "Казань, ул. Баумана, 43"
|
"created": "2025-01-18T17:55:05.691Z",
|
||||||
|
"updated": "2025-01-18T17:55:05.695Z",
|
||||||
|
"id": "678be8e211e62f4a61790ccc"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
11
server/routers/dry-wash/model/const.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
const orderStatus = {
|
||||||
|
CANCELLED: 'cancelled',
|
||||||
|
PROGRESS: 'progress',
|
||||||
|
PENDING: 'pending',
|
||||||
|
WORKING: 'working',
|
||||||
|
COMPLETE: 'complete',
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
orderStatus
|
||||||
|
}
|
||||||
@@ -1,26 +1,58 @@
|
|||||||
const { Schema, model } = require('mongoose')
|
const { Schema, model } = require('mongoose')
|
||||||
|
const { orderStatus } = require('./const')
|
||||||
|
|
||||||
const schema = new Schema({
|
const schema = new Schema({
|
||||||
startWashTime: {type: String, required: true},
|
phone: {
|
||||||
endWashTime: {type: String, required: true},
|
type: String,
|
||||||
orderDate: {type: String, required: true},
|
required: true
|
||||||
location: {type: String, required: true},
|
},
|
||||||
phone: {type: String, required: true},
|
carNumber: {
|
||||||
status: {type: String, required: true},
|
type: String,
|
||||||
carNumber: {type: String, required: true},
|
required: true
|
||||||
|
},
|
||||||
|
carBody: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
carColor: String,
|
||||||
|
startWashTime: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
endWashTime: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
enum: Object.values(orderStatus)
|
||||||
|
},
|
||||||
|
master: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: 'dry-wash-master'
|
||||||
|
},
|
||||||
|
notes: String,
|
||||||
created: {
|
created: {
|
||||||
type: Date, default: () => new Date().toISOString(),
|
type: Date,
|
||||||
|
default: () => new Date().toISOString(),
|
||||||
},
|
},
|
||||||
updated: {
|
updated: {
|
||||||
type: Date, default: () => new Date().toISOString(),
|
type: Date,
|
||||||
|
default: () => new Date().toISOString(),
|
||||||
},
|
},
|
||||||
master: {type: Schema.Types.ObjectId, ref: 'dry-wash-master'},
|
|
||||||
notes: String,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
schema.set('toJSON', {
|
schema.set('toJSON', {
|
||||||
virtuals: true,
|
virtuals: true,
|
||||||
versionKey: false,
|
versionKey: false,
|
||||||
|
transform(_doc, ret) {
|
||||||
|
delete ret._id
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
schema.virtual('id').get(function () {
|
schema.virtual('id').get(function () {
|
||||||
|
|||||||
251
server/routers/dry-wash/order.js
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
const mongoose = require("mongoose")
|
||||||
|
const router = require('express').Router()
|
||||||
|
const { MasterModel } = require('./model/master')
|
||||||
|
const { OrderModel } = require('./model/order')
|
||||||
|
const { orderStatus } = require('./model/const')
|
||||||
|
|
||||||
|
const isValidPhoneNumber = (value) => /^(\+)?\d{9,15}/.test(value)
|
||||||
|
const isValidCarNumber = (value) => /^[авекмнорстух][0-9]{3}[авекмнорстух]{2}[0-9]{2,3}$/i.test(value)
|
||||||
|
const isValidCarBodyType = (value) => typeof value === 'number' && value > 0 && value < 100
|
||||||
|
const isValidCarColor = (value) => value.length < 50 && /^[#a-z0-9а-я-\s,.()]+$/i.test(value)
|
||||||
|
const isValidISODate = (value) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:.\d{1,3})?Z$/.test(value)
|
||||||
|
|
||||||
|
const latitudeRe = /^(-?[1-8]?\d(?:\.\d{1,18})?|90(?:\.0{1,18})?)$/
|
||||||
|
const longitudeRe = /^(-?(?:1[0-7]|[1-9])?\d(?:\.\d{1,18})?|180(?:\.0{1,18})?)$/
|
||||||
|
const addressRe = /^[а-я0-9\s,.'-/()]*$/i
|
||||||
|
const isValidLocation = (value) => {
|
||||||
|
if (value.length > 200) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const [coordinates, address] = value.split(' ')
|
||||||
|
const [latitude, longitude] = coordinates.split(',')
|
||||||
|
return latitudeRe.test(latitude) && longitudeRe.test(longitude) && addressRe.test(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
const isValidOrderStatus = (value) => Object.values(orderStatus).includes(value)
|
||||||
|
const isValidOrderNotes = (value) => value.length < 500
|
||||||
|
|
||||||
|
const VALIDATION_MESSAGES = {
|
||||||
|
order: {
|
||||||
|
notFound: 'Order not found'
|
||||||
|
},
|
||||||
|
orderId: {
|
||||||
|
invalid: 'Valid order ID is required',
|
||||||
|
},
|
||||||
|
orderStatus: {
|
||||||
|
invalid: 'Invalid order status'
|
||||||
|
},
|
||||||
|
orderNotes: {
|
||||||
|
invalid: 'Invalid order notes'
|
||||||
|
},
|
||||||
|
master: {
|
||||||
|
notFound: 'Master not found'
|
||||||
|
},
|
||||||
|
masterId: {
|
||||||
|
invalid: 'Invalid master ID',
|
||||||
|
},
|
||||||
|
phoneNumber: {
|
||||||
|
required: 'Phone number is required',
|
||||||
|
invalid: 'Invalid phone number'
|
||||||
|
},
|
||||||
|
carNumber: {
|
||||||
|
required: 'Car number is required',
|
||||||
|
invalid: 'Invalid car number'
|
||||||
|
},
|
||||||
|
carBody: {
|
||||||
|
required: 'Car body type is required',
|
||||||
|
invalid: 'Invalid car body type'
|
||||||
|
},
|
||||||
|
carColor: {
|
||||||
|
invalid: 'Invalid car color'
|
||||||
|
},
|
||||||
|
washingBegin: {
|
||||||
|
required: 'Begin time of washing is required',
|
||||||
|
invalid: 'Invalid begin time of washing'
|
||||||
|
},
|
||||||
|
washingEnd: {
|
||||||
|
required: 'End time of washing is required',
|
||||||
|
invalid: 'Invalid end time of washing'
|
||||||
|
},
|
||||||
|
washingLocation: {
|
||||||
|
required: 'Location of washing is required',
|
||||||
|
invalid: 'Invalid location of washing'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
router.post('/create', async (req, res, next) => {
|
||||||
|
const bodyErrors = []
|
||||||
|
|
||||||
|
const { customer } = req.body
|
||||||
|
if (!customer.phone) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.phoneNumber.required)
|
||||||
|
} else if (!isValidPhoneNumber(customer.phone)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.phoneNumber.invalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { car } = req.body
|
||||||
|
if (!car.number) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.carNumber.required)
|
||||||
|
} else if (!isValidCarNumber(car.number)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.carNumber.invalid)
|
||||||
|
}
|
||||||
|
if (!car.body) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.carBody.required)
|
||||||
|
} else if (!isValidCarBodyType(car.body)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.carBody.invalid)
|
||||||
|
}
|
||||||
|
if (!isValidCarColor(car.color)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.carColor.invalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { washing } = req.body
|
||||||
|
if (!washing.begin) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.washingBegin.required)
|
||||||
|
} else if (!isValidISODate(washing.begin)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.washingBegin.invalid)
|
||||||
|
}
|
||||||
|
if (!washing.end) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.washingEnd.required)
|
||||||
|
} else if (!isValidISODate(washing.end)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.washingEnd.invalid)
|
||||||
|
}
|
||||||
|
if (!washing.location) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.washingLocation.required)
|
||||||
|
} else if (!isValidLocation(washing.location)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.washingLocation.invalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bodyErrors.length > 0) {
|
||||||
|
throw new Error(bodyErrors.join(', '))
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const order = await OrderModel.create({
|
||||||
|
phone: customer.phone,
|
||||||
|
carNumber: car.number,
|
||||||
|
carBody: car.body,
|
||||||
|
carColor: car.color,
|
||||||
|
startWashTime: washing.begin,
|
||||||
|
endWashTime: washing.end,
|
||||||
|
location: washing.location,
|
||||||
|
status: orderStatus.PROGRESS,
|
||||||
|
notes: '',
|
||||||
|
created: new Date().toISOString(),
|
||||||
|
})
|
||||||
|
|
||||||
|
res.status(200).send({ success: true, body: order })
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
next(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.get('/:id', async (req, res, next) => {
|
||||||
|
const { id } = req.params
|
||||||
|
if (!mongoose.Types.ObjectId.isValid(id)) {
|
||||||
|
throw new Error(VALIDATION_MESSAGES.orderId.invalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const order = await OrderModel.findById(id)
|
||||||
|
if (!order) {
|
||||||
|
throw new Error(VALIDATION_MESSAGES.order.notFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).send({ success: true, body: order })
|
||||||
|
} catch (error) {
|
||||||
|
next(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.patch('/:id', async (req, res, next) => {
|
||||||
|
const { id } = req.params
|
||||||
|
if (!mongoose.Types.ObjectId.isValid(id)) {
|
||||||
|
throw new Error(VALIDATION_MESSAGES.orderId.invalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
const bodyErrors = []
|
||||||
|
|
||||||
|
const { status } = req.body
|
||||||
|
if (status) {
|
||||||
|
if (!isValidOrderStatus(status)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.orderStatus.invalid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { master: masterId } = req.body
|
||||||
|
if (masterId) {
|
||||||
|
if (!mongoose.Types.ObjectId.isValid(masterId)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.masterId.invalid)
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const master = await MasterModel.findById(masterId)
|
||||||
|
if (!master) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.master.notFound)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
next(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { notes } = req.body
|
||||||
|
if (notes) {
|
||||||
|
if (!isValidOrderNotes(notes)) {
|
||||||
|
bodyErrors.push(VALIDATION_MESSAGES.orderNotes.invalid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bodyErrors.length > 0) {
|
||||||
|
throw new Error(bodyErrors.join(', '))
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const updateData = {}
|
||||||
|
if (status) {
|
||||||
|
updateData.status = status
|
||||||
|
}
|
||||||
|
if (masterId) {
|
||||||
|
updateData.master = masterId
|
||||||
|
}
|
||||||
|
if (notes) {
|
||||||
|
updateData.notes = notes
|
||||||
|
}
|
||||||
|
updateData.updated = new Date().toISOString()
|
||||||
|
|
||||||
|
const order = await OrderModel.findByIdAndUpdate(
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
{ new: true }
|
||||||
|
)
|
||||||
|
if (!order) {
|
||||||
|
throw new Error(VALIDATION_MESSAGES.order.notFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).send({ success: true, body: order })
|
||||||
|
} catch (error) {
|
||||||
|
next(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.delete('/:id', async (req, res, next) => {
|
||||||
|
const { id } = req.params
|
||||||
|
if (!mongoose.Types.ObjectId.isValid(id)) {
|
||||||
|
throw new Error(VALIDATION_MESSAGES.orderId.invalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const order = await OrderModel.findByIdAndDelete(id, {
|
||||||
|
new: true,
|
||||||
|
})
|
||||||
|
if (!order) {
|
||||||
|
throw new Error(VALIDATION_MESSAGES.order.notFound)
|
||||||
|
}
|
||||||
|
res.status(200).send({ success: true, body: order })
|
||||||
|
} catch (error) {
|
||||||
|
next(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
@@ -2,5 +2,6 @@ const router = require('express').Router();
|
|||||||
|
|
||||||
router.use('/performer', require('./dashboard-performer'))
|
router.use('/performer', require('./dashboard-performer'))
|
||||||
router.use('/auth', require('./auth'))
|
router.use('/auth', require('./auth'))
|
||||||
|
router.use('/landing', require('./landing'))
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
29
server/routers/freetracker/landing/index.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
const Router = require('express').Router;
|
||||||
|
|
||||||
|
const router = Router()
|
||||||
|
|
||||||
|
const values = {
|
||||||
|
'blocks': 'success',
|
||||||
|
'application': 'success'
|
||||||
|
}
|
||||||
|
|
||||||
|
const timer = (_req, _res, next) => {
|
||||||
|
setTimeout(() => next(), 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
router.use(timer)
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/blocks',
|
||||||
|
(req, res) =>
|
||||||
|
res.send(require(`./json/blocks-${values['blocks']}.json`))
|
||||||
|
)
|
||||||
|
|
||||||
|
router.post(
|
||||||
|
'/application',
|
||||||
|
(req, res) => {
|
||||||
|
res.send(require(`./json/application-${values['application']}.json`))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"body": { },
|
||||||
|
"errors": [
|
||||||
|
"Что-то пошло не так"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"body": { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"body": {
|
||||||
|
"blocks": []
|
||||||
|
},
|
||||||
|
"errors": [
|
||||||
|
"Что-то пошло не так"
|
||||||
|
]
|
||||||
|
}
|
||||||
22
server/routers/freetracker/landing/json/blocks-success.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"body": {
|
||||||
|
"blocks": [
|
||||||
|
{
|
||||||
|
"titleKey":"block1.title",
|
||||||
|
"textKey":"block1.subtitle",
|
||||||
|
"imageName":"truck1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"titleKey":"block2.title",
|
||||||
|
"textKey":"block2.subtitle",
|
||||||
|
"imageName":"truck2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"titleKey":"block3.title",
|
||||||
|
"textKey":"block3.subtitle",
|
||||||
|
"imageName":"truck3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,10 @@ router.get("/game-page", (request, response) => {
|
|||||||
response.send(require("./json/gamepage/success.json"));
|
response.send(require("./json/gamepage/success.json"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get("/update-like", (request, response) => {
|
||||||
|
response.send(require("./json/gamepage/success.json"));
|
||||||
|
});
|
||||||
|
|
||||||
router.get("/categories", (request, response) => {
|
router.get("/categories", (request, response) => {
|
||||||
response.send(require("./json/categories/success.json"));
|
response.send(require("./json/categories/success.json"));
|
||||||
});
|
});
|
||||||
@@ -20,4 +24,69 @@ router.get("/all-games", (request, response) => {
|
|||||||
response.send(require("./json/home-page-data/all-games.json"));
|
response.send(require("./json/home-page-data/all-games.json"));
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
// // Маршрут для обновления лайков
|
||||||
|
// router.post("/update-like", (request, response) => {
|
||||||
|
// const { username, likes } = request.body;
|
||||||
|
|
||||||
|
// // Эмулируем успешное обновление лайков
|
||||||
|
// console.log(`Лайки для пользователя ${username} обновлены до ${likes}`);
|
||||||
|
|
||||||
|
// response.status(200).json({
|
||||||
|
// success: true,
|
||||||
|
// message: `Лайки для пользователя ${username} обновлены до ${likes}`,
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
const fs = require("fs").promises;
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
// Path to JSON file
|
||||||
|
const commentsFilePath = path.join(__dirname, "./json/gamepage/success.json");
|
||||||
|
|
||||||
|
// Read JSON file
|
||||||
|
async function readComments() {
|
||||||
|
const data = await fs.readFile(commentsFilePath, "utf-8");
|
||||||
|
const parsedData = JSON.parse(data);
|
||||||
|
console.log("Прочитанные данные:", parsedData); // Логируем полученные данные
|
||||||
|
return parsedData;
|
||||||
|
}
|
||||||
|
// Write to JSON file
|
||||||
|
async function writeComments(data) {
|
||||||
|
await fs.writeFile(commentsFilePath, JSON.stringify(data, null, 2), "utf-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update likes route
|
||||||
|
router.post("/update-like", async (req, res) => {
|
||||||
|
const { username, likes } = req.body;
|
||||||
|
|
||||||
|
if (!username || likes === undefined) {
|
||||||
|
return res.status(400).json({ success: false, message: "Invalid input" });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await readComments();
|
||||||
|
const comment = data.data.comments.find((c) => c.username === username);
|
||||||
|
|
||||||
|
if (comment) {
|
||||||
|
comment.likes = likes;
|
||||||
|
await writeComments(data); // Сохраняем обновленные данные в файл
|
||||||
|
|
||||||
|
// Возвращаем актуализированные данные
|
||||||
|
res.status(200).json({
|
||||||
|
success: true,
|
||||||
|
message: "Likes updated successfully",
|
||||||
|
data: data.data, // Возвращаем актуализированные данные
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ success: false, message: "Comment not found" });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating likes:", error);
|
||||||
|
res.status(500).json({ success: false, message: "Server error" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
|
|||||||
@@ -8,14 +8,18 @@
|
|||||||
"price": 259,
|
"price": 259,
|
||||||
"old_price": 500,
|
"old_price": 500,
|
||||||
"image": "sales_game1",
|
"image": "sales_game1",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"title": "Red Solstice 2 Survivors",
|
"title": "Red Solstice 2 Survivors",
|
||||||
"price": 561,
|
"price": 561,
|
||||||
"image": "sales_game2",
|
"image": "sales_game2",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 3,
|
||||||
@@ -23,7 +27,9 @@
|
|||||||
"price": 820,
|
"price": 820,
|
||||||
"old_price": 1100,
|
"old_price": 1100,
|
||||||
"image": "new_game2",
|
"image": "new_game2",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 4,
|
"id": 4,
|
||||||
@@ -31,7 +37,9 @@
|
|||||||
"price": 990,
|
"price": 990,
|
||||||
"old_price": 1200,
|
"old_price": 1200,
|
||||||
"image": "leaders_game4",
|
"image": "leaders_game4",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 5,
|
"id": 5,
|
||||||
@@ -39,7 +47,9 @@
|
|||||||
"price": 1200,
|
"price": 1200,
|
||||||
"old_price": 2500,
|
"old_price": 2500,
|
||||||
"image": "leaders_game5",
|
"image": "leaders_game5",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 6,
|
"id": 6,
|
||||||
@@ -47,31 +57,39 @@
|
|||||||
"price": 600,
|
"price": 600,
|
||||||
"old_price": 890,
|
"old_price": 890,
|
||||||
"image": "leaders_game6",
|
"image": "leaders_game6",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"games2": [
|
"games2": [
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 7,
|
||||||
"title": "Alpha League",
|
"title": "Alpha League",
|
||||||
"price": 299,
|
"price": 299,
|
||||||
"image": "new_game1",
|
"image": "new_game1",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 8,
|
||||||
"title": "Sons Of The Forests",
|
"title": "Sons Of The Forests",
|
||||||
"price": 820,
|
"price": 820,
|
||||||
"old_price": 1100,
|
"old_price": 1100,
|
||||||
"image": "new_game2",
|
"image": "new_game2",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 9,
|
||||||
"title": "Pacific Drives",
|
"title": "Pacific Drives",
|
||||||
"price": 1799,
|
"price": 1799,
|
||||||
"image": "new_game3",
|
"image": "new_game3",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 4,
|
"id": 4,
|
||||||
@@ -79,7 +97,9 @@
|
|||||||
"price": 990,
|
"price": 990,
|
||||||
"old_price": 1200,
|
"old_price": 1200,
|
||||||
"image": "leaders_game4",
|
"image": "leaders_game4",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 5,
|
"id": 5,
|
||||||
@@ -87,7 +107,9 @@
|
|||||||
"price": 1200,
|
"price": 1200,
|
||||||
"old_price": 2500,
|
"old_price": 2500,
|
||||||
"image": "leaders_game5",
|
"image": "leaders_game5",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 6,
|
"id": 6,
|
||||||
@@ -95,31 +117,39 @@
|
|||||||
"price": 600,
|
"price": 600,
|
||||||
"old_price": 890,
|
"old_price": 890,
|
||||||
"image": "leaders_game6",
|
"image": "leaders_game6",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"games3": [
|
"games3": [
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 10,
|
||||||
"title": "Elden Ring",
|
"title": "Elden Ring",
|
||||||
"price": 3295,
|
"price": 3295,
|
||||||
"old_price": 3599,
|
"old_price": 3599,
|
||||||
"image": "leaders_game2",
|
"image": "leaders_game2",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 11,
|
||||||
"title": "Counter-Strike 2",
|
"title": "Counter-Strike 2",
|
||||||
"price": 479,
|
"price": 479,
|
||||||
"image": "leaders_game1",
|
"image": "leaders_game1",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 12,
|
||||||
"title": "PUBG: BATTLEGROUNDS",
|
"title": "PUBG: BATTLEGROUNDS",
|
||||||
"price": 199,
|
"price": 199,
|
||||||
"image": "leaders_game3",
|
"image": "leaders_game3",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 4,
|
"id": 4,
|
||||||
@@ -127,7 +157,9 @@
|
|||||||
"price": 990,
|
"price": 990,
|
||||||
"old_price": 1200,
|
"old_price": 1200,
|
||||||
"image": "leaders_game4",
|
"image": "leaders_game4",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 5,
|
"id": 5,
|
||||||
@@ -135,7 +167,9 @@
|
|||||||
"price": 1200,
|
"price": 1200,
|
||||||
"old_price": 2500,
|
"old_price": 2500,
|
||||||
"image": "leaders_game5",
|
"image": "leaders_game5",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 6,
|
"id": 6,
|
||||||
@@ -143,7 +177,9 @@
|
|||||||
"price": 600,
|
"price": 600,
|
||||||
"old_price": 890,
|
"old_price": 890,
|
||||||
"image": "leaders_game6",
|
"image": "leaders_game6",
|
||||||
"os": "windows"
|
"os": "windows",
|
||||||
|
"fav1": "star1",
|
||||||
|
"fav2": "star2"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,35 @@
|
|||||||
{
|
{
|
||||||
"success": true,
|
"success": true,
|
||||||
"data": {
|
"data": {
|
||||||
"comments": [
|
"comments": [
|
||||||
{
|
{
|
||||||
"username": "Пользователь1",
|
"username": "Пользователь1",
|
||||||
"text": "Текст комментария 1"
|
"text": "Текст комментария 1",
|
||||||
},
|
"likes": 9,
|
||||||
{
|
"rating": 8,
|
||||||
"username": "Пользователь2",
|
"date": "2025-03-01T10:00:00Z"
|
||||||
"text": "Текст комментария 2"
|
},
|
||||||
},
|
{
|
||||||
{
|
"username": "Пользователь2",
|
||||||
"username": "Пользователь3",
|
"text": "Текст комментария 2",
|
||||||
"text": "Текст комментария 3"
|
"likes": 7,
|
||||||
},
|
"rating": 7,
|
||||||
{
|
"date": "2025-01-01T10:00:00Z"
|
||||||
"username": "Пользователь4",
|
},
|
||||||
"text": "Текст комментария 4"
|
{
|
||||||
}
|
"username": "Пользователь3",
|
||||||
]
|
"text": "Текст комментария 3",
|
||||||
}
|
"likes": 5,
|
||||||
|
"rating": 3,
|
||||||
|
"date": "2025-02-01T10:00:00Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username": "Пользователь4",
|
||||||
|
"text": "Текст комментария 4",
|
||||||
|
"likes": 15,
|
||||||
|
"rating": 2,
|
||||||
|
"date": "2025-12-01T10:00:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
BIN
server/routers/old/bushou/images.tar
Normal file
|
Before Width: | Height: | Size: 377 B |
|
Before Width: | Height: | Size: 470 B |
|
Before Width: | Height: | Size: 578 B |
|
Before Width: | Height: | Size: 481 B |
|
Before Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 593 B |
|
Before Width: | Height: | Size: 539 B |
|
Before Width: | Height: | Size: 414 B |
|
Before Width: | Height: | Size: 414 B |
|
Before Width: | Height: | Size: 739 B |
|
Before Width: | Height: | Size: 686 B |
|
Before Width: | Height: | Size: 750 B |
|
Before Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 706 B |
|
Before Width: | Height: | Size: 776 B |
|
Before Width: | Height: | Size: 628 B |
|
Before Width: | Height: | Size: 742 B |
|
Before Width: | Height: | Size: 853 B |
|
Before Width: | Height: | Size: 911 B |
|
Before Width: | Height: | Size: 601 B |
|
Before Width: | Height: | Size: 648 B |
|
Before Width: | Height: | Size: 709 B |
|
Before Width: | Height: | Size: 442 B |
|
Before Width: | Height: | Size: 858 B |
|
Before Width: | Height: | Size: 718 B |
|
Before Width: | Height: | Size: 1015 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 811 B |
|
Before Width: | Height: | Size: 872 B |
|
Before Width: | Height: | Size: 659 B |
|
Before Width: | Height: | Size: 767 B |
|
Before Width: | Height: | Size: 719 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 812 B |
|
Before Width: | Height: | Size: 760 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 955 B |
|
Before Width: | Height: | Size: 908 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1016 B |
|
Before Width: | Height: | Size: 997 B |
|
Before Width: | Height: | Size: 856 B |
|
Before Width: | Height: | Size: 693 B |
|
Before Width: | Height: | Size: 711 B |
|
Before Width: | Height: | Size: 766 B |
|
Before Width: | Height: | Size: 952 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 843 B |
|
Before Width: | Height: | Size: 951 B |
|
Before Width: | Height: | Size: 967 B |
|
Before Width: | Height: | Size: 923 B |
|
Before Width: | Height: | Size: 725 B |
|
Before Width: | Height: | Size: 935 B |
|
Before Width: | Height: | Size: 820 B |
|
Before Width: | Height: | Size: 841 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1006 B |
|
Before Width: | Height: | Size: 949 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 930 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 782 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 855 B |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 809 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 837 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 760 B |
|
Before Width: | Height: | Size: 1020 B |
|
Before Width: | Height: | Size: 1015 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |