diff --git a/app/locales/en.json b/app/locales/en.json index 5ef955e..e696947 100644 --- a/app/locales/en.json +++ b/app/locales/en.json @@ -73,17 +73,23 @@ "profiles.confirm_delete": "Delete this profile?", "pc_list.title": "'s postcards", "pc_list.new": "+ New postcard", + "pc_list.new_sent": "✉️ Sent", + "pc_list.new_received": "📬 Received", "pc_list.duplicate": "Card number already exists", "pc_list.all_countries": "All countries", "pc_list.filter": "Filter", "pc_list.tab_sent": "Sent", "pc_list.tab_received": "Received", + "pc_list.mark_sent": "Send", + "pc_list.confirm_sent": "Mark as sent?", "pc_list.mark_delivered": "Delivered", "pc_list.confirm_delivered": "Mark as delivered?", "pc_list.empty_sent": "No sent postcards.", "pc_list.empty_received": "No received postcards.", "pc_detail.title": "Postcard detail", "pc_detail.edit": "Edit", + "pc_detail.mark_sent": "Send", + "pc_detail.confirm_sent": "Mark as sent?", "pc_detail.mark_delivered": "Mark delivered", "pc_detail.confirm_delivered": "Mark as delivered?", "pc_detail.delete": "Delete", @@ -106,10 +112,13 @@ "pc_detail.profile": "Profile", "pc_detail.notes": "Notes", "status.sent": "Sent", + "status.pending": "Pending", "status.delivered": "Delivered", "status.received": "Received", "pc_form.edit": "Edit postcard", "pc_form.new": "New postcard", + "pc_form.new_sent": "New sent", + "pc_form.new_received": "New received", "pc_form.number": "Number", "pc_form.number_hint": "Format: AB-1234567", "pc_form.status": "Status", diff --git a/app/locales/zh.json b/app/locales/zh.json index d5ac648..3163d48 100644 --- a/app/locales/zh.json +++ b/app/locales/zh.json @@ -73,17 +73,23 @@ "profiles.confirm_delete": "确定删除此 Profile?", "pc_list.title": " 的明信片", "pc_list.new": "+ 新明信片", + "pc_list.new_sent": "✉️ 寄出", + "pc_list.new_received": "📬 收到", "pc_list.duplicate": "编号已存在", "pc_list.all_countries": "全部国家", "pc_list.filter": "筛选", "pc_list.tab_sent": "寄出", "pc_list.tab_received": "收到", + "pc_list.mark_sent": "寄出", + "pc_list.confirm_sent": "确认寄出?", "pc_list.mark_delivered": "已送达", "pc_list.confirm_delivered": "确认已送达?", "pc_list.empty_sent": "没有寄出的明信片。", "pc_list.empty_received": "没有收到的明信片。", "pc_detail.title": "明信片详情", "pc_detail.edit": "编辑", + "pc_detail.mark_sent": "寄出", + "pc_detail.confirm_sent": "确认寄出?", "pc_detail.mark_delivered": "已送达", "pc_detail.confirm_delivered": "确认已送达?", "pc_detail.delete": "删除", @@ -106,10 +112,13 @@ "pc_detail.profile": "所属 Profile", "pc_detail.notes": "备注", "status.sent": "已寄出", + "status.pending": "待寄出", "status.delivered": "已送达", "status.received": "已收到", "pc_form.edit": "编辑明信片", "pc_form.new": "新建明信片", + "pc_form.new_sent": "新建寄出", + "pc_form.new_received": "新建收到", "pc_form.number": "编号", "pc_form.number_hint": "格式:AB-1234567", "pc_form.status": "状态", diff --git a/app/routers/web.py b/app/routers/web.py index af536b5..5c9a62d 100644 --- a/app/routers/web.py +++ b/app/routers/web.py @@ -131,7 +131,7 @@ def index_page(request: Request, db: Session = Depends(get_db)): ).all() for c in cards: visible = True - if c.status in ("sent", "delivered") and p.showcase_visible not in ("sent", "both"): + if c.status in ("pending", "sent", "delivered") and p.showcase_visible not in ("sent", "both"): visible = False if c.status == "received" and p.showcase_visible not in ("received", "both"): visible = False @@ -173,7 +173,7 @@ def api_public_cards( ).all() for c in cards: vis = True - if c.status in ("sent", "delivered") and p.showcase_visible not in ("sent", "both"): + if c.status in ("pending", "sent", "delivered") and p.showcase_visible not in ("sent", "both"): vis = False if c.status == "received" and p.showcase_visible not in ("received", "both"): vis = False @@ -218,7 +218,7 @@ def api_public_cards_user( Postcard.image_front.isnot(None), Postcard.image_front != "" ).all() if tab == "sent" and p.showcase_visible in ("sent", "both"): - all_cards.extend([c for c in cards if c.status in ("sent", "delivered")]) + all_cards.extend([c for c in cards if c.status in ("pending", "sent", "delivered")]) elif tab == "received" and p.showcase_visible in ("received", "both"): all_cards.extend([c for c in cards if c.status == "received"]) all_cards.sort(key=lambda c: c.send_time or c.created_at, reverse=True) @@ -613,7 +613,7 @@ def dashboard(request: Request, user: User = Depends(get_current_user_web), db: for c in all_cards: if not c.country_to: continue - if c.status in ("sent", "delivered"): + if c.status in ("pending", "sent", "delivered"): sent_country_counts[c.country_to] = sent_country_counts.get(c.country_to, 0) + 1 elif c.status == "received": received_country_counts[c.country_to] = received_country_counts.get(c.country_to, 0) + 1 @@ -712,7 +712,7 @@ def postcard_list( postcards.sort(key=lambda pc: (_status_order.get(pc.status, 9), -(pc.send_time or pc.arrival_time or pc.receive_time or pc.created_at).timestamp())) # split into sent and received - sent = [pc for pc in postcards if pc.status in ("sent", "delivered")] + sent = [pc for pc in postcards if pc.status in ("pending", "sent", "delivered")] received = [pc for pc in postcards if pc.status == "received"] return templates.TemplateResponse( @@ -722,11 +722,12 @@ def postcard_list( @router.get("/profiles/{profile_id}/postcards/new", response_class=HTMLResponse) -def postcard_new(request: Request, profile_id: int, user: User = Depends(get_current_user_web), db: Session = Depends(get_db)): +def postcard_new(request: Request, profile_id: int, create_type: str = Query("sent"), user: User = Depends(get_current_user_web), db: Session = Depends(get_db)): profile = db.query(Profile).filter(Profile.id == profile_id, Profile.user_id == user.id).first() if not profile: return _redirect("/profiles") - return templates.TemplateResponse("postcard_form.html", {"request": request, "user": user, "profile": profile, "postcard": None}) + today = datetime.now().strftime("%Y-%m-%d") + return templates.TemplateResponse("postcard_form.html", {"request": request, "user": user, "profile": profile, "postcard": None, "create_type": create_type, "today": today}) @router.post("/profiles/{profile_id}/postcards") @@ -916,6 +917,28 @@ def mark_delivered( return _redirect(f"/postcards/{postcard_id}") +@router.post("/postcards/{postcard_id}/mark-sent") +def mark_sent( + postcard_id: int, + user: User = Depends(get_current_user_web), + db: Session = Depends(get_db), +): + """Transition pending → sent, auto-fill send_time if empty.""" + pc = ( + db.query(Postcard) + .join(Profile) + .filter(Postcard.id == postcard_id, Profile.user_id == user.id) + .first() + ) + if not pc: + return _redirect("/profiles") + pc.status = "sent" + if not pc.send_time: + pc.send_time = datetime.now() + db.commit() + return _redirect(f"/postcards/{postcard_id}") + + # ---------- Image Upload ---------- @router.post("/postcards/{postcard_id}/image/{side}") @@ -1028,11 +1051,11 @@ def public_showcase(request: Request, username: str, db: Session = Depends(get_d Postcard.image_front.isnot(None), Postcard.image_front != "" ).all() if p.showcase_visible in ("sent", "both"): - sent_all.extend([c for c in cards if c.status in ("sent", "delivered")]) + sent_all.extend([c for c in cards if c.status in ("pending", "sent", "delivered")]) if p.showcase_visible in ("received", "both"): received_all.extend([c for c in cards if c.status == "received"]) if p.showcase_visible in ("sent", "both"): - p_sent = [c for c in cards if c.status in ("sent", "delivered")] + p_sent = [c for c in cards if c.status in ("pending", "sent", "delivered")] else: p_sent = [] if p.showcase_visible in ("received", "both"): diff --git a/app/static/style.css b/app/static/style.css index 92cf5b4..ce058f3 100644 --- a/app/static/style.css +++ b/app/static/style.css @@ -156,6 +156,7 @@ code { background: var(--bg); padding: .15rem .4rem; border-radius: 4px; font-si /* Badge */ .badge { display: inline-block; padding: .1rem .4rem; border-radius: 999px; font-size: .65rem; font-weight: 600; color: #fff; background: var(--text-muted); white-space: nowrap; line-height: 1.4; align-self: center; } .badge-sent { background: var(--sent); } +.badge-pending { background: var(--primary); } .badge-delivered { background: var(--delivered); } .badge-received { background: var(--received); } diff --git a/app/templates/postcard_detail.html b/app/templates/postcard_detail.html index fedc0ac..f040361 100644 --- a/app/templates/postcard_detail.html +++ b/app/templates/postcard_detail.html @@ -5,11 +5,15 @@