ty-produktovyy-dizayner-i-se/js/storage.js

93 lines
2.3 KiB
JavaScript

/* HR Candidate Matcher — Storage Layer */
/* global window */
(function () {
'use strict';
var APP = window.HRMatcher = window.HRMatcher || {};
var NAMESPACE = 'hr_matcher';
var SCHEMA_VERSION = 1;
var STORAGE_KEY = NAMESPACE + '_v' + SCHEMA_VERSION;
var storageAvailable = false;
var memoryFallback = {};
function testStorage() {
try {
var test = '__storage_test__';
localStorage.setItem(test, test);
localStorage.removeItem(test);
return true;
} catch (e) {
return false;
}
}
storageAvailable = testStorage();
APP.storage = {
isAvailable: function () { return storageAvailable; },
save: function (data) {
var payload = {
version: SCHEMA_VERSION,
timestamp: Date.now(),
data: data
};
if (storageAvailable) {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));
return true;
} catch (e) {
if (e.name === 'QuotaExceededError' || e.code === 22) {
APP.ui && APP.ui.showToast && APP.ui.showToast('Хранилище переполнено. Изменения не сохраняются.', 'error');
}
memoryFallback = payload;
return false;
}
} else {
memoryFallback = payload;
return false;
}
},
load: function () {
if (storageAvailable) {
try {
var raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return null;
var parsed = JSON.parse(raw);
if (parsed && parsed.version === SCHEMA_VERSION && parsed.data) {
return parsed.data;
}
return null;
} catch (e) {
return null;
}
}
return memoryFallback && memoryFallback.data ? memoryFallback.data : null;
},
clear: function () {
if (storageAvailable) {
try {
localStorage.removeItem(STORAGE_KEY);
} catch (e) { /* ignore */ }
}
memoryFallback = {};
},
savePartial: function (key, value) {
var current = this.load() || {};
current[key] = value;
return this.save(current);
},
removePartial: function (key) {
var current = this.load() || {};
delete current[key];
return this.save(current);
}
};
})();