feat: add home page with search/unassigned tables; center login card

- Add home view as default: search by inv number, unassigned equipment
  table with auditory assignment, search results (assigned) table
- Add inv_number query param to GET /oboruds/ for backend search
- Center login card vertically and horizontally via flexbox

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-05-11 16:50:52 +03:00
parent 1950bd4d45
commit 2ae18dea27
4 changed files with 173 additions and 5 deletions

View File

@@ -17,7 +17,7 @@ async function fetchJSON(url) {
createApp({
data() {
return {
view: 'byAud',
view: 'home',
auditories: [],
selectedAudId: '',
oboruds: [],
@@ -27,6 +27,11 @@ createApp({
status: '',
error: '',
printTitle: '',
// home view
homeSearch: '',
homeUnassigned: [],
homeSearchResults: [],
homeSearchDone: false,
// auth/user management
token: '',
role: '',
@@ -72,6 +77,69 @@ createApp({
canEdit() { return this.isAdmin || this.isEditor; },
},
methods: {
async showHome() {
this.view = 'home';
this.status = '';
this.error = '';
this.homeSearch = '';
this.homeSearchResults = [];
this.homeSearchDone = false;
await this.loadHomeUnassigned();
},
async loadHomeUnassigned() {
this.status = 'Загрузка нераспределённого оборудования…';
this.error = '';
try {
const data = await fetchJSON('/oboruds/?unassigned=true&sort_by_inv=true');
this.homeUnassigned = data.map(it => ({ ...it, selectedAudId: '' }));
this.status = '';
} catch (e) {
console.error(e);
this.error = 'Не удалось загрузить данные';
this.status = '';
}
},
async doHomeSearch() {
const q = this.homeSearch.trim();
if (!q) {
this.status = 'Введите инвентарный номер';
return;
}
this.status = 'Поиск…';
this.error = '';
this.homeSearchDone = false;
try {
const data = await fetchJSON(`/oboruds/?inv_number=${encodeURIComponent(q)}`);
this.homeSearchResults = data.filter(it => it.aud_id).map(it => ({ ...it, selectedAudId: '' }));
this.homeSearchDone = true;
this.status = '';
} catch (e) {
console.error(e);
this.error = 'Не удалось выполнить поиск';
this.status = '';
}
},
async assignToAuditory(item) {
if (!item.selectedAudId) {
this.status = 'Выберите аудиторию';
return;
}
try {
this.status = 'Сохранение…';
this.error = '';
await this.fetchAuth(`/oboruds/${item.id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ aud_id: item.selectedAudId }),
});
await this.loadHomeUnassigned();
this.status = 'Сохранено';
} catch (e) {
console.error(e);
this.error = 'Не удалось назначить аудиторию';
this.status = '';
}
},
logout() {
try {
localStorage.removeItem('access_token');
@@ -592,6 +660,7 @@ createApp({
this.loadAuditories();
this.loadOwners();
this.loadEquipmentTypes();
this.loadHomeUnassigned();
if (this.isAdmin) {
this.loadUsers();
}