More changes than expected. Mobile version improvements & PWA
Build & Push Docker Images / test-backend (push) Successful in 44s
Build & Push Docker Images / test-frontend (push) Successful in 52s
Build & Push Docker Images / build-backend (push) Failing after 34s
Build & Push Docker Images / build-frontend (push) Failing after 30s

This commit is contained in:
Ichitux
2026-05-20 22:28:17 +02:00
parent 7b288d33cb
commit 2eff93e66a
118 changed files with 13780 additions and 209 deletions
+95 -19
View File
@@ -1,7 +1,13 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import './MedicineResults.css';
import {
pushSupported,
isSubscribedLocally,
subscribeToPush,
unsubscribeFromPush,
} from '../utils/notifications.js';
function MedicineResults({ medicines, onSelect, query }) {
function MedicineResults({ medicines, onSelect, query, currentUser, onLoginRequest }) {
if (medicines.length === 0 && query.length >= 2) {
return (
<div className="no-results">
@@ -13,26 +19,96 @@ function MedicineResults({ medicines, onSelect, query }) {
return (
<div className="medicine-results">
{medicines.map((medicine) => (
<div
key={medicine.id}
className="medicine-card"
onClick={() => onSelect(medicine)}
>
<div className="medicine-card-header">
<h3>{medicine.name}</h3>
</div>
<div className="medicine-card-body">
<p><strong>Active Ingredient:</strong> {medicine.active_ingredient}</p>
<p><strong>Dosage:</strong> {medicine.dosage} <strong>Form:</strong> {medicine.form}</p>
</div>
<div className="medicine-card-footer">
<span className="view-pharmacies">View pharmacies </span>
</div>
</div>
<MedicineCard
key={medicine.nregistro || medicine.id}
medicine={medicine}
onSelect={onSelect}
currentUser={currentUser}
onLoginRequest={onLoginRequest}
/>
))}
</div>
);
}
export default MedicineResults;
function MedicineCard({ medicine, onSelect, currentUser, onLoginRequest }) {
const nregistro = medicine.nregistro || medicine.id;
const [subscribed, setSubscribed] = useState(() => isSubscribedLocally(nregistro));
const [busy, setBusy] = useState(false);
const [error, setError] = useState(null);
const supported = pushSupported();
useEffect(() => {
setSubscribed(isSubscribedLocally(nregistro));
}, [nregistro]);
async function handleBell(e) {
e.stopPropagation();
if (!currentUser) {
onLoginRequest?.();
return;
}
if (!supported) {
setError('Notifications need iOS 16.4+ and this site installed as an app (Share → Add to Home Screen).');
return;
}
if (busy) return;
setBusy(true);
setError(null);
try {
if (subscribed) {
await unsubscribeFromPush(nregistro);
setSubscribed(false);
} else {
await subscribeToPush(nregistro, medicine.name);
setSubscribed(true);
}
} catch (err) {
console.error('[notify] toggle failed:', err);
setError(err.message || 'Could not update subscription');
} finally {
setBusy(false);
}
}
return (
<div className="medicine-card" onClick={() => onSelect(medicine)}>
<div className="medicine-card-header">
<h3>{medicine.name}</h3>
<button
type="button"
className={`notify-bell${subscribed && currentUser ? ' notify-bell--on' : ''}${!currentUser ? ' notify-bell--locked' : ''}`}
onClick={handleBell}
disabled={busy}
aria-pressed={subscribed && !!currentUser}
aria-label={
!currentUser
? 'Login to enable notifications'
: subscribed
? 'Stop notifications for this medicine'
: 'Notify me when this medicine becomes available'
}
title={
!currentUser
? 'Login to enable notifications'
: subscribed
? 'Notifications on — click to turn off'
: 'Notify me when this medicine is added to a pharmacy'
}
>
{subscribed && currentUser ? '🔔' : '🔕'}
</button>
</div>
<div className="medicine-card-body">
<p><strong>Active Ingredient:</strong> {medicine.active_ingredient}</p>
<p><strong>Dosage:</strong> {medicine.dosage} <strong>Form:</strong> {medicine.form}</p>
{error && <p className="notify-error" onClick={e => e.stopPropagation()}>{error}</p>}
</div>
<div className="medicine-card-footer">
<span className="view-pharmacies">View pharmacies </span>
</div>
</div>
);
}
export default MedicineResults;