273 lines
9.8 KiB
TypeScript
Executable File
273 lines
9.8 KiB
TypeScript
Executable File
|
|
import { Building, District } from "../types";
|
|
import { MOCK_BUILDINGS, MOCK_DISTRICTS } from "../constants";
|
|
|
|
const DB_KEY_BUILDINGS = 'mkd_buildings_v2';
|
|
const DB_KEY_DISTRICTS = 'mkd_districts_v2';
|
|
const DB_KEY_GLOBAL_PASSPORT_FIELDS = 'mkd_global_passport_fields';
|
|
|
|
export const storageService = {
|
|
// --- DISTRICTS ---
|
|
getDistricts: (): District[] => {
|
|
try {
|
|
const stored = localStorage.getItem(DB_KEY_DISTRICTS);
|
|
if (stored) {
|
|
const parsed = JSON.parse(stored);
|
|
return Array.isArray(parsed) ? parsed : [];
|
|
}
|
|
return [];
|
|
} catch (e) {
|
|
return [];
|
|
}
|
|
},
|
|
|
|
saveDistrict: (district: District): void => {
|
|
const all = storageService.getDistricts();
|
|
const index = all.findIndex(d => d.id === district.id);
|
|
let newAll;
|
|
if (index >= 0) {
|
|
newAll = [...all];
|
|
newAll[index] = district;
|
|
} else {
|
|
newAll = [...all, district];
|
|
}
|
|
localStorage.setItem(DB_KEY_DISTRICTS, JSON.stringify(newAll));
|
|
},
|
|
|
|
createDistrict: (data: Omit<District, 'id'>): District => {
|
|
const newDistrict: District = {
|
|
...data,
|
|
id: `d-${Date.now()}`
|
|
};
|
|
storageService.saveDistrict(newDistrict);
|
|
return newDistrict;
|
|
},
|
|
|
|
deleteDistrict: (id: string): void => {
|
|
const all = storageService.getDistricts();
|
|
const newAll = all.filter(d => d.id !== id);
|
|
localStorage.setItem(DB_KEY_DISTRICTS, JSON.stringify(newAll));
|
|
},
|
|
|
|
// --- BUILDINGS ---
|
|
getAllBuildings: (): Building[] => {
|
|
try {
|
|
const stored = localStorage.getItem(DB_KEY_BUILDINGS);
|
|
if (stored) {
|
|
const parsed = JSON.parse(stored);
|
|
return Array.isArray(parsed) ? parsed : [];
|
|
}
|
|
return [];
|
|
} catch (e) {
|
|
return [];
|
|
}
|
|
},
|
|
|
|
getBuildingsByDistrict: (districtId: string): Building[] => {
|
|
const all = storageService.getAllBuildings();
|
|
return all.filter(b => b.districtId === districtId);
|
|
},
|
|
|
|
getBuildingById: (id: string): Building | undefined => {
|
|
const all = storageService.getAllBuildings();
|
|
return all.find(b => b.id === id);
|
|
},
|
|
|
|
saveBuildingData: (updatedBuilding: Building): void => {
|
|
try {
|
|
const all = storageService.getAllBuildings();
|
|
const index = all.findIndex(b => b.id === updatedBuilding.id);
|
|
const toSave = {
|
|
...updatedBuilding,
|
|
isDirty: true,
|
|
lastSync: Date.now()
|
|
};
|
|
let newAll;
|
|
if (index >= 0) {
|
|
newAll = [...all];
|
|
newAll[index] = toSave;
|
|
} else {
|
|
newAll = [...all, toSave];
|
|
}
|
|
localStorage.setItem(DB_KEY_BUILDINGS, JSON.stringify(newAll));
|
|
} catch (e) {
|
|
console.error("Failed to save to storage", e);
|
|
}
|
|
},
|
|
|
|
createBuilding: (data: Partial<Building> & { address: string, districtId: string }): Building => {
|
|
const id = `b-${Date.now()}`;
|
|
const newBuilding: Building = {
|
|
id,
|
|
districtId: data.districtId,
|
|
imageUrl: data.imageUrl || 'https://picsum.photos/800/600',
|
|
nps: 0,
|
|
passport: {
|
|
address: data.address,
|
|
apartmentsCount: 0,
|
|
general: {
|
|
address: data.address,
|
|
fiasCode: '',
|
|
constructionYear: new Date().getFullYear(),
|
|
commissionYear: new Date().getFullYear(),
|
|
seriesType: 'Индивидуальный',
|
|
floors: 1,
|
|
undergroundFloors: 0,
|
|
totalArea: 0,
|
|
livingArea: 0,
|
|
nonLivingArea: 0,
|
|
commonArea: 0,
|
|
cadastralNumberBuild: '',
|
|
cadastralNumberLand: ''
|
|
},
|
|
construction: { foundationType: '', foundationMaterial: '', wallMaterial: '', floorMaterial: '', roofType: '', roofMaterial: '', roofArea: 0, facadeType: '', facadeInsulation: false, windowType: '' },
|
|
engineering: { heatingType: '', heatingWiring: '', hasITP: false, waterSupplyMaterial: '', waterSupplyType: '', sewerMaterial: '', electricityEntries: 1, hasVRU: false, gasType: '', ventilationType: '' },
|
|
odpu: { customFields: {} },
|
|
meters: [],
|
|
lifts: [],
|
|
land: { area: 0, hasPlayground: false, hasSportsGround: false, hasParking: false, hasFencing: false, hasContainerSite: false },
|
|
management: {
|
|
contractDate: '',
|
|
contractNumber: '',
|
|
servicesList: [],
|
|
tariffMaintenance: 0,
|
|
reserveFund: 5.00, // Значение по умолчанию 5%
|
|
serviceContracts: [] // Initialize empty array
|
|
},
|
|
...data.passport
|
|
},
|
|
staff: [],
|
|
entrances: [],
|
|
commonSections: [],
|
|
accounts: [],
|
|
financials: { balance: 0, debt: 0, collectionRate: 0, topDebtors: [], invoices: [] },
|
|
requests: { new: 0, inProgress: 0, overdue: 0 },
|
|
inspectionHistory: [],
|
|
tasks: [],
|
|
annualPlan: [],
|
|
inventory: [],
|
|
writeOffHistory: [],
|
|
residents: [],
|
|
reports: [],
|
|
isDirty: true,
|
|
...data
|
|
};
|
|
storageService.saveBuildingData(newBuilding);
|
|
return newBuilding;
|
|
},
|
|
|
|
deleteBuilding: (id: string): void => {
|
|
const all = storageService.getAllBuildings();
|
|
const newAll = all.filter(b => b.id !== id);
|
|
localStorage.setItem(DB_KEY_BUILDINGS, JSON.stringify(newAll));
|
|
},
|
|
|
|
syncWithServer: async (): Promise<boolean> => {
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
const all = storageService.getAllBuildings();
|
|
const cleaned = all.map(b => ({ ...b, isDirty: false }));
|
|
localStorage.setItem(DB_KEY_BUILDINGS, JSON.stringify(cleaned));
|
|
resolve(true);
|
|
}, 1500);
|
|
});
|
|
},
|
|
clearLocal: () => {
|
|
localStorage.removeItem(DB_KEY_BUILDINGS);
|
|
localStorage.removeItem(DB_KEY_DISTRICTS);
|
|
},
|
|
|
|
// --- GLOBAL PASSPORT FIELDS (для всех домов) ---
|
|
getGlobalPassportFields: (): { [section: string]: { [fieldName: string]: { value: any; type: string; files?: string[] } } } => {
|
|
try {
|
|
const stored = localStorage.getItem(DB_KEY_GLOBAL_PASSPORT_FIELDS);
|
|
if (stored) return JSON.parse(stored);
|
|
return {};
|
|
} catch (e) {
|
|
return {};
|
|
}
|
|
},
|
|
|
|
saveGlobalPassportField: (section: 'general' | 'construction' | 'engineering' | 'odpu' | 'land' | 'management', fieldName: string, fieldType: 'text' | 'number' | 'checkbox'): void => {
|
|
const globalFields = storageService.getGlobalPassportFields();
|
|
if (!globalFields[section]) {
|
|
globalFields[section] = {};
|
|
}
|
|
const defaultValue = fieldType === 'number' ? 0 : fieldType === 'checkbox' ? false : '';
|
|
globalFields[section][fieldName] = {
|
|
value: defaultValue,
|
|
type: fieldType,
|
|
files: []
|
|
};
|
|
localStorage.setItem(DB_KEY_GLOBAL_PASSPORT_FIELDS, JSON.stringify(globalFields));
|
|
|
|
// Применяем это поле ко всем домам
|
|
const allBuildings = storageService.getAllBuildings();
|
|
allBuildings.forEach(building => {
|
|
const sectionData = building.passport[section] as any;
|
|
const customFields = { ...(sectionData.customFields || {}) };
|
|
if (!customFields[fieldName]) {
|
|
customFields[fieldName] = {
|
|
value: defaultValue,
|
|
type: fieldType,
|
|
files: []
|
|
};
|
|
const updatedSection = { ...sectionData, customFields };
|
|
building.passport[section] = updatedSection as any;
|
|
}
|
|
});
|
|
localStorage.setItem(DB_KEY_BUILDINGS, JSON.stringify(allBuildings));
|
|
},
|
|
|
|
updateGlobalPassportField: (section: 'general' | 'construction' | 'engineering' | 'odpu' | 'land' | 'management', fieldName: string, value: any, files?: string[]): void => {
|
|
const globalFields = storageService.getGlobalPassportFields();
|
|
if (globalFields[section] && globalFields[section][fieldName]) {
|
|
globalFields[section][fieldName].value = value;
|
|
if (files !== undefined) {
|
|
globalFields[section][fieldName].files = files;
|
|
}
|
|
localStorage.setItem(DB_KEY_GLOBAL_PASSPORT_FIELDS, JSON.stringify(globalFields));
|
|
|
|
// Обновляем это поле во всех домах
|
|
const allBuildings = storageService.getAllBuildings();
|
|
allBuildings.forEach(building => {
|
|
const sectionData = building.passport[section] as any;
|
|
const customFields = { ...(sectionData.customFields || {}) };
|
|
if (customFields[fieldName]) {
|
|
customFields[fieldName].value = value;
|
|
if (files !== undefined) {
|
|
customFields[fieldName].files = files;
|
|
}
|
|
const updatedSection = { ...sectionData, customFields };
|
|
building.passport[section] = updatedSection as any;
|
|
}
|
|
});
|
|
localStorage.setItem(DB_KEY_BUILDINGS, JSON.stringify(allBuildings));
|
|
}
|
|
},
|
|
|
|
deleteGlobalPassportField: (section: 'general' | 'construction' | 'engineering' | 'odpu' | 'land' | 'management', fieldName: string): void => {
|
|
const globalFields = storageService.getGlobalPassportFields();
|
|
if (globalFields[section] && globalFields[section][fieldName]) {
|
|
delete globalFields[section][fieldName];
|
|
if (Object.keys(globalFields[section]).length === 0) {
|
|
delete globalFields[section];
|
|
}
|
|
localStorage.setItem(DB_KEY_GLOBAL_PASSPORT_FIELDS, JSON.stringify(globalFields));
|
|
|
|
// Удаляем это поле из всех домов
|
|
const allBuildings = storageService.getAllBuildings();
|
|
allBuildings.forEach(building => {
|
|
const sectionData = building.passport[section] as any;
|
|
const customFields = { ...(sectionData.customFields || {}) };
|
|
if (customFields[fieldName]) {
|
|
delete customFields[fieldName];
|
|
const updatedSection = { ...sectionData, customFields };
|
|
building.passport[section] = updatedSection as any;
|
|
}
|
|
});
|
|
localStorage.setItem(DB_KEY_BUILDINGS, JSON.stringify(allBuildings));
|
|
}
|
|
}
|
|
};
|