183 lines
7.4 KiB
JavaScript
183 lines
7.4 KiB
JavaScript
/**
|
|||
|
|
* Lightweight local mock API for UI preview when Postgres isn't configured.
|
||
|
|
* Serves the same shape as Nest public endpoints from seed defaults.
|
||
|
|
*/
|
||
|
|
import http from "node:http";
|
||
|
|
|
||
|
|
const sections = {
|
||
|
|
hero: {
|
||
|
|
eyebrow: "گروه توسعه نرمافزار",
|
||
|
|
location: "[ تأسیس ۱۴۰۰ — تهران / دورکاری ]",
|
||
|
|
loaderTitle: "هوشافزار منتک",
|
||
|
|
lines: [
|
||
|
|
"در هوشافزار منتک",
|
||
|
|
"بهترین نرمافزارها و خدمات",
|
||
|
|
"متناسب با کسبوکار شما پیشنهاد میشود",
|
||
|
|
],
|
||
|
|
highlightWord: "هوشافزار منتک",
|
||
|
|
highlightWords: ["هوشافزار منتک"],
|
||
|
|
body: "منتک یک تیم مهندسی ارشد است که پلتفرمهای وب، اپلیکیشن موبایل و زیرساخت ابری را برای کسبوکارهایی میسازد که نمیخواهند معمولی باشند.",
|
||
|
|
cta: "مشاهده نمونهکارها",
|
||
|
|
badge: "مهندسی منتک • از ۱۴۰۰ •",
|
||
|
|
coords: "تهران، ایران",
|
||
|
|
projectsLabel: "بیش از ۱۲۰ پروژه تحویلشده",
|
||
|
|
},
|
||
|
|
marquee: {
|
||
|
|
items: [
|
||
|
|
"آبشده همکار",
|
||
|
|
"آبشده خانگی",
|
||
|
|
"فروشگاه آنلاین",
|
||
|
|
"سامانه بد و بس",
|
||
|
|
"سامانه فوری سند",
|
||
|
|
"مدیریت ارتباط با مشتری CRM",
|
||
|
|
"هوش مصنوعی",
|
||
|
|
],
|
||
|
|
},
|
||
|
|
manifesto: {
|
||
|
|
tag: "ما که هستیم",
|
||
|
|
words: [
|
||
|
|
{ text: "ما" },
|
||
|
|
{ text: "نرمافزاری" },
|
||
|
|
{ text: "میسازیم", volt: true },
|
||
|
|
{ text: "که" },
|
||
|
|
{ text: "تفاوت" },
|
||
|
|
{ text: "ایجاد" },
|
||
|
|
{ text: "کند." },
|
||
|
|
{ text: "منتک", volt: true },
|
||
|
|
],
|
||
|
|
body: "استراتژی، طراحی و مهندسی زیر یک سقف — با دقت وسواسگونه نسبت به کیفیت و عملکرد.",
|
||
|
|
},
|
||
|
|
services: {
|
||
|
|
tag: "چه میکنیم",
|
||
|
|
items: [
|
||
|
|
{ n: "۰۱", title: "استراتژی محصول", desc: "ایدههای مبهم را به نقشه راه معتبر تبدیل میکنیم.", tags: ["کشف محصول", "پژوهش کاربر", "نقشه راه", "MVP"] },
|
||
|
|
{ n: "۰۲", title: "مهندسی وب", desc: "پلتفرمهای وب سریع و مقیاسپذیر.", tags: ["Nuxt", "NestJS", "Node.js", "React"] },
|
||
|
|
{ n: "۰۳", title: "اپلیکیشن موبایل", desc: "تجربهٔ بومیگونه روی iOS و Android.", tags: ["React Native", "Flutter"] },
|
||
|
|
{ n: "۰۴", title: "ابرو DevOps", desc: "استقرار خودکار، امنیت و مانیتورینگ.", tags: ["AWS / GCP", "کوبرنتیز", "CI/CD"] },
|
||
|
|
{ n: "۰۵", title: "هوش مصنوعی و داده", desc: "هوش مصنوعی کاربردی و خطوط لوله داده.", tags: ["LLM", "اتوماسیون"] },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
work: {
|
||
|
|
tag: "نمونه کارها",
|
||
|
|
items: [
|
||
|
|
{ n: "۰۱", title: "پالسبورد", cat: "پلتفرم تحلیلی فینتک", year: "۱۴۰۳" },
|
||
|
|
{ n: "۰۲", title: "ایرولوپ", cat: "نرمافزار لجستیک", year: "۱۴۰۳" },
|
||
|
|
{ n: "۰۳", title: "مدسینک", cat: "پلتفرم هلثتک", year: "۱۴۰۲" },
|
||
|
|
{ n: "۰۴", title: "نوواپی", cat: "زیرساخت پرداخت", year: "۱۴۰۲" },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
process: {
|
||
|
|
tag: "چگونه کار میکنیم",
|
||
|
|
steps: [
|
||
|
|
{ n: "۰۱", title: "کشف", desc: "کارگاه، پژوهش و همراستایی روی نتایج." },
|
||
|
|
{ n: "۰۲", title: "طراحی", desc: "سیستمها، جریانها و رابطهای ساده." },
|
||
|
|
{ n: "۰۳", title: "توسعه", desc: "مهندسان ارشد و نرمافزار آمادهٔ تولید." },
|
||
|
|
{ n: "۰۴", title: "استقرار و مقیاس", desc: "CI/CD، مانیتورینگ و رشد پایدار." },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
stats: {
|
||
|
|
items: [
|
||
|
|
{ value: 120, suffix: "+", label: "پروژه تحویلشده" },
|
||
|
|
{ value: 40, suffix: "+", label: "مشتری" },
|
||
|
|
{ value: 15, suffix: "", label: "مهندس و طراح" },
|
||
|
|
{ value: 98, suffix: "%", label: "ماندگاری مشتری" },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
team: {
|
||
|
|
tag: "تیم",
|
||
|
|
headline: "با جمع ما آشنا شوید",
|
||
|
|
body: "تیمی جمعوجور از متخصصان محصول، طراحی و مهندسی.",
|
||
|
|
members: [
|
||
|
|
{ name: "علی رضایی", role: "مدیرعامل و همبنیانگذار" },
|
||
|
|
{ name: "سارا محمدی", role: "مدیر فنی و همبنیانگذار" },
|
||
|
|
{ name: "مریم حسینی", role: "سرپرست طراحی" },
|
||
|
|
{ name: "رضا کریمی", role: "مهندس ارشد" },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
footer: {
|
||
|
|
tag: "تماس",
|
||
|
|
marquee: ["پروژهای در ذهن دارید؟", "سلام کنید", "با هم کار کنیم"],
|
||
|
|
cta: "شروع همکاری",
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
const site = {
|
||
|
|
settings: {
|
||
|
|
brandName: "منتک",
|
||
|
|
tagline: "گروه توسعه نرمافزار",
|
||
|
|
email: "hello@montech.ir",
|
||
|
|
phone: "+98 21 0000 0000",
|
||
|
|
address: "تهران، ایران",
|
||
|
|
timezone: "Asia/Tehran",
|
||
|
|
logoUrl: null,
|
||
|
|
socials: [
|
||
|
|
{ label: "لینکدین", url: "https://linkedin.com" },
|
||
|
|
{ label: "گیتهاب", url: "https://github.com" },
|
||
|
|
],
|
||
|
|
},
|
||
|
|
sections,
|
||
|
|
pages: [
|
||
|
|
{
|
||
|
|
key: "home",
|
||
|
|
title: "خانه",
|
||
|
|
seo: {
|
||
|
|
title: "منتک — گروه توسعه نرمافزار",
|
||
|
|
description: "منتک پلتفرمهای وب، اپلیکیشن موبایل و زیرساخت ابری میسازد.",
|
||
|
|
canonical: "http://localhost:3000/",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
],
|
||
|
|
};
|
||
|
|
|
||
|
|
const blog = [
|
||
|
|
{
|
||
|
|
id: "1",
|
||
|
|
slug: "welcome-to-montech",
|
||
|
|
title: "به منتک خوش آمدید",
|
||
|
|
excerpt: "ما نرمافزاری میسازیم که واقعاً کار میکند.",
|
||
|
|
publishedAt: new Date().toISOString(),
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
const port = Number(process.env.PORT || 3050);
|
||
|
|
|
||
|
|
const server = http.createServer((req, res) => {
|
||
|
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
||
|
|
res.setHeader("Access-Control-Allow-Methods", "GET,OPTIONS");
|
||
|
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
||
|
|
if (req.method === "OPTIONS") {
|
||
|
|
res.writeHead(204);
|
||
|
|
res.end();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const url = req.url || "/";
|
||
|
|
const json = (data, code = 200) => {
|
||
|
|
res.writeHead(code, { "Content-Type": "application/json; charset=utf-8" });
|
||
|
|
res.end(JSON.stringify(data));
|
||
|
|
};
|
||
|
|
|
||
|
|
if (url === "/api/health") return json({ ok: true, mock: true });
|
||
|
|
if (url === "/api/public/site") return json(site);
|
||
|
|
if (url === "/api/public/blog") return json(blog);
|
||
|
|
if (url.startsWith("/api/public/blog/")) {
|
||
|
|
const slug = decodeURIComponent(url.split("/").pop() || "");
|
||
|
|
const post = blog.find((p) => p.slug === slug);
|
||
|
|
return post
|
||
|
|
? json({ ...post, content: "محتوای نمونه برای پیشنمایش لوکال." })
|
||
|
|
: json({ message: "Not found" }, 404);
|
||
|
|
}
|
||
|
|
if (url === "/api/public/gallery") return json([]);
|
||
|
|
if (url.startsWith("/api/public/pages/")) {
|
||
|
|
const key = decodeURIComponent(url.split("/").pop() || "");
|
||
|
|
const page = site.pages.find((p) => p.key === key);
|
||
|
|
return page ? json(page) : json({ message: "Not found" }, 404);
|
||
|
|
}
|
||
|
|
|
||
|
|
json({ message: `Mock API — no route for ${url}` }, 404);
|
||
|
|
});
|
||
|
|
|
||
|
|
server.listen(port, "127.0.0.1", () => {
|
||
|
|
console.log(`[mock-api] http://127.0.0.1:${port}`);
|
||
|
|
});
|