Add document lifecycle tracking with order/production status

- Extended PDFStatus with full lifecycle: pending → uploading → in_basket →
  ordering → in_production → sent/canceled
- Added shipDocument() and getDocumentStatus() API methods
- Grouped UI sections: Ready to Upload, In Basket, In Production, Completed
- Order button for documents in basket to place production order
- Refresh button to check current status from Binect server
- Display price and recipient address for uploaded documents
- Status icons and color-coded indicators for each state

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-16 10:17:28 +01:00
parent 724940ebf7
commit 3a48d4f497
5 changed files with 815 additions and 78 deletions

View File

@@ -7,13 +7,16 @@ import { startPDFDetection, DetectedPDF } from '../utils/pdf-detector';
import { loadCredentials } from '../utils/storage';
import {
addPDF,
getPendingCount,
getActionableCount,
getAllPDFs,
getPendingPDFs,
updatePDFStatus,
removePDF,
cleanupOldEntries,
PDFStatus
PDFStatus,
PDFStatusMeta
} from '../utils/pdf-queue';
import { shipDocument, getDocumentStatus } from '../utils/binect-api';
/**
* Initialize extension on install
@@ -78,10 +81,10 @@ async function checkAndDeleteExpiredCredentials() {
}
/**
* Update badge with pending PDF count
* Update badge with actionable PDF count
*/
async function updateBadge() {
const count = await getPendingCount();
const count = await getActionableCount();
const text = count > 0 ? count.toString() : '•';
chrome.action.setBadgeText({ text });
chrome.action.setBadgeBackgroundColor({ color: '#4A90E2' }); // Binect Blue
@@ -117,6 +120,16 @@ startPDFDetection(async (pdf: DetectedPDF) => {
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log('[Service Worker] Message received:', request.action);
// Get all PDFs (including completed ones for display)
if (request.action === 'getAllPDFs') {
getAllPDFs().then(entries => {
console.log('[Service Worker] Returning all PDFs:', entries.length, 'entries');
sendResponse({ entries });
});
return true;
}
// Legacy: Get only actionable PDFs
if (request.action === 'getPDFQueue') {
getPendingPDFs().then(entries => {
console.log('[Service Worker] Returning PDF queue:', entries.length, 'entries');
@@ -126,7 +139,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
}
if (request.action === 'updatePDFStatus') {
const { id, status, meta } = request as { id: string; status: PDFStatus; meta?: object };
const { id, status, meta } = request as { id: string; status: PDFStatus; meta?: PDFStatusMeta };
updatePDFStatus(id, status, meta).then(() => {
return updateBadge();
}).then(() => {
@@ -144,9 +157,50 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
return true;
}
// Ship a document (place order for production)
if (request.action === 'shipDocument') {
const { documentId, username, password } = request as {
documentId: number;
username: string;
password: string;
};
shipDocument(documentId, username, password)
.then(result => {
sendResponse({ success: true, ...result });
})
.catch(error => {
sendResponse({
success: false,
error: error instanceof Error ? error.message : 'Failed to ship document'
});
});
return true;
}
// Get document status from Binect
if (request.action === 'getDocumentStatus') {
const { documentId, username, password } = request as {
documentId: number;
username: string;
password: string;
};
getDocumentStatus(documentId, username, password)
.then(result => {
sendResponse({ success: true, ...result });
})
.catch(error => {
sendResponse({
success: false,
error: error instanceof Error ? error.message : 'Failed to get status'
});
});
return true;
}
// Legacy handlers for backward compatibility
if (request.action === 'getLastPDF') {
// Return the first pending PDF for backward compatibility
getPendingPDFs().then(entries => {
const pdf = entries.length > 0 ? entries[0] : null;
sendResponse({ pdf });