279 lines
8.8 KiB
HTML
279 lines
8.8 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Проверка наличия льготных препаратов</title>
|
||
<link rel="icon" type="image/png" href="/favicon.png">
|
||
<style>
|
||
body {
|
||
font-family: Arial, sans-serif;
|
||
margin: 20px;
|
||
background-color: #f5f5f5;
|
||
}
|
||
.container {
|
||
max-width: 700px;
|
||
margin: 0 auto;
|
||
background-color: white;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
}
|
||
h2 {
|
||
color: #333;
|
||
text-align: center;
|
||
}
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin-top: 20px;
|
||
}
|
||
th, td {
|
||
border: 1px solid #ddd;
|
||
padding: 12px;
|
||
text-align: left;
|
||
}
|
||
th {
|
||
background-color: #195695;
|
||
color: white;
|
||
}
|
||
u {
|
||
border-bottom: 1px dashed #cccccc;
|
||
text-decoration: none;
|
||
cursor: help;
|
||
}
|
||
.name {
|
||
background-color: #e6f2ff;
|
||
text-align: center;
|
||
color: #195695;
|
||
}
|
||
.loading {
|
||
text-align: center;
|
||
padding: 20px;
|
||
font-style: italic;
|
||
color: #666;
|
||
}
|
||
.error {
|
||
color: red;
|
||
text-align: center;
|
||
padding: 20px;
|
||
}
|
||
.note {
|
||
margin-top: 10px;
|
||
font-size: small;
|
||
text-align: center;
|
||
}
|
||
.search-container {
|
||
display: flex;
|
||
gap: 10px;
|
||
justify-content: center;
|
||
}
|
||
#searchInput {
|
||
flex: 1;
|
||
min-width: 220px;
|
||
max-width: 280px;
|
||
padding: 10px;
|
||
font-size: 16px;
|
||
border: 1px solid #ccc;
|
||
border-radius: 4px;
|
||
}
|
||
#searchButton {
|
||
padding: 10px 20px;
|
||
font-size: 16px;
|
||
background-color: #6d4203;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
}
|
||
#searchButton:hover {
|
||
background-color: #8f6f3f;
|
||
}
|
||
|
||
/* Responsive behavior for smaller screens */
|
||
@media (max-width: 600px) {
|
||
.search-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
flex-wrap: wrap;
|
||
align-items: stretch;
|
||
}
|
||
|
||
#searchInput {
|
||
align-self: center;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
#searchButton {
|
||
align-self: center;
|
||
width: 90%;
|
||
}
|
||
}
|
||
|
||
@media (hover: none) {
|
||
u {
|
||
border-bottom: none !important;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<h2>Проверка наличия льготных препаратов<br/>в аптеках Санкт-Петербурга</h2>
|
||
|
||
<div class="search-container">
|
||
<input type="text" id="searchInput" placeholder="Введите название препарата">
|
||
<button id="searchButton">Найти</button>
|
||
</div>
|
||
|
||
<div id="content"></div>
|
||
</div>
|
||
|
||
<script>
|
||
function fetchData(name) {
|
||
document.getElementById('content').innerHTML = '<div class="loading">Загрузка данных...</div>';
|
||
name = name.replaceAll(' ', '_');
|
||
fetch(`/api-proxy?operation=getMedicament&filter=${name}`)
|
||
.then(response => response.json())
|
||
.then(data => displayData(processData(data)))
|
||
.catch(error => showError(error));
|
||
}
|
||
|
||
// Extract needed data from JSON
|
||
function processData(data) {
|
||
if (data['status'] !== "SUCCESS")
|
||
return data['errors'];
|
||
|
||
const results = data['model']['result'];
|
||
let processedData = [];
|
||
|
||
results.forEach(result => {
|
||
result['districts'].forEach(district => {
|
||
district['apothecaries'].forEach(apothecary => {
|
||
let address = apothecary['address'];
|
||
const regex = /\d*, [а-яА-Я\-. ]+, (.+) \*.+/;
|
||
let m;
|
||
if ((m = regex.exec(address)) !== null)
|
||
address = m[1];
|
||
else
|
||
address = address.substring(0, address.indexOf('*'));
|
||
|
||
processedData.push({
|
||
name: result['name'],
|
||
apothecary: apothecary['name'] + '<br/><i>' + address + '</i>',
|
||
countFederal: apothecary['ost1'],
|
||
countRegional: apothecary['ost2'],
|
||
timestamp: apothecary['date']
|
||
});
|
||
});
|
||
});
|
||
});
|
||
|
||
return processedData;
|
||
}
|
||
|
||
// Display the data in a table format
|
||
function displayData(data) {
|
||
let htmlContent;
|
||
|
||
if (typeof(data) === 'object') {
|
||
htmlContent = `
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Аптека</th>
|
||
<th style="width: 75px; text-align: center;">Остаток<br/>(<u title="региональная льгота">рег</u>/<u title="федеральная льгота">фед</u>)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
`;
|
||
|
||
// Group consecutive items with same name and generate merged cells
|
||
if (data.length > 0) {
|
||
let currentName = data[0].name;
|
||
let rowCount = 1;
|
||
let rowStartIndex = 0;
|
||
|
||
for (let i = 1; i <= data.length; i++) {
|
||
if (i < data.length && data[i].name === currentName) {
|
||
rowCount++;
|
||
} else {
|
||
// Generate rows for the current group
|
||
htmlContent += '<tr><td colspan="2"></td></tr>';
|
||
htmlContent += `<tr><td colspan="2" class="name"><b>${currentName}</b></td></tr>`;
|
||
for (let j = rowStartIndex; j < i; j++) {
|
||
const item = data[j];
|
||
htmlContent += `
|
||
<tr>
|
||
<td>${item.apothecary}</td>
|
||
<td style="text-align: center;">${item.countRegional} / ${item.countFederal}</td>
|
||
</tr>`;
|
||
}
|
||
|
||
// Reset for next group
|
||
if (i < data.length) {
|
||
currentName = data[i].name;
|
||
rowCount = 1;
|
||
rowStartIndex = i;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
htmlContent += `
|
||
</tbody>
|
||
</table>
|
||
`;
|
||
|
||
htmlContent += '<div class="note">Информация получена через <a href="https://eservice.gu.spb.ru/portalFront/resources/portal.html#medicament" target="_blank" style="text-decoration: none;">портал госуслуг Санкт-Петербурга</a>.</div>'
|
||
}
|
||
else
|
||
htmlContent = `<div class="error">${data}</div>`;
|
||
|
||
document.getElementById('content').innerHTML = htmlContent;
|
||
}
|
||
|
||
function showError(error) {
|
||
document.getElementById('content').innerHTML = `<div class="error">Ошибка: ${error.message}</div>`;
|
||
}
|
||
|
||
function search() {
|
||
const name = document.getElementById('searchInput').value.trim();
|
||
if (name) {
|
||
saveInputValue();
|
||
fetchData(name);
|
||
}
|
||
}
|
||
|
||
// Save input value to localStorage
|
||
function saveInputValue() {
|
||
const name = document.getElementById('searchInput').value;
|
||
localStorage.setItem('medicamentName', name);
|
||
}
|
||
|
||
// Restore input value from localStorage
|
||
function restoreInputValue() {
|
||
const savedValue = localStorage.getItem('medicamentName');
|
||
if (savedValue) {
|
||
document.getElementById('searchInput').value = savedValue;
|
||
return savedValue;
|
||
}
|
||
return null;
|
||
}
|
||
|
||
window.addEventListener('load', () => {
|
||
let name = restoreInputValue();
|
||
if (name !== null)
|
||
fetchData(name);
|
||
});
|
||
|
||
document.getElementById('searchButton').addEventListener('click', search);
|
||
document.getElementById('searchInput').addEventListener('keypress', (e) => {
|
||
if (e.key === 'Enter')
|
||
search();
|
||
});
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|