Merge remote-tracking branch 'origin/feature/ui-updates-v1' into new-one
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
/**
|
||||
* مختصات پروژههای گروه ساختمانی آرامش — برگرفته از شیت «Sheet1.csv».
|
||||
*
|
||||
* دو نکتهی دادهای که در همانجا حل میشوند:
|
||||
* ۱) ستونهای neshan_url و google_maps_url در شیت فقط برچسب بودند
|
||||
* («Open in Neshan») و نشانی واقعی نداشتند؛ پس پیوندها از روی مختصات
|
||||
* ساخته میشوند که الگوی تثبیتشدهی هر دو سرویس است.
|
||||
* ۲) ستون توضیحات خالی است؛ متن پیشفرض در لایهی رابط کاربری جایگزین میشود.
|
||||
*/
|
||||
|
||||
import type { Project, ProjectCardItem } from './site'
|
||||
|
||||
export type MapProject = {
|
||||
id: number
|
||||
name: string
|
||||
/** سال شمسی — ممکن است خالی باشد */
|
||||
year: string
|
||||
/** پروژهی در جریان (ستون new شیت) */
|
||||
isNew: boolean
|
||||
lat: number
|
||||
lng: number
|
||||
description: string
|
||||
}
|
||||
|
||||
/** مرکز پیشفرض نقشه — اصفهان */
|
||||
export const ISFAHAN_CENTER: [number, number] = [51.6675, 32.6539]
|
||||
|
||||
type CsvRow = { name: string; year: string; isNew: boolean; lat: number; lng: number; description: string }
|
||||
|
||||
/**
|
||||
* ستونهای برچسبی شیت حذف شدهاند (نشانی واقعی نداشتند) و ستون توضیحات به
|
||||
* description نگاشت شده است. ترتیب: name,year,new,lat,lng,description
|
||||
*/
|
||||
const RAW_CSV = `name,year,new,lat,lng,description
|
||||
پروژه سروش,1381,no,32.6662842,51.701735,
|
||||
چهرازی-زیتون,1383,no,32.6700428,51.69985,
|
||||
جعفریان,1384,no,32.6669259,51.701085,
|
||||
بهار,1385,yes,32.6468963,51.6899119,
|
||||
حسن مرادی,1385,no,32.6704278,51.6985567,
|
||||
کوثر,1386,no,32.6522044,51.6856474,
|
||||
صبا,1387,no,32.6541363,51.6847828,
|
||||
پورمعالی - بهشت,1387,no,32.6500402,51.6919823,
|
||||
2 پروژه- فردوس,1388,no,32.6614576,51.706429,
|
||||
ارم,1388,no,32.6563712,51.710694,
|
||||
سینا,1388,no,32.6469299,51.6855403,
|
||||
مسجد سید,1389,yes,32.6669953,51.6557085,
|
||||
هفده شهریور,1389,yes,32.7249998,51.6543819,
|
||||
آرامش رفیع زاده,1390,no,32.6467107,51.6873398,
|
||||
بن بست شریعت,1390,yes,32.6459939,51.6897556,
|
||||
قصر - یاسین,1390,no,32.6663549,51.7065512,
|
||||
پردیس,1390,no,32.6518961,51.6973621,
|
||||
آرامش حکیم,1392,no,32.6426783,51.6813477,
|
||||
آرامش دخانیات,1393,no,32.6411924,51.6797555,
|
||||
بهشتی فرشادی,1393,no,32.6531989,51.6790984,
|
||||
کاکتوس,1394,no,32.6486747,51.6859003,
|
||||
آرامش - صیاد,1395,no,32.6486798,51.712659,
|
||||
کوثر,1395,yes,32.6506204,51.6344053,
|
||||
آرامش - بوعلی 1,1396,no,32.6455156,51.6918424,
|
||||
میرزا نصیر,1396,no,32.668195,51.7173079,
|
||||
نیکان,1396,yes,32.6504663,51.6355982,
|
||||
آرامش-رسا,1397,no,32.6522126,51.6857297,
|
||||
نگین,1397,yes,32.6507084,51.6313395,
|
||||
آرامش - بوعلی 2,1398,no,32.645391,51.6917828,
|
||||
آرامش استاد همایی,1398,no,32.6563505,51.691988,
|
||||
آرامش صدر,1398,no,32.6469234,51.6826176,
|
||||
آرامش - سپهسالار,1399,yes,32.6259658,51.7080268,
|
||||
آرامش- صدر,1399,no,32.6469205,51.6829887,
|
||||
آرامش - سنایی,1400,yes,32.6973339,51.6194128,
|
||||
مغازه لباس فروشی,1400,no,32.6516965,51.7020497,
|
||||
آرامش - آتشگاه,1401,yes,32.6547584,51.6319244,
|
||||
آرامش - بزرگمهر,1401,no,32.651381,51.6993575,
|
||||
آرامش - سعدی,1401,yes,32.6970115,51.6196909,
|
||||
آرامش - صمدیه لباف,1401,yes,32.6716585,51.6359248,
|
||||
آرامش 2,1401,yes,32.6505704,51.6337863,
|
||||
آرامش 5 رمضان,1401,yes,32.6674407,51.6568827,
|
||||
آرامش احمدآباد,1401,no,32.6626101,51.6969828,
|
||||
تجاری آتشگاه,1401,yes,32.6515087,51.6033278,
|
||||
آرامش - شهیدان,1402,yes,32.6854968,51.6171964,
|
||||
آرامش خواجو,1402,no,32.6419187,51.6831873,
|
||||
آرامش- اداری ابوالحسن,1402,no,32.6453749,51.6915519,
|
||||
آرامش - انقلاب,1403,yes,32.719769,51.645921,
|
||||
آرامش - شریف,1404,no,32.6473319,51.6955996,
|
||||
آرامش - کهندژ,1404,yes,32.6649497,51.630077,
|
||||
آرامش جی,1404,no,32.6610717,51.7110184,
|
||||
آرامش - بابک,1405,yes,32.674076,51.6368204,
|
||||
آرامش - شمس آبادی,1405,yes,32.6560844,51.664771,
|
||||
آرامش - میرزاطاهر 3,1405,yes,32.6495532,51.6178643,
|
||||
آرامش - وحدت,1405,yes,32.6537564,51.6197007,
|
||||
آرامش پروین,1405,no,32.6618223,51.7098152,
|
||||
خلیفه سلطانی,1405,yes,32.7035398,51.6223296,
|
||||
آرامش - میرزا طاهر 5,1406,yes,32.6517244,51.6202975,
|
||||
آرامش - میرزاطاهر 6,1408,yes,32.6505366,51.6267342,
|
||||
آرامش - میرزا طاهر 4,,yes,32.6510328,51.631436,
|
||||
آرامش- میرزا طاهر 1,,yes,32.6506236,51.6298238,`
|
||||
|
||||
/**
|
||||
* تجزیهی یک خط CSV — پشتیبانی از فیلدهای گیومهدار و گیومهی دوگانهی درونی.
|
||||
* جداکننده کاما و نویسههای مخفی ابتدای فایل (BOM) هم حذف میشوند.
|
||||
*/
|
||||
function parseCsvLine(line: string): string[] {
|
||||
const fields: string[] = []
|
||||
let current = ''
|
||||
let inQuotes = false
|
||||
|
||||
for (let i = 0; i < line.length; i += 1) {
|
||||
const char = line[i]
|
||||
if (inQuotes) {
|
||||
if (char === '"') {
|
||||
if (line[i + 1] === '"') {
|
||||
current += '"'
|
||||
i += 1
|
||||
} else inQuotes = false
|
||||
} else current += char
|
||||
} else if (char === '"') inQuotes = true
|
||||
else if (char === ',') {
|
||||
fields.push(current.trim())
|
||||
current = ''
|
||||
} else current += char
|
||||
}
|
||||
fields.push(current.trim())
|
||||
return fields
|
||||
}
|
||||
|
||||
/** CSV خام → آرایهی تایپشدهی JSON */
|
||||
export function parseProjectsCsv(raw: string): MapProject[] {
|
||||
const rows: CsvRow[] = []
|
||||
const lines = raw.replace(/^\ufeff/, '').split(/\r?\n/)
|
||||
|
||||
for (const line of lines.slice(1)) {
|
||||
if (!line.trim()) continue
|
||||
const [name, year = '', isNew = '', lat = '', lng = '', description = ''] = parseCsvLine(line)
|
||||
const parsedLat = Number(lat)
|
||||
const parsedLng = Number(lng)
|
||||
if (!name || !Number.isFinite(parsedLat) || !Number.isFinite(parsedLng)) continue
|
||||
rows.push({ name, year, isNew: isNew.toLowerCase() === 'yes', lat: parsedLat, lng: parsedLng, description })
|
||||
}
|
||||
|
||||
return rows.map((row, index) => ({ id: index + 1, ...row }))
|
||||
}
|
||||
|
||||
export const MAP_PROJECTS: MapProject[] = parseProjectsCsv(RAW_CSV)
|
||||
|
||||
/** پیوند نشان روی نقشه برای سرویس نشان */
|
||||
export function buildNeshanUrl(project: Pick<MapProject, 'lat' | 'lng'>, zoom = 17): string {
|
||||
return `https://neshan.org/maps/@${project.lat},${project.lng},${zoom}z`
|
||||
}
|
||||
|
||||
/** پیوند نقشه گوگل */
|
||||
export function buildGoogleMapsUrl(project: Pick<MapProject, 'lat' | 'lng'>): string {
|
||||
return `https://www.google.com/maps?q=${project.lat},${project.lng}`
|
||||
}
|
||||
|
||||
const NAME_NOISE = ['آرامش', 'پروژه', 'مجتمع', 'گروه', 'ساختمانی', 'برج', 'مجموعه']
|
||||
|
||||
/**
|
||||
* نرمالسازی نام برای تطبیق شیت با دادهی بکاند: نویسههای نامرئی،
|
||||
* ی/ک عربی، نشانهها و واژههای عمومی حذف میشوند تا «آرامش - سنایی» و
|
||||
* «پروژه سنایی» یک کلید بگیرند.
|
||||
*/
|
||||
export function normalizeProjectName(name: string): string {
|
||||
let result = (name ?? '')
|
||||
.normalize('NFC')
|
||||
.replace(/[\u200b-\u200f\u202a-\u202e\ufeff]/g, ' ')
|
||||
.replace(/[يى]/g, 'ی')
|
||||
.replace(/ك/g, 'ک')
|
||||
.replace(/[ۀة]/g, 'ه')
|
||||
.replace(/[^\p{L}\p{N}\s]/gu, ' ')
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
|
||||
for (const noise of NAME_NOISE) result = result.replace(new RegExp(`(^|\\s)${noise}(?=\\s|$)`, 'g'), ' ')
|
||||
return result.replace(/\s+/g, ' ').trim()
|
||||
}
|
||||
|
||||
/** پروژهی شیت متناظر با یک نام (تطبیق دقیق نرمالشده، سپس دربرگیری) */
|
||||
export function findMapProjectByName(name: string): MapProject | undefined {
|
||||
const key = normalizeProjectName(name)
|
||||
if (!key) return undefined
|
||||
|
||||
const exact = MAP_PROJECTS.find((project) => normalizeProjectName(project.name) === key)
|
||||
if (exact) return exact
|
||||
|
||||
return MAP_PROJECTS.find((project) => {
|
||||
const candidate = normalizeProjectName(project.name)
|
||||
return candidate.length >= 3 && key.length >= 3 && (candidate.includes(key) || key.includes(candidate))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* محل جایگزین وقتی پروژهای در شیت پیدا نشد — مرکز اصفهان با نام پروژهی
|
||||
* بکاند، تا نمای تکپروژه هرگز بدون نقشه نماند.
|
||||
*/
|
||||
export function createPlaceholderProject(name: string, description = ''): MapProject {
|
||||
return {
|
||||
id: 0,
|
||||
name,
|
||||
year: '',
|
||||
isNew: false,
|
||||
lat: ISFAHAN_CENTER[1],
|
||||
lng: ISFAHAN_CENTER[0],
|
||||
description,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* کادر محدودهٔ نقشه از مختصات پروژهها — با حاشیه تا لبهٔ نقشه خالی نماند و
|
||||
* کاربر به بیرون از محدودهٔ پروژهها جابهجا نشود.
|
||||
*/
|
||||
export function boundsForProjects(
|
||||
projects: Pick<MapProject, 'lat' | 'lng'>[],
|
||||
padding = 0.02,
|
||||
): [[number, number], [number, number]] | undefined {
|
||||
if (!projects.length) return undefined
|
||||
const lats = projects.map((project) => project.lat)
|
||||
const lngs = projects.map((project) => project.lng)
|
||||
return [
|
||||
[Math.min(...lngs) - padding, Math.min(...lats) - padding],
|
||||
[Math.max(...lngs) + padding, Math.max(...lats) + padding],
|
||||
]
|
||||
}
|
||||
|
||||
/** ردیف شیت → کارت فهرست: عنوان از شیت، وضعیت از ستون new، نشانی از مختصات */
|
||||
export function csvProjectToCard(project: MapProject, detailHref: string): ProjectCardItem {
|
||||
return {
|
||||
id: project.id,
|
||||
title: project.name,
|
||||
status: project.isNew ? 'progress' : 'done',
|
||||
detailHref,
|
||||
addressUrl: buildNeshanUrl(project),
|
||||
}
|
||||
}
|
||||
|
||||
/** پروژهٔ بکاند → کارت فهرست؛ نشانی نشان از تطبیق نامی با شیت میآید */
|
||||
export function apiProjectToCard(project: Project, detailHref: string): ProjectCardItem {
|
||||
const matched = findMapProjectByName(project.title)
|
||||
return {
|
||||
id: project.id,
|
||||
title: project.title,
|
||||
status: project.status,
|
||||
detailHref,
|
||||
location: project.location || undefined,
|
||||
image: project.image || undefined,
|
||||
area: project.area || undefined,
|
||||
addressUrl: matched ? buildNeshanUrl(matched) : undefined,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
export type BilingualText = { en: string; fa: string };
|
||||
|
||||
export type StaticProject = {
|
||||
id: string;
|
||||
slug: string;
|
||||
name: BilingualText;
|
||||
location: BilingualText;
|
||||
area: BilingualText;
|
||||
status: 'done' | 'progress';
|
||||
};
|
||||
|
||||
|
||||
export const projectsData: StaticProject[] = [
|
||||
{ id: '1', slug: 'project-1', name: { en: 'Project 1', fa: 'پروژه سروش' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '2', slug: 'project-2', name: { en: 'Project 2', fa: 'چهرازی-زیتون' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '3', slug: 'project-3', name: { en: 'Project 3', fa: 'جعفریان' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '4', slug: 'project-4', name: { en: 'Project 4', fa: 'بهار' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '5', slug: 'project-5', name: { en: 'Project 5', fa: 'حسن مرادی' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '6', slug: 'project-6', name: { en: 'Project 6', fa: 'کوثر' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '7', slug: 'project-7', name: { en: 'Project 7', fa: 'صبا' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '8', slug: 'project-8', name: { en: 'Project 8', fa: 'پورمعالی - بهشت' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '9', slug: 'project-9', name: { en: 'Project 9', fa: '2 پروژه- فردوس' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '10', slug: 'project-10', name: { en: 'Project 10', fa: 'ارم' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '11', slug: 'project-11', name: { en: 'Project 11', fa: 'سینا' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '12', slug: 'project-12', name: { en: 'Project 12', fa: 'مسجد سید' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '13', slug: 'project-13', name: { en: 'Project 13', fa: 'هفده شهریور' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '14', slug: 'project-14', name: { en: 'Project 14', fa: 'آرامش رفیع زاده' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '15', slug: 'project-15', name: { en: 'Project 15', fa: 'بن بست شریعت' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '16', slug: 'project-16', name: { en: 'Project 16', fa: 'قصر - یاسین' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '17', slug: 'project-17', name: { en: 'Project 17', fa: 'پردیس' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '18', slug: 'project-18', name: { en: 'Project 18', fa: 'آرامش حکیم' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '19', slug: 'project-19', name: { en: 'Project 19', fa: 'آرامش دخانیات' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '20', slug: 'project-20', name: { en: 'Project 20', fa: 'بهشتی فرشادی' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '21', slug: 'project-21', name: { en: 'Project 21', fa: 'کاکتوس' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '22', slug: 'project-22', name: { en: 'Project 22', fa: 'آرامش - صیاد' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '23', slug: 'project-23', name: { en: 'Project 23', fa: 'کوثر' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '24', slug: 'project-24', name: { en: 'Project 24', fa: 'آرامش - بوعلی 1' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '25', slug: 'project-25', name: { en: 'Project 25', fa: 'میرزا نصیر' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '26', slug: 'project-26', name: { en: 'Project 26', fa: 'نیکان' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '27', slug: 'project-27', name: { en: 'Project 27', fa: 'آرامش-رسا' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '28', slug: 'project-28', name: { en: 'Project 28', fa: 'نگین' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '29', slug: 'project-29', name: { en: 'Project 29', fa: 'آرامش - بوعلی 2' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '30', slug: 'project-30', name: { en: 'Project 30', fa: 'آرامش استاد همایی' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '31', slug: 'project-31', name: { en: 'Project 31', fa: 'آرامش صدر' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '32', slug: 'project-32', name: { en: 'Project 32', fa: 'آرامش - سپهسالار' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '33', slug: 'project-33', name: { en: 'Project 33', fa: 'آرامش- صدر' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '34', slug: 'project-34', name: { en: 'Project 34', fa: 'آرامش - سنایی' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '35', slug: 'project-35', name: { en: 'Project 35', fa: 'مغازه لباس فروشی' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '36', slug: 'project-36', name: { en: 'Project 36', fa: 'آرامش - آتشگاه' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '37', slug: 'project-37', name: { en: 'Project 37', fa: 'آرامش - بزرگمهر' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '38', slug: 'project-38', name: { en: 'Project 38', fa: 'آرامش - سعدی' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '39', slug: 'project-39', name: { en: 'Project 39', fa: 'آرامش - صمدیه لباف' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '40', slug: 'project-40', name: { en: 'Project 40', fa: 'آرامش 2' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '41', slug: 'project-41', name: { en: 'Project 41', fa: 'آرامش 5 رمضان' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '42', slug: 'project-42', name: { en: 'Project 42', fa: 'آرامش احمدآباد' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '43', slug: 'project-43', name: { en: 'Project 43', fa: 'تجاری آتشگاه' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '44', slug: 'project-44', name: { en: 'Project 44', fa: 'آرامش - شهیدان' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '45', slug: 'project-45', name: { en: 'Project 45', fa: 'آرامش خواجو' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '46', slug: 'project-46', name: { en: 'Project 46', fa: 'آرامش- اداری ابوالحسن' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '47', slug: 'project-47', name: { en: 'Project 47', fa: 'آرامش - انقلاب' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '48', slug: 'project-48', name: { en: 'Project 48', fa: 'آرامش - شریف' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '49', slug: 'project-49', name: { en: 'Project 49', fa: 'آرامش - کهندژ' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '50', slug: 'project-50', name: { en: 'Project 50', fa: 'آرامش جی' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '51', slug: 'project-51', name: { en: 'Project 51', fa: 'آرامش - بابک' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '52', slug: 'project-52', name: { en: 'Project 52', fa: 'آرامش - شمس آبادی' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '53', slug: 'project-53', name: { en: 'Project 53', fa: 'آرامش - میرزاطاهر 3' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '54', slug: 'project-54', name: { en: 'Project 54', fa: 'آرامش - وحدت' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '55', slug: 'project-55', name: { en: 'Project 55', fa: 'آرامش پروین' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'done' },
|
||||
{ id: '56', slug: 'project-56', name: { en: 'Project 56', fa: 'خلیفه سلطانی' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '57', slug: 'project-57', name: { en: 'Project 57', fa: 'آرامش - میرزا طاهر 5' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '58', slug: 'project-58', name: { en: 'Project 58', fa: 'آرامش - میرزاطاهر 6' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '59', slug: 'project-59', name: { en: 'Project 59', fa: 'آرامش - میرزا طاهر 4' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
{ id: '60', slug: 'project-60', name: { en: 'Project 60', fa: 'آرامش- میرزا طاهر 1' }, location: { en: 'Isfahan', fa: 'اصفهان' }, area: { en: '1000', fa: '۱۰۰۰' }, status: 'progress' },
|
||||
];
|
||||
@@ -32,6 +32,10 @@ export type Project = {
|
||||
units_en?: string;
|
||||
client: string;
|
||||
client_en?: string;
|
||||
/** مختصات جغرافیایی پروژه — عرض جغرافیایی؛ ستونهای آینده بکاند، اختیاری */
|
||||
lat?: number;
|
||||
/** مختصات جغرافیایی پروژه — طول جغرافیایی؛ ستونهای آینده بکاند، اختیاری */
|
||||
lng?: number;
|
||||
summary: string;
|
||||
summary_en?: string;
|
||||
body: string[];
|
||||
@@ -70,3 +74,20 @@ export type Article = {
|
||||
/** هشتگها/برچسبهای مقاله */
|
||||
tags?: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* شکل پروژه در کارتهای فهرست — از پروژهٔ بکاند یا ردیف شیت پر میشود؛
|
||||
* فیلدهای اختیاری فقط وقتی رندر میشوند که دادهشان موجود باشد.
|
||||
*/
|
||||
export type ProjectCardItem = {
|
||||
id: number | string;
|
||||
title: string;
|
||||
status: ProjectStatus;
|
||||
/** مسیر صفحهٔ جزئیات پروژه */
|
||||
detailHref: string;
|
||||
/** نشانی بیرونی پروژه (نشان) — در نبودش دکمهٔ آن رندر نمیشود */
|
||||
addressUrl?: string;
|
||||
location?: string;
|
||||
image?: string;
|
||||
area?: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user