This commit is contained in:
2023-12-01 14:43:18 +05:00
parent b8cec033bb
commit edcd51599c
33 changed files with 2669 additions and 236 deletions
+3 -1
View File
@@ -1 +1,3 @@
PORT=3000
PORT=3000
MONGO_URI=mongodb://root:p62Z!ZatgY25@194.26.138.94:27017/
JWT_SECRET=yDcdWJgvlj2bJAuovYfQHTvtc3U9xQPw
+7 -1
View File
@@ -11,12 +11,18 @@
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2"
"express": "^4.18.2",
"mongoose": "^8.0.1",
"multer": "^1.4.5-lts.1",
"sharp": "^0.32.6",
"uuid": "^9.0.1"
},
"devDependencies": {
"@types/cors": "^2.8.15",
"@types/express": "^4.17.20",
"@types/multer": "^1.4.11",
"@types/node": "^20.8.10",
"@types/uuid": "^9.0.7",
"nodemon": "^3.0.1",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
+16
View File
@@ -0,0 +1,16 @@
import { connect } from "mongoose";
async function connectDB() {
try {
await connect(process.env.MONGO_URI!, { dbName: "estate" });
console.log("MongoDB connected...");
} catch (error) {
if (error instanceof Error) {
console.error(error.message);
}
process.exit(1);
}
}
export default connectDB;
-62
View File
@@ -1,62 +0,0 @@
const db = {
products: [
{
id: 1,
name: "Смартфон POCO C51 64 ГБ",
price: 6499,
image:
"https://c.dns-shop.ru/thumb/st1/fit/500/500/256e8ece17c46e683dbe0facd94c5e69/5c108f7da6e5886d4d32d723d0e24ad0151bd790d7941374c56d9d8e9718d9f6.jpg.webp",
colors: ["black", "blue", "green"],
popularity: 3,
desc: `Смартфон POCO C51 64 ГБ предлагает функции, необходимые для разговоров по мобильной связи, общения в социальных сетях и мультимедийных развлечений. Он выполнен в компактном пластиковом корпусе с обтекаемыми гранями и тыловой панелью голубого цвета. Экран IPS диагональю 6.52 дюйма обеспечивает интуитивное управление и реалистичное изображение.
Высокая производительность системы достигается благодаря 8-ядерному процессору MediaTek Helio G36 и 2 ГБ оперативной памяти. На тыловой панели установлена сдвоенная камера 8+0.3 Мп с автофокусом и светодиодной вспышкой для реалистичной съемки фотографий и видео. Фронтальная камера 5 Мп позволяет делать селфи и общаться по видеосвязи. Встроенный сканер отпечатков пальцев гарантирует простую и безопасную разблокировку устройства. За автономность смартфона POCO C51 отвечает аккумуляторная батарея емкостью 5000 мА*ч.`,
},
{
id: 2,
name: "Смартфон realme C30s 64 ГБ",
price: 6999,
image:
"https://c.dns-shop.ru/thumb/st1/fit/500/500/774bc3d792cbcab34769a178c61686f2/cb157601cb15ceac4756053ed94ff8a9b2598f461f86084ca57090724cd9214e.jpg.webp",
colors: ["black", "blue"],
popularity: 3,
desc: `Смартфон realme C30S имеет тонкий корпус черного цвета и вес 186 г, что облегчает эксплуатацию. Для разграничения звонков можно установить две SIM-карты. Модель оснащена мощным производительным 8-ядерным процессором, который обеспечивает бесперебойную и быструю работу. Широкий экран диагональю 6.5 дюймов обеспечивает комфортную игру и просмотр фильмов. IPS-дисплей поддерживает насыщенную и яркую цветопередачу.
Смартфон realme C30S имеет 64 ГБ памяти, чего достаточно для хранения необходимой информации. Батарея емкостью 5000 мА*ч позволяет долгое время играть или смотреть видео без подзарядки. Даже при остатке 5% можно включить режим энергосбережения, чтобы оставаться на связи. Для быстрой разблокировки экрана на боковой стороне корпуса есть сканер отпечатка пальцев.`,
},
{
id: 3,
name: "Смартфон Xiaomi Redmi A2+ 64 ГБ",
price: 7499,
image:
"https://c.dns-shop.ru/thumb/st1/fit/500/500/43aa8e3640bdc253df179db3eecd9cd3/b5926e67b994494fd67cdf8b75d9db0bad7bc5f4bc9839937ffc3daf7053abdc.jpg.webp",
colors: ["black", "blue", "green"],
popularity: 5,
desc: `Смартфон Xiaomi Redmi A2+ в голубом цвете корпуса поддерживает установку двух SIM-карт, чтобы вы могли разграничить личные и деловые звонки. Экран обладает диагональю 6.52” и разрешением 1600x720 для комфортного просмотра любого контента. Закаленное стекло способствует защите дисплея от мелких повреждений: потертостей и царапин. 8-ядерный процессор MediaTek Helio G36 вместе с 3 ГБ оперативной памяти обеспечивает достаточный уровень производительности для запуска мобильных приложений и работы в режиме многозадачности.
Смартфон Xiaomi Redmi A2+ имеет 64 ГБ встроенной памяти и предусматривает отдельный слот, в который можно установить карту памяти емкостью до 1 ТБ. Тыловая камера представлена двумя модулями 8+0.3 Мп для съемки детализированных и красочных снимков. Двойная светодиодная вспышка позволит проводить фотосъемку в условиях плохой освещенности. Для создания селфи предусмотрена 5-мегапиксельная фронтальная камера. Литий-полимерный аккумулятор емкостью 5000 мАч позволит устройству проработать в режиме разговора до 28 ч.`,
},
{
id: 4,
name: "Смартфон Infinix SMART 7 HD 64 ГБ",
price: 6999,
image:
"https://c.dns-shop.ru/thumb/st1/fit/500/500/746f2653ecd116f0b3f5bc3e1ce6040f/8a0c3b832d57c5ea8faae411b3afd708403516a91e448da83efb13ef5d6696bd.jpg.webp",
colors: ["white", "black", "blue"],
popularity: 2,
desc: `Смартфон Infinix Smart 7 HD 64 ГБ выполнен в корпусе белого цвета и оснащен дисплеем 6.6 дюйма. Панель IPS (1612x720 пикселей) воспроизводит реалистичное изображение с насыщенными и яркими цветами. Плавная и бесперебойная работа аппаратной платформы при выполнении различных задач обеспечивается благодаря процессору Unisoc SC9863A и 2 ГБ оперативной памяти.
Infinix Smart 7 HD оснащен слотами для установки двух карт SIM и карты памяти microSD. Основная камера 8+0.3 Мп предназначена для создания детализированных фотографий и видео. На передней стороне в каплевидном вырезе расположена камера 5 Мп, которая позволяет общаться по видеосвязи и делать селфи. В устройстве реализованы беспроводные интерфейсы Wi-Fi и Bluetooth. Аккумулятор 5000 мА*ч гарантирует до 32 часов работы смартфона без подзарядки в режиме просмотра видео.`,
},
{
id: 5,
name: "Смартфон Tecno POP 7 64 ГБ",
price: 8499,
image:
"https://c.dns-shop.ru/thumb/st4/fit/500/500/8278fc2e0c767175a1bc3fe505284ca7/88c242ac48d30b2977c1802c8ad41f63484c9e2bb3a0976befc7d0bb7caa6c6e.jpg.webp",
colors: ["black", "blue", "purple"],
popularity: 4,
desc: `Смартфон Tecno POP 7 в пластиковом корпусе голубого цвета обладает многоуровневой биометрической защитой. Она запускает идентификацию личности по отпечатку и чертам лица. Процессор с 8 ядрами и 2 ГБ оперативной памяти выступают гарантом быстрого запуска приложений и отклика на пожелания пользователя. Энергия аккумулятора емкостью 5000 мАч рассчитана на длительное использование функционала.
Смартфон Tecno POP 7 оснащен основной камерой с разрешением матрицы 8 Мп и светодиодной вспышкой. Кадры получатся насыщенными даже в условиях слабого освещения. В 6.6-дюймовый экран интегрирован датчик, который анализирует уровень внешнего освещения. Он автоматически уменьшает или повышает яркость для комфортного просмотра контента.`,
},
],
};
export default db;
+7 -3
View File
@@ -1,6 +1,11 @@
import "dotenv/config";
import connectDB from "./config/db";
import express, { json } from "express";
import cors from "cors";
import uploadRouter from "./routes/upload";
import projectsRouter from "./routes/projects";
await connectDB();
const app = express();
const port = process.env.PORT || 3000;
@@ -8,9 +13,8 @@ const port = process.env.PORT || 3000;
app.use(json());
app.use(cors());
app.get("/", (_req, res) => {
res.json({ ok: 1 });
});
app.use("/upload", uploadRouter);
app.use("/projects", projectsRouter);
app.listen(port, () => {
console.log(`Server is listening on port ${port}`);
+42
View File
@@ -0,0 +1,42 @@
import { Schema, model } from "mongoose";
const projectSchema = new Schema(
{
name: {
type: String,
required: true,
},
company: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
image: {
type: String,
required: true,
},
stage: {
type: Number,
default: 1,
},
releaseYear: {
type: Number,
required: true,
},
devices: {
type: Array,
},
},
{
timestamps: true,
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
);
const Project = model("Project", projectSchema);
export default Project;
+76
View File
@@ -0,0 +1,76 @@
import { Router } from "express";
import Project from "../models/Project";
const router = Router();
router.get("/", async (_req, res) => {
try {
const projects = await Project.find().sort({ createdAt: -1 });
return res.json(projects);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.get("/:id", async (req, res) => {
try {
const project = await Project.findById(req.params.id);
return res.json(project);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.post("/", async (req, res) => {
try {
const project = await Project.create(req.body);
return res.json(project);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.put("/:id", async (req, res) => {
console.log(req.body);
try {
const project = await Project.findByIdAndUpdate(req.params.id, req.body, {
upsert: true,
new: true,
});
console.log("updated", project);
return res.json(project);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.delete("/:id", async (req, res) => {
console.log(req.body);
try {
const project = await Project.findByIdAndDelete(req.params.id);
return res.json(project);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
const projectsRouter = router;
export default projectsRouter;
+61
View File
@@ -0,0 +1,61 @@
import { Router } from "express";
import multer, { memoryStorage } from "multer";
import sharp from "sharp";
import fs from "fs";
import { v4 as uuidv4 } from "uuid";
const router = Router();
const upload = multer({
dest: "uploads/",
storage: memoryStorage(),
fileFilter: (_req, file, cb) => {
if (file.mimetype.split("/")[0] === "image") {
cb(null, true);
} else {
cb(new Error("Only images are allowed!"));
}
},
});
router.get("/:file", (req, res) => {
const fileName = req.params.file;
try {
const readStream = fs.createReadStream(`uploads/${fileName}`);
readStream.pipe(res);
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
router.post("/", upload.single("file"), async (req, res) => {
if (!req.file) {
return res.json({ error: "req.file" });
}
try {
const filename = `${uuidv4()}.jpg`;
await sharp(req.file.buffer)
.resize({
width: 512,
height: 512,
fit: "inside",
withoutEnlargement: true,
})
.jpeg({ quality: 90 })
.toFile(`uploads/${filename}`);
return res.json({ file: `http://192.168.1.170:3000/upload/${filename}` });
} catch (error) {
if (error instanceof Error) {
return res.json({ error: error.message });
}
}
});
const uploadRouter = router;
export default uploadRouter;
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

+1473
View File
File diff suppressed because it is too large Load Diff