Archiv: Datei-Badge, Bestellungen: Preiskategorie als Festpreis übernehmen
This commit is contained in:
@@ -5,7 +5,27 @@ const { authenticate } = require('../../middleware/auth');
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/', authenticate, (req, res) => {
|
||||
res.json(db.prepare('SELECT * FROM calculations WHERE user_id=? ORDER BY created_at DESC').all(req.user.id));
|
||||
const uid = req.user.id;
|
||||
const items = db.prepare('SELECT * FROM calculations WHERE user_id=? ORDER BY created_at DESC').all(uid);
|
||||
|
||||
// Prüfen welche Modelle Dateien haben: Unterordner von "3D-Modelle" mit Dateien
|
||||
const baseFolder = db.prepare(
|
||||
"SELECT id FROM folders WHERE user_id=? AND name='3D-Modelle' AND parent_id IS NULL"
|
||||
).get(uid);
|
||||
|
||||
let filesMap = {};
|
||||
if (baseFolder) {
|
||||
const rows = db.prepare(`
|
||||
SELECT f.name, COUNT(fi.id) AS cnt
|
||||
FROM folders f
|
||||
LEFT JOIN files fi ON fi.folder_id = f.id
|
||||
WHERE f.parent_id = ? AND f.user_id = ?
|
||||
GROUP BY f.id
|
||||
`).all(baseFolder.id, uid);
|
||||
for (const r of rows) filesMap[r.name] = r.cnt > 0;
|
||||
}
|
||||
|
||||
res.json(items.map(i => ({ ...i, has_files: !!filesMap[i.name] })));
|
||||
});
|
||||
|
||||
router.post('/', authenticate, (req, res) => {
|
||||
|
||||
@@ -375,15 +375,25 @@ function BestellungDetail({ id, toast, onBack }) {
|
||||
<div style={{...S.card,marginBottom:10}}>
|
||||
<div style={S.head}>GESAMTSUMME</div>
|
||||
<div style={{display:'grid',gridTemplateColumns:'1fr 1fr 1fr',gap:8,marginBottom:totals.has_any_custom||order.custom_price?12:0}}>
|
||||
{PREISE.map(p=>(
|
||||
<div key={p.key} style={{background:`${p.c}10`,border:`1px solid ${p.c}30`,borderRadius:9,padding:'10px 8px',textAlign:'center'}}>
|
||||
<div style={{fontSize:16,marginBottom:2}}>{p.emoji}</div>
|
||||
<div style={{color:'rgba(255,255,255,0.6)',fontSize:9,fontFamily:'monospace',marginBottom:3}}>{p.label}</div>
|
||||
<div style={{color:p.c,fontFamily:"'Space Mono',monospace",fontSize:16,fontWeight:700}}>
|
||||
{totals[p.key].toFixed(2)}€
|
||||
{PREISE.map(p=>{
|
||||
const canSelect = !order.bezahlt && order.custom_price == null && !totals.has_any_custom;
|
||||
return (
|
||||
<div key={p.key}
|
||||
onClick={() => canSelect && api(`/tools/bestellungen/${id}`,{method:'PUT',body:{custom_price:totals[p.key]}}).then(u=>{setOrder(u);setForm(f=>({...f,custom_price:totals[p.key].toFixed(2)}));toast(`${p.label}-Preis übernommen`);}).catch(e=>toast(e.message,'error'))}
|
||||
title={canSelect ? `${p.label}-Preis als Festpreis übernehmen` : undefined}
|
||||
style={{background:`${p.c}10`,border:`1px solid ${p.c}30`,borderRadius:9,padding:'10px 8px',textAlign:'center',
|
||||
cursor:canSelect?'pointer':'default',
|
||||
transition:'background 0.15s',
|
||||
...(canSelect?{':hover':{background:`${p.c}20`}}:{})}}>
|
||||
<div style={{fontSize:16,marginBottom:2}}>{p.emoji}</div>
|
||||
<div style={{color:'rgba(255,255,255,0.6)',fontSize:9,fontFamily:'monospace',marginBottom:3}}>{p.label}</div>
|
||||
<div style={{color:p.c,fontFamily:"'Space Mono',monospace",fontSize:16,fontWeight:700}}>
|
||||
{totals[p.key].toFixed(2)}€
|
||||
</div>
|
||||
{canSelect && <div style={{color:`${p.c}80`,fontSize:8,fontFamily:'monospace',marginTop:3}}>↑ übernehmen</div>}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{totals.has_any_custom && (
|
||||
<div style={{padding:'10px 14px',background:'rgba(255,255,255,0.04)',border:'1px solid rgba(255,255,255,0.1)',borderRadius:8,display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:8}}>
|
||||
|
||||
@@ -633,7 +633,15 @@ export function SavedList({ toast, mobile }) {
|
||||
<div style={{ flex:1, minWidth:0 }}>
|
||||
{/* Name + Datum */}
|
||||
<div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:4 }}>
|
||||
<div style={{ color:'#fff', fontFamily:'monospace', fontSize:13, fontWeight:700 }}>{item.name}</div>
|
||||
<div style={{ display:'flex', alignItems:'center', gap:6 }}>
|
||||
<div style={{ color:'#fff', fontFamily:'monospace', fontSize:13, fontWeight:700 }}>{item.name}</div>
|
||||
{item.has_files && (
|
||||
<span title="3D-Dateien vorhanden"
|
||||
style={{ fontSize:11, background:'rgba(78,205,196,0.12)', border:'1px solid rgba(78,205,196,0.25)',
|
||||
borderRadius:5, padding:'1px 5px', color:'#4ecdc4', fontFamily:'monospace', fontSize:9,
|
||||
letterSpacing:0.5, flexShrink:0 }}>🖨 Dateien</span>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ color:'rgba(255,255,255,0.5)', fontFamily:'monospace', fontSize:10, flexShrink:0, marginLeft:8 }}>
|
||||
{new Date(item.created_at).toLocaleDateString('de-DE')}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user