@open-mercato/core 0.6.4-develop.4305.1.efaf0ebab1 → 0.6.4-develop.4322.1.7bf54b8070
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +16 -3
- package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +4 -0
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +21 -5
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +21 -5
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +48 -32
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +18 -3
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
- package/dist/modules/entities/api/entities.js +4 -1
- package/dist/modules/entities/api/entities.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js +14 -9
- package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js +21 -3
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +18 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +18 -3
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/jest.config.cjs +3 -0
- package/package.json +7 -7
- package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +20 -3
- package/src/modules/customers/api/companies/[id]/route.ts +4 -0
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +25 -5
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +25 -5
- package/src/modules/customers/commands/companies.ts +51 -34
- package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +21 -3
- package/src/modules/entities/api/entities.ts +4 -1
- package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +22 -11
- package/src/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.tsx +36 -3
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +21 -2
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +21 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/inbox_ops/backend/inbox-ops/proposals/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport {\n ArrowLeft,\n CheckCircle,\n XCircle,\n AlertTriangle,\n CheckCheck,\n Loader2,\n ExternalLink,\n RefreshCw,\n Users,\n Languages,\n Pencil,\n} from 'lucide-react'\nimport type { ProposalTranslationEntry } from '../../../../data/entities'\nimport type { ProposalDetail, ActionDetail, DiscrepancyDetail, EmailDetail } from '../../../../components/proposals/types'\nimport { ActionCard, ConfidenceBadge, useActionTypeLabels, useDiscrepancyDescriptions } from '../../../../components/proposals/ActionCard'\nimport { CategoryBadge, CATEGORY_CONFIG, ALL_CATEGORIES, useCategoryLabels } from '../../../../components/proposals/CategoryBadge'\nimport { hasContactNameIssue } from '../../../../lib/contactValidation'\nimport { EditActionDialog } from '../../../../components/proposals/EditActionDialog'\n\nfunction EmailThreadViewer({ email }: { email: EmailDetail | null }) {\n const t = useT()\n if (!email) return null\n\n const messages = email.threadMessages || []\n\n return (\n <div className=\"space-y-3\">\n <h3 className=\"font-semibold text-sm\">{t('inbox_ops.email_thread', 'Email Thread')}</h3>\n {messages.length > 0 ? (\n messages.map((msg, index) => (\n <div key={index} className=\"border rounded-lg p-3 md:p-4 bg-card\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium truncate\">\n {msg.from?.name || msg.from?.email || t('inbox_ops.sender_unknown', 'Unknown')}\n </div>\n <div className=\"text-xs text-muted-foreground truncate\">{msg.from?.email}</div>\n </div>\n <span className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {msg.date ? new Date(msg.date).toLocaleString([], { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) : ''}\n </span>\n </div>\n <div className=\"text-sm whitespace-pre-wrap text-foreground/80\">{msg.body}</div>\n </div>\n ))\n ) : email.cleanedText ? (\n <div className=\"border rounded-lg p-3 md:p-4 bg-card\">\n <div className=\"text-sm whitespace-pre-wrap text-foreground/80\">{email.cleanedText}</div>\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('inbox_ops.no_email_content', 'No email content available')}</p>\n )}\n </div>\n )\n}\n\nfunction CategoryEditDropdown({\n currentCategory,\n onSelect,\n disabled,\n}: {\n currentCategory: string | null | undefined\n onSelect: (category: string) => void\n disabled: boolean\n}) {\n const t = useT()\n const labels = useCategoryLabels()\n const [isOpen, setIsOpen] = React.useState(false)\n const dropdownRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n }\n }\n function handleEscape(event: KeyboardEvent) {\n if (event.key === 'Escape') setIsOpen(false)\n }\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n }\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n }\n }, [isOpen])\n\n return (\n <div className=\"relative inline-block\" ref={dropdownRef}>\n <div className=\"flex items-center gap-1\">\n <CategoryBadge category={currentCategory} />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-6 w-6 p-0\"\n onClick={() => setIsOpen(!isOpen)}\n disabled={disabled}\n title={t('inbox_ops.recategorize', 'Change Category')}\n >\n <Pencil className=\"h-3 w-3\" />\n </Button>\n </div>\n {isOpen && (\n <div className=\"absolute top-full left-0 mt-1 z-dropdown w-48 rounded-md border bg-popover shadow-md\">\n <div className=\"p-1\">\n {ALL_CATEGORIES.map((cat) => {\n const config = CATEGORY_CONFIG[cat]\n const { Icon } = config\n return (\n <Button\n key={cat}\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className={`flex items-center gap-2 w-full justify-start rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground ${currentCategory === cat ? 'bg-accent' : ''}`}\n onClick={() => { onSelect(cat); setIsOpen(false) }}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {labels[cat] || cat}\n </Button>\n )\n })}\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default function ProposalDetailPage({ params }: { params?: { id?: string } }) {\n const t = useT()\n const locale = useLocale()\n const router = useRouter()\n const proposalId = params?.id\n\n const [proposal, setProposal] = React.useState<ProposalDetail | null>(null)\n const [actions, setActions] = React.useState<ActionDetail[]>([])\n const [discrepancies, setDiscrepancies] = React.useState<DiscrepancyDetail[]>([])\n const [email, setEmail] = React.useState<EmailDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isProcessing, setIsProcessing] = React.useState(false)\n\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const { runMutation } = useGuardedMutation<Record<string, unknown>>({\n contextId: 'inbox-ops-proposal-detail',\n })\n const actionTypeLabels = useActionTypeLabels()\n const resolveDiscrepancyDescription = useDiscrepancyDescriptions()\n const [editingAction, setEditingAction] = React.useState<ActionDetail | null>(null)\n const [sendingReplyId, setSendingReplyId] = React.useState<string | null>(null)\n\n const [translation, setTranslation] = React.useState<ProposalTranslationEntry | null>(null)\n const [isTranslating, setIsTranslating] = React.useState(false)\n const [showTranslation, setShowTranslation] = React.useState(false)\n\n const handleEditAction = React.useCallback((action: ActionDetail) => {\n if (action.actionType === 'create_order' || action.actionType === 'create_quote') {\n const kind = action.actionType === 'create_order' ? 'order' : 'quote'\n try {\n sessionStorage.setItem(\n 'inbox_ops.orderDraft',\n JSON.stringify({\n actionId: action.id,\n proposalId: action.proposalId,\n payload: action.payload,\n }),\n )\n } catch { /* sessionStorage unavailable */ }\n router.push(`/backend/sales/documents/create?kind=${kind}&fromInboxAction=${encodeURIComponent(action.id)}`)\n return\n }\n if (action.actionType === 'create_product') {\n try {\n sessionStorage.setItem(\n 'inbox_ops.productDraft',\n JSON.stringify({\n actionId: action.id,\n proposalId: action.proposalId,\n payload: action.payload,\n }),\n )\n } catch { /* sessionStorage unavailable */ }\n router.push(`/backend/catalog/products/create?fromInboxAction=${encodeURIComponent(action.id)}`)\n return\n }\n setEditingAction(action)\n }, [router])\n\n const handleTranslate = React.useCallback(async () => {\n if (!proposalId) return\n setIsTranslating(true)\n const result = await runMutation({\n operation: () => apiCall<{ translation: ProposalTranslationEntry; cached: boolean }>(\n `/api/inbox_ops/proposals/${proposalId}/translate`,\n { method: 'POST', body: JSON.stringify({ targetLocale: locale }) },\n ),\n context: {},\n })\n if (result?.ok && result.result?.translation) {\n setTranslation(result.result.translation)\n setShowTranslation(true)\n } else {\n const detail = (result?.result as Record<string, unknown> | null)?.error\n flash(detail ? `${t('inbox_ops.translate.failed', 'Translation failed')}: ${detail}` : t('inbox_ops.translate.failed', 'Translation failed'), 'error')\n }\n setIsTranslating(false)\n }, [proposalId, locale, t, runMutation])\n\n const handleCategorize = React.useCallback(async (category: string) => {\n if (!proposalId) return\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean; category: string; previousCategory: string | null }>(\n `/api/inbox_ops/proposals/${proposalId}/categorize`,\n { method: 'POST', body: JSON.stringify({ category }) },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n setProposal((prev) => prev ? { ...prev, category: result.result!.category } : prev)\n } else {\n flash(t('inbox_ops.flash.save_failed', 'Failed to save'), 'error')\n }\n }, [proposalId, t, runMutation])\n\n const loadData = React.useCallback(async () => {\n if (!proposalId) return\n setIsLoading(true)\n setError(null)\n try {\n const result = await apiCall<{\n proposal: ProposalDetail\n actions: ActionDetail[]\n discrepancies: DiscrepancyDetail[]\n email: EmailDetail\n }>(`/api/inbox_ops/proposals/${proposalId}`)\n if (result?.ok && result.result) {\n setProposal(result.result.proposal)\n setActions(result.result.actions || [])\n setDiscrepancies(result.result.discrepancies || [])\n setEmail(result.result.email)\n } else {\n setError(t('inbox_ops.flash.load_failed', 'Failed to load proposal'))\n }\n } catch {\n setError(t('inbox_ops.flash.load_failed', 'Failed to load proposal'))\n }\n setIsLoading(false)\n }, [proposalId, t])\n\n React.useEffect(() => { loadData() }, [loadData])\n\n const handleAcceptAction = React.useCallback(async (actionId: string) => {\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean; error?: string }>(\n `/api/inbox_ops/proposals/${proposalId}/actions/${actionId}/accept`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.flash.action_executed', 'Action executed'), 'success')\n await loadData()\n } else {\n flash(result?.result?.error || t('inbox_ops.flash.action_execute_failed', 'Failed to execute action'), 'error')\n }\n setIsProcessing(false)\n }, [proposalId, loadData, t, runMutation])\n\n const handleRejectAction = React.useCallback(async (actionId: string) => {\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean }>(\n `/api/inbox_ops/proposals/${proposalId}/actions/${actionId}/reject`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.flash.action_rejected', 'Action rejected'), 'success')\n await loadData()\n } else {\n flash(t('inbox_ops.flash.action_reject_failed', 'Failed to reject action'), 'error')\n }\n setIsProcessing(false)\n }, [proposalId, loadData, runMutation])\n\n const handleAcceptAll = React.useCallback(async () => {\n const pendingActions = actions.filter((a) => a.status === 'pending')\n const pendingCount = pendingActions.length\n const nameIssueCount = pendingActions.filter((a) => hasContactNameIssue(a)).length\n\n const confirmText = nameIssueCount > 0\n ? t('inbox_ops.action.accept_all_confirm_with_skip', 'Execute {count} pending actions? {skipCount} contact actions will be skipped due to missing names.')\n .replace('{count}', String(pendingCount))\n .replace('{skipCount}', String(nameIssueCount))\n : t('inbox_ops.action.accept_all_confirm', 'Execute {count} pending actions?').replace('{count}', String(pendingCount))\n\n const confirmed = await confirm({\n title: t('inbox_ops.action.accept_all', 'Accept All'),\n text: confirmText,\n })\n if (!confirmed) return\n\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean; succeeded: number; failed: number }>(\n `/api/inbox_ops/proposals/${proposalId}/accept-all`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n const msg = result.result.failed > 0\n ? t('inbox_ops.flash.accept_all_partial', '{succeeded} actions executed, {failed} failed')\n .replace('{succeeded}', String(result.result.succeeded))\n .replace('{failed}', String(result.result.failed))\n : t('inbox_ops.flash.accept_all_success', '{succeeded} actions executed')\n .replace('{succeeded}', String(result.result.succeeded))\n flash(msg, 'success')\n await loadData()\n } else {\n flash(t('inbox_ops.flash.accept_all_failed', 'Failed to accept all actions'), 'error')\n }\n setIsProcessing(false)\n }, [proposalId, actions, confirm, t, loadData, runMutation])\n\n const handleRejectAll = React.useCallback(async () => {\n const confirmed = await confirm({\n title: t('inbox_ops.action.reject_all', 'Reject Proposal'),\n text: t('inbox_ops.action.reject_all_confirm', 'Reject all pending actions in this proposal?'),\n })\n if (!confirmed) return\n\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean }>(\n `/api/inbox_ops/proposals/${proposalId}/reject`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.action.proposal_rejected', 'Proposal rejected'), 'success')\n await loadData()\n }\n setIsProcessing(false)\n }, [proposalId, confirm, t, loadData, runMutation])\n\n const handleRetryExtraction = React.useCallback(async () => {\n if (!email) return\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean }>(\n `/api/inbox_ops/emails/${email.id}/reprocess`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.flash.reprocessing_started', 'Reprocessing started'), 'success')\n await loadData()\n }\n setIsProcessing(false)\n }, [email, loadData, runMutation])\n\n const handleSendReply = React.useCallback(async (actionId: string) => {\n setSendingReplyId(actionId)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean; error?: string }>(\n `/api/inbox_ops/proposals/${proposalId}/replies/${actionId}/send`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.reply.sent_success', 'Reply sent successfully'), 'success')\n await loadData()\n } else {\n flash(result?.result?.error || t('inbox_ops.flash.send_reply_failed', 'Failed to send reply'), 'error')\n }\n setSendingReplyId(null)\n }, [proposalId, t, loadData, runMutation])\n\n if (isLoading) return <LoadingMessage label={t('inbox_ops.loading_proposal', 'Loading proposal...')} />\n if (error) return <ErrorMessage label={error} />\n\n const pendingActions = actions.filter((a) => a.status === 'pending')\n const emailIsProcessing = email?.status === 'processing'\n const emailFailed = email?.status === 'failed'\n\n return (\n <Page>\n {ConfirmDialogElement}\n {editingAction && (\n <EditActionDialog\n action={editingAction}\n actionTypeLabels={actionTypeLabels}\n onClose={() => setEditingAction(null)}\n onSaved={loadData}\n />\n )}\n\n <div className=\"flex items-center justify-between px-4 py-3 md:px-6 md:py-4 border-b bg-background\">\n <div className=\"flex items-center gap-2 md:gap-3 min-w-0\">\n <Link href=\"/backend/inbox-ops\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\">\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n </Link>\n <div className=\"min-w-0 flex-1\">\n <h1 className=\"text-base md:text-lg font-semibold truncate\">{email?.subject || t('inbox_ops.proposal', 'Proposal')}</h1>\n <p className=\"text-xs text-muted-foreground truncate\">\n {email?.forwardedByName || email?.forwardedByAddress} \u00B7 {email?.receivedAt && new Date(email.receivedAt).toLocaleString()}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n {pendingActions.length > 0 && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9 text-destructive border-destructive/30 hover:bg-destructive/10\"\n onClick={handleRejectAll}\n disabled={isProcessing}\n >\n <XCircle className=\"h-4 w-4 mr-1\" />\n <span className=\"hidden md:inline\">{t('inbox_ops.action.reject_all', 'Reject Proposal')}</span>\n </Button>\n )}\n {pendingActions.length > 1 && (\n <Button type=\"button\" size=\"sm\" className=\"h-11 md:h-9\" onClick={handleAcceptAll} disabled={isProcessing}>\n {isProcessing ? <Loader2 className=\"h-4 w-4 animate-spin mr-1\" /> : <CheckCheck className=\"h-4 w-4 mr-1\" />}\n <span className=\"hidden md:inline\">{t('inbox_ops.action.accept_all', 'Accept All')}</span>\n </Button>\n )}\n </div>\n </div>\n\n <PageBody>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-6\">\n {/* Left panel: Email Thread */}\n <div>\n <EmailThreadViewer email={email} />\n </div>\n\n {/* Right panel: Summary + Actions */}\n <div className=\"space-y-4\">\n {emailIsProcessing ? (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <Loader2 className=\"h-8 w-8 animate-spin text-primary mb-3\" />\n <p className=\"text-sm text-muted-foreground\">{t('inbox_ops.extraction_loading', 'AI is analyzing this thread...')}</p>\n </div>\n ) : emailFailed ? (\n <div className=\"border rounded-lg p-4 bg-status-error-bg border-status-error-border\">\n <div className=\"flex items-center gap-2 mb-2\">\n <AlertTriangle className=\"h-5 w-5 text-status-error-icon\" />\n <span className=\"text-sm font-medium text-status-error-text\">{t('inbox_ops.extraction_failed', 'Extraction failed')}</span>\n </div>\n {email?.processingError && (\n <p className=\"text-xs text-status-error-text mb-3\">{email.processingError}</p>\n )}\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={handleRetryExtraction} disabled={isProcessing}>\n <RefreshCw className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.retry', 'Retry')}\n </Button>\n </div>\n ) : proposal ? (\n <>\n {/* Summary */}\n <div className=\"border rounded-lg p-3 md:p-4\">\n <div className=\"flex items-center justify-between mb-2\">\n <h3 className=\"font-semibold text-sm\">{t('inbox_ops.summary', 'Summary')}</h3>\n {(proposal.workingLanguage || 'en') !== locale && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 text-xs\"\n onClick={showTranslation ? () => setShowTranslation(false) : handleTranslate}\n disabled={isTranslating}\n >\n {isTranslating ? (\n <Loader2 className=\"h-3 w-3 animate-spin mr-1\" />\n ) : (\n <Languages className=\"h-3 w-3 mr-1\" />\n )}\n {showTranslation\n ? t('inbox_ops.translate.show_original', 'Show original')\n : t('inbox_ops.translate.translate', 'Translate')}\n </Button>\n )}\n </div>\n <p className=\"text-sm text-foreground/80 mb-3\">\n {showTranslation && translation ? translation.summary : proposal.summary}\n </p>\n\n <div className=\"flex items-center gap-4 mb-3 flex-wrap\">\n <div>\n <span className=\"text-xs text-muted-foreground\">{t('inbox_ops.confidence', 'Confidence')}</span>\n <ConfidenceBadge value={proposal.confidence} />\n </div>\n <div>\n <span className=\"text-xs text-muted-foreground block\">{t('inbox_ops.category', 'Category')}</span>\n <CategoryEditDropdown\n currentCategory={proposal.category}\n onSelect={handleCategorize}\n disabled={isProcessing}\n />\n </div>\n </div>\n\n {proposal.possiblyIncomplete && (\n <div className=\"flex items-center gap-2 text-xs text-status-warning-text bg-status-warning-bg rounded px-2 py-1 mb-3\">\n <AlertTriangle className=\"h-3 w-3\" />\n {t('inbox_ops.possibly_incomplete', 'This thread appears to be a partial forward')}\n </div>\n )}\n\n {/* Participants */}\n {proposal.participants.length > 0 && (\n <div>\n <h4 className=\"text-xs font-medium text-muted-foreground mb-1\">{t('inbox_ops.participants', 'Participants')}</h4>\n <div className=\"space-y-1\">\n {proposal.participants.map((p, idx) => (\n <div key={idx} className=\"flex items-center gap-2 text-sm\">\n <Users className=\"h-3 w-3 text-muted-foreground\" />\n <span>{p.name}</span>\n <span className=\"text-xs text-muted-foreground\">({p.role})</span>\n {p.matchedContactId && <CheckCircle className=\"h-3 w-3 text-status-success-icon\" />}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n\n {/* Discrepancies not tied to a specific action */}\n {(() => {\n const actionIds = new Set(actions.map((a) => a.id))\n const general = discrepancies.filter((d) => !d.resolved && (!d.actionId || !actionIds.has(d.actionId)))\n if (general.length === 0) return null\n return (\n <div className=\"border rounded-lg p-3 md:p-4 bg-status-warning-bg border-status-warning-border\">\n <div className=\"flex items-center gap-2 mb-2\">\n <AlertTriangle className=\"h-4 w-4 text-status-warning-icon\" />\n <h3 className=\"font-semibold text-sm text-status-warning-text\">{t('inbox_ops.discrepancies', 'Issues Detected')}</h3>\n </div>\n <div className=\"space-y-1.5\">\n {general.map((d) => (\n <div key={d.id} className={`flex items-start gap-2 text-xs rounded px-2 py-1.5 ${\n d.severity === 'error' ? 'bg-status-error-bg text-status-error-text' : 'bg-status-warning-bg text-status-warning-text'\n }`}>\n <AlertTriangle className=\"h-3 w-3 mt-0.5 flex-shrink-0\" />\n <div>\n <span>{resolveDiscrepancyDescription(d.description, d.foundValue)}</span>\n {(d.expectedValue || d.foundValue) && (\n <div className=\"mt-0.5 text-overline opacity-80\">\n {d.expectedValue && <span>{t('inbox_ops.discrepancy.expected', 'Expected')}: {d.expectedValue}</span>}\n {d.expectedValue && d.foundValue && <span> \u00B7 </span>}\n {d.foundValue && <span>{t('inbox_ops.discrepancy.found', 'Found')}: {d.foundValue}</span>}\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n )\n })()}\n\n {/* Actions */}\n <div>\n <h3 className=\"font-semibold text-sm mb-2\">{t('inbox_ops.actions', 'Proposed Actions')}</h3>\n {actions.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">{t('inbox_ops.no_actions', 'No actionable items detected in this thread')}</p>\n ) : (\n <div className=\"space-y-3\">\n {actions.map((action) => (\n <div key={action.id}>\n <ActionCard\n action={action}\n discrepancies={discrepancies}\n actionTypeLabels={actionTypeLabels}\n onAccept={handleAcceptAction}\n onReject={handleRejectAction}\n onRetry={handleAcceptAction}\n onEdit={handleEditAction}\n translatedDescription={showTranslation ? translation?.actions[action.id] : undefined}\n resolveDiscrepancyDescription={resolveDiscrepancyDescription}\n />\n {action.actionType === 'draft_reply' && (action.status === 'executed' || action.status === 'accepted') && (\n <div className=\"mt-2 pl-7\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-11 md:h-9\"\n disabled={sendingReplyId === action.id}\n onClick={() => handleSendReply(action.id)}\n >\n {sendingReplyId === action.id ? (\n <Loader2 className=\"h-4 w-4 animate-spin mr-1\" />\n ) : (\n <ExternalLink className=\"h-4 w-4 mr-1\" />\n )}\n {sendingReplyId === action.id\n ? t('inbox_ops.reply.sending', 'Sending...')\n : t('inbox_ops.reply.send', 'Send Reply')}\n </Button>\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n </>\n ) : null}\n </div>\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { LoadingMessage, ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { useT, useLocale } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport {\n ArrowLeft,\n CheckCircle,\n XCircle,\n AlertTriangle,\n CheckCheck,\n Loader2,\n ExternalLink,\n RefreshCw,\n Users,\n Languages,\n Pencil,\n} from 'lucide-react'\nimport type { ProposalTranslationEntry } from '../../../../data/entities'\nimport type { ProposalDetail, ActionDetail, DiscrepancyDetail, EmailDetail } from '../../../../components/proposals/types'\nimport { ActionCard, ConfidenceBadge, useActionTypeLabels, useDiscrepancyDescriptions } from '../../../../components/proposals/ActionCard'\nimport { CategoryBadge, CATEGORY_CONFIG, ALL_CATEGORIES, useCategoryLabels } from '../../../../components/proposals/CategoryBadge'\nimport { hasContactNameIssue } from '../../../../lib/contactValidation'\nimport { EditActionDialog } from '../../../../components/proposals/EditActionDialog'\n\nfunction EmailThreadViewer({ email }: { email: EmailDetail | null }) {\n const t = useT()\n if (!email) return null\n\n const messages = email.threadMessages || []\n\n return (\n <div className=\"space-y-3\">\n <h3 className=\"font-semibold text-sm\">{t('inbox_ops.email_thread', 'Email Thread')}</h3>\n {messages.length > 0 ? (\n messages.map((msg, index) => (\n <div key={index} className=\"border rounded-lg p-3 md:p-4 bg-card\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"text-sm font-medium truncate\">\n {msg.from?.name || msg.from?.email || t('inbox_ops.sender_unknown', 'Unknown')}\n </div>\n <div className=\"text-xs text-muted-foreground truncate\">{msg.from?.email}</div>\n </div>\n <span className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {msg.date ? new Date(msg.date).toLocaleString([], { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) : ''}\n </span>\n </div>\n <div className=\"text-sm whitespace-pre-wrap text-foreground/80\">{msg.body}</div>\n </div>\n ))\n ) : email.cleanedText ? (\n <div className=\"border rounded-lg p-3 md:p-4 bg-card\">\n <div className=\"text-sm whitespace-pre-wrap text-foreground/80\">{email.cleanedText}</div>\n </div>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{t('inbox_ops.no_email_content', 'No email content available')}</p>\n )}\n </div>\n )\n}\n\nfunction CategoryEditDropdown({\n currentCategory,\n onSelect,\n disabled,\n}: {\n currentCategory: string | null | undefined\n onSelect: (category: string) => void\n disabled: boolean\n}) {\n const t = useT()\n const labels = useCategoryLabels()\n const [isOpen, setIsOpen] = React.useState(false)\n const dropdownRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n }\n }\n function handleEscape(event: KeyboardEvent) {\n if (event.key === 'Escape') setIsOpen(false)\n }\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n }\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n }\n }, [isOpen])\n\n return (\n <div className=\"relative inline-block\" ref={dropdownRef}>\n <div className=\"flex items-center gap-1\">\n <CategoryBadge category={currentCategory} />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-6 w-6 p-0\"\n onClick={() => setIsOpen(!isOpen)}\n disabled={disabled}\n title={t('inbox_ops.recategorize', 'Change Category')}\n >\n <Pencil className=\"h-3 w-3\" />\n </Button>\n </div>\n {isOpen && (\n <div className=\"absolute top-full left-0 mt-1 z-dropdown w-48 rounded-md border bg-popover shadow-md\">\n <div className=\"p-1\">\n {ALL_CATEGORIES.map((cat) => {\n const config = CATEGORY_CONFIG[cat]\n const { Icon } = config\n return (\n <Button\n key={cat}\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className={`flex items-center gap-2 w-full justify-start rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground ${currentCategory === cat ? 'bg-accent' : ''}`}\n onClick={() => { onSelect(cat); setIsOpen(false) }}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {labels[cat] || cat}\n </Button>\n )\n })}\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default function ProposalDetailPage({ params }: { params?: { id?: string } }) {\n const t = useT()\n const locale = useLocale()\n const router = useRouter()\n const proposalId = params?.id\n\n const [proposal, setProposal] = React.useState<ProposalDetail | null>(null)\n const [actions, setActions] = React.useState<ActionDetail[]>([])\n const [discrepancies, setDiscrepancies] = React.useState<DiscrepancyDetail[]>([])\n const [email, setEmail] = React.useState<EmailDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n const [isProcessing, setIsProcessing] = React.useState(false)\n\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const { runMutation } = useGuardedMutation<Record<string, unknown>>({\n contextId: 'inbox-ops-proposal-detail',\n })\n const actionTypeLabels = useActionTypeLabels()\n const resolveDiscrepancyDescription = useDiscrepancyDescriptions()\n const [editingAction, setEditingAction] = React.useState<ActionDetail | null>(null)\n const [sendingReplyId, setSendingReplyId] = React.useState<string | null>(null)\n\n const [translation, setTranslation] = React.useState<ProposalTranslationEntry | null>(null)\n const [isTranslating, setIsTranslating] = React.useState(false)\n const [showTranslation, setShowTranslation] = React.useState(false)\n\n const handleEditAction = React.useCallback((action: ActionDetail) => {\n if (action.actionType === 'create_order' || action.actionType === 'create_quote') {\n const kind = action.actionType === 'create_order' ? 'order' : 'quote'\n try {\n sessionStorage.setItem(\n 'inbox_ops.orderDraft',\n JSON.stringify({\n actionId: action.id,\n proposalId: action.proposalId,\n payload: action.payload,\n }),\n )\n } catch { /* sessionStorage unavailable */ }\n router.push(`/backend/sales/documents/create?kind=${kind}&fromInboxAction=${encodeURIComponent(action.id)}`)\n return\n }\n if (action.actionType === 'create_product') {\n try {\n sessionStorage.setItem(\n 'inbox_ops.productDraft',\n JSON.stringify({\n actionId: action.id,\n proposalId: action.proposalId,\n payload: action.payload,\n }),\n )\n } catch { /* sessionStorage unavailable */ }\n router.push(`/backend/catalog/products/create?fromInboxAction=${encodeURIComponent(action.id)}`)\n return\n }\n setEditingAction(action)\n }, [router])\n\n const handleTranslate = React.useCallback(async () => {\n if (!proposalId) return\n setIsTranslating(true)\n const result = await runMutation({\n operation: () => apiCall<{ translation: ProposalTranslationEntry; cached: boolean }>(\n `/api/inbox_ops/proposals/${proposalId}/translate`,\n { method: 'POST', body: JSON.stringify({ targetLocale: locale }) },\n ),\n context: {},\n })\n if (result?.ok && result.result?.translation) {\n setTranslation(result.result.translation)\n setShowTranslation(true)\n } else {\n const detail = (result?.result as Record<string, unknown> | null)?.error\n flash(detail ? `${t('inbox_ops.translate.failed', 'Translation failed')}: ${detail}` : t('inbox_ops.translate.failed', 'Translation failed'), 'error')\n }\n setIsTranslating(false)\n }, [proposalId, locale, t, runMutation])\n\n const handleCategorize = React.useCallback(async (category: string) => {\n if (!proposalId) return\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean; category: string; previousCategory: string | null }>(\n `/api/inbox_ops/proposals/${proposalId}/categorize`,\n { method: 'POST', body: JSON.stringify({ category }) },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n setProposal((prev) => prev ? { ...prev, category: result.result!.category } : prev)\n } else {\n flash(t('inbox_ops.flash.save_failed', 'Failed to save'), 'error')\n }\n }, [proposalId, t, runMutation])\n\n const loadData = React.useCallback(async () => {\n if (!proposalId) return\n setIsLoading(true)\n setError(null)\n setIsNotFound(false)\n try {\n const result = await apiCall<{\n proposal: ProposalDetail\n actions: ActionDetail[]\n discrepancies: DiscrepancyDetail[]\n email: EmailDetail\n }>(`/api/inbox_ops/proposals/${proposalId}`)\n if (result?.ok && result.result) {\n setProposal(result.result.proposal)\n setActions(result.result.actions || [])\n setDiscrepancies(result.result.discrepancies || [])\n setEmail(result.result.email)\n } else if (result?.status === 404) {\n setIsNotFound(true)\n } else {\n setError(t('inbox_ops.flash.load_failed', 'Failed to load proposal'))\n }\n } catch {\n setError(t('inbox_ops.flash.load_failed', 'Failed to load proposal'))\n }\n setIsLoading(false)\n }, [proposalId, t])\n\n React.useEffect(() => { loadData() }, [loadData])\n\n const handleAcceptAction = React.useCallback(async (actionId: string) => {\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean; error?: string }>(\n `/api/inbox_ops/proposals/${proposalId}/actions/${actionId}/accept`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.flash.action_executed', 'Action executed'), 'success')\n await loadData()\n } else {\n flash(result?.result?.error || t('inbox_ops.flash.action_execute_failed', 'Failed to execute action'), 'error')\n }\n setIsProcessing(false)\n }, [proposalId, loadData, t, runMutation])\n\n const handleRejectAction = React.useCallback(async (actionId: string) => {\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean }>(\n `/api/inbox_ops/proposals/${proposalId}/actions/${actionId}/reject`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.flash.action_rejected', 'Action rejected'), 'success')\n await loadData()\n } else {\n flash(t('inbox_ops.flash.action_reject_failed', 'Failed to reject action'), 'error')\n }\n setIsProcessing(false)\n }, [proposalId, loadData, runMutation])\n\n const handleAcceptAll = React.useCallback(async () => {\n const pendingActions = actions.filter((a) => a.status === 'pending')\n const pendingCount = pendingActions.length\n const nameIssueCount = pendingActions.filter((a) => hasContactNameIssue(a)).length\n\n const confirmText = nameIssueCount > 0\n ? t('inbox_ops.action.accept_all_confirm_with_skip', 'Execute {count} pending actions? {skipCount} contact actions will be skipped due to missing names.')\n .replace('{count}', String(pendingCount))\n .replace('{skipCount}', String(nameIssueCount))\n : t('inbox_ops.action.accept_all_confirm', 'Execute {count} pending actions?').replace('{count}', String(pendingCount))\n\n const confirmed = await confirm({\n title: t('inbox_ops.action.accept_all', 'Accept All'),\n text: confirmText,\n })\n if (!confirmed) return\n\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean; succeeded: number; failed: number }>(\n `/api/inbox_ops/proposals/${proposalId}/accept-all`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n const msg = result.result.failed > 0\n ? t('inbox_ops.flash.accept_all_partial', '{succeeded} actions executed, {failed} failed')\n .replace('{succeeded}', String(result.result.succeeded))\n .replace('{failed}', String(result.result.failed))\n : t('inbox_ops.flash.accept_all_success', '{succeeded} actions executed')\n .replace('{succeeded}', String(result.result.succeeded))\n flash(msg, 'success')\n await loadData()\n } else {\n flash(t('inbox_ops.flash.accept_all_failed', 'Failed to accept all actions'), 'error')\n }\n setIsProcessing(false)\n }, [proposalId, actions, confirm, t, loadData, runMutation])\n\n const handleRejectAll = React.useCallback(async () => {\n const confirmed = await confirm({\n title: t('inbox_ops.action.reject_all', 'Reject Proposal'),\n text: t('inbox_ops.action.reject_all_confirm', 'Reject all pending actions in this proposal?'),\n })\n if (!confirmed) return\n\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean }>(\n `/api/inbox_ops/proposals/${proposalId}/reject`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.action.proposal_rejected', 'Proposal rejected'), 'success')\n await loadData()\n }\n setIsProcessing(false)\n }, [proposalId, confirm, t, loadData, runMutation])\n\n const handleRetryExtraction = React.useCallback(async () => {\n if (!email) return\n setIsProcessing(true)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean }>(\n `/api/inbox_ops/emails/${email.id}/reprocess`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.flash.reprocessing_started', 'Reprocessing started'), 'success')\n await loadData()\n }\n setIsProcessing(false)\n }, [email, loadData, runMutation])\n\n const handleSendReply = React.useCallback(async (actionId: string) => {\n setSendingReplyId(actionId)\n const result = await runMutation({\n operation: () => apiCall<{ ok: boolean; error?: string }>(\n `/api/inbox_ops/proposals/${proposalId}/replies/${actionId}/send`,\n { method: 'POST' },\n ),\n context: {},\n })\n if (result?.ok && result.result?.ok) {\n flash(t('inbox_ops.reply.sent_success', 'Reply sent successfully'), 'success')\n await loadData()\n } else {\n flash(result?.result?.error || t('inbox_ops.flash.send_reply_failed', 'Failed to send reply'), 'error')\n }\n setSendingReplyId(null)\n }, [proposalId, t, loadData, runMutation])\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('inbox_ops.loading_proposal', 'Loading proposal...')} />\n </PageBody>\n </Page>\n )\n }\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('inbox_ops.proposal.notFound', 'Proposal not found.')}\n backHref=\"/backend/inbox-ops\"\n backLabel={t('inbox_ops.proposal.backToList', 'Back to inbox')}\n />\n </PageBody>\n </Page>\n )\n }\n if (error) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage label={error} />\n </PageBody>\n </Page>\n )\n }\n\n const pendingActions = actions.filter((a) => a.status === 'pending')\n const emailIsProcessing = email?.status === 'processing'\n const emailFailed = email?.status === 'failed'\n\n return (\n <Page>\n {ConfirmDialogElement}\n {editingAction && (\n <EditActionDialog\n action={editingAction}\n actionTypeLabels={actionTypeLabels}\n onClose={() => setEditingAction(null)}\n onSaved={loadData}\n />\n )}\n\n <div className=\"flex items-center justify-between px-4 py-3 md:px-6 md:py-4 border-b bg-background\">\n <div className=\"flex items-center gap-2 md:gap-3 min-w-0\">\n <Link href=\"/backend/inbox-ops\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\">\n <ArrowLeft className=\"h-4 w-4\" />\n </Button>\n </Link>\n <div className=\"min-w-0 flex-1\">\n <h1 className=\"text-base md:text-lg font-semibold truncate\">{email?.subject || t('inbox_ops.proposal', 'Proposal')}</h1>\n <p className=\"text-xs text-muted-foreground truncate\">\n {email?.forwardedByName || email?.forwardedByAddress} \u00B7 {email?.receivedAt && new Date(email.receivedAt).toLocaleString()}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n {pendingActions.length > 0 && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-11 md:h-9 text-destructive border-destructive/30 hover:bg-destructive/10\"\n onClick={handleRejectAll}\n disabled={isProcessing}\n >\n <XCircle className=\"h-4 w-4 mr-1\" />\n <span className=\"hidden md:inline\">{t('inbox_ops.action.reject_all', 'Reject Proposal')}</span>\n </Button>\n )}\n {pendingActions.length > 1 && (\n <Button type=\"button\" size=\"sm\" className=\"h-11 md:h-9\" onClick={handleAcceptAll} disabled={isProcessing}>\n {isProcessing ? <Loader2 className=\"h-4 w-4 animate-spin mr-1\" /> : <CheckCheck className=\"h-4 w-4 mr-1\" />}\n <span className=\"hidden md:inline\">{t('inbox_ops.action.accept_all', 'Accept All')}</span>\n </Button>\n )}\n </div>\n </div>\n\n <PageBody>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-6\">\n {/* Left panel: Email Thread */}\n <div>\n <EmailThreadViewer email={email} />\n </div>\n\n {/* Right panel: Summary + Actions */}\n <div className=\"space-y-4\">\n {emailIsProcessing ? (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <Loader2 className=\"h-8 w-8 animate-spin text-primary mb-3\" />\n <p className=\"text-sm text-muted-foreground\">{t('inbox_ops.extraction_loading', 'AI is analyzing this thread...')}</p>\n </div>\n ) : emailFailed ? (\n <div className=\"border rounded-lg p-4 bg-status-error-bg border-status-error-border\">\n <div className=\"flex items-center gap-2 mb-2\">\n <AlertTriangle className=\"h-5 w-5 text-status-error-icon\" />\n <span className=\"text-sm font-medium text-status-error-text\">{t('inbox_ops.extraction_failed', 'Extraction failed')}</span>\n </div>\n {email?.processingError && (\n <p className=\"text-xs text-status-error-text mb-3\">{email.processingError}</p>\n )}\n <Button type=\"button\" size=\"sm\" variant=\"outline\" onClick={handleRetryExtraction} disabled={isProcessing}>\n <RefreshCw className=\"h-4 w-4 mr-1\" />\n {t('inbox_ops.action.retry', 'Retry')}\n </Button>\n </div>\n ) : proposal ? (\n <>\n {/* Summary */}\n <div className=\"border rounded-lg p-3 md:p-4\">\n <div className=\"flex items-center justify-between mb-2\">\n <h3 className=\"font-semibold text-sm\">{t('inbox_ops.summary', 'Summary')}</h3>\n {(proposal.workingLanguage || 'en') !== locale && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 text-xs\"\n onClick={showTranslation ? () => setShowTranslation(false) : handleTranslate}\n disabled={isTranslating}\n >\n {isTranslating ? (\n <Loader2 className=\"h-3 w-3 animate-spin mr-1\" />\n ) : (\n <Languages className=\"h-3 w-3 mr-1\" />\n )}\n {showTranslation\n ? t('inbox_ops.translate.show_original', 'Show original')\n : t('inbox_ops.translate.translate', 'Translate')}\n </Button>\n )}\n </div>\n <p className=\"text-sm text-foreground/80 mb-3\">\n {showTranslation && translation ? translation.summary : proposal.summary}\n </p>\n\n <div className=\"flex items-center gap-4 mb-3 flex-wrap\">\n <div>\n <span className=\"text-xs text-muted-foreground\">{t('inbox_ops.confidence', 'Confidence')}</span>\n <ConfidenceBadge value={proposal.confidence} />\n </div>\n <div>\n <span className=\"text-xs text-muted-foreground block\">{t('inbox_ops.category', 'Category')}</span>\n <CategoryEditDropdown\n currentCategory={proposal.category}\n onSelect={handleCategorize}\n disabled={isProcessing}\n />\n </div>\n </div>\n\n {proposal.possiblyIncomplete && (\n <div className=\"flex items-center gap-2 text-xs text-status-warning-text bg-status-warning-bg rounded px-2 py-1 mb-3\">\n <AlertTriangle className=\"h-3 w-3\" />\n {t('inbox_ops.possibly_incomplete', 'This thread appears to be a partial forward')}\n </div>\n )}\n\n {/* Participants */}\n {proposal.participants.length > 0 && (\n <div>\n <h4 className=\"text-xs font-medium text-muted-foreground mb-1\">{t('inbox_ops.participants', 'Participants')}</h4>\n <div className=\"space-y-1\">\n {proposal.participants.map((p, idx) => (\n <div key={idx} className=\"flex items-center gap-2 text-sm\">\n <Users className=\"h-3 w-3 text-muted-foreground\" />\n <span>{p.name}</span>\n <span className=\"text-xs text-muted-foreground\">({p.role})</span>\n {p.matchedContactId && <CheckCircle className=\"h-3 w-3 text-status-success-icon\" />}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n\n {/* Discrepancies not tied to a specific action */}\n {(() => {\n const actionIds = new Set(actions.map((a) => a.id))\n const general = discrepancies.filter((d) => !d.resolved && (!d.actionId || !actionIds.has(d.actionId)))\n if (general.length === 0) return null\n return (\n <div className=\"border rounded-lg p-3 md:p-4 bg-status-warning-bg border-status-warning-border\">\n <div className=\"flex items-center gap-2 mb-2\">\n <AlertTriangle className=\"h-4 w-4 text-status-warning-icon\" />\n <h3 className=\"font-semibold text-sm text-status-warning-text\">{t('inbox_ops.discrepancies', 'Issues Detected')}</h3>\n </div>\n <div className=\"space-y-1.5\">\n {general.map((d) => (\n <div key={d.id} className={`flex items-start gap-2 text-xs rounded px-2 py-1.5 ${\n d.severity === 'error' ? 'bg-status-error-bg text-status-error-text' : 'bg-status-warning-bg text-status-warning-text'\n }`}>\n <AlertTriangle className=\"h-3 w-3 mt-0.5 flex-shrink-0\" />\n <div>\n <span>{resolveDiscrepancyDescription(d.description, d.foundValue)}</span>\n {(d.expectedValue || d.foundValue) && (\n <div className=\"mt-0.5 text-overline opacity-80\">\n {d.expectedValue && <span>{t('inbox_ops.discrepancy.expected', 'Expected')}: {d.expectedValue}</span>}\n {d.expectedValue && d.foundValue && <span> \u00B7 </span>}\n {d.foundValue && <span>{t('inbox_ops.discrepancy.found', 'Found')}: {d.foundValue}</span>}\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n )\n })()}\n\n {/* Actions */}\n <div>\n <h3 className=\"font-semibold text-sm mb-2\">{t('inbox_ops.actions', 'Proposed Actions')}</h3>\n {actions.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">{t('inbox_ops.no_actions', 'No actionable items detected in this thread')}</p>\n ) : (\n <div className=\"space-y-3\">\n {actions.map((action) => (\n <div key={action.id}>\n <ActionCard\n action={action}\n discrepancies={discrepancies}\n actionTypeLabels={actionTypeLabels}\n onAccept={handleAcceptAction}\n onReject={handleRejectAction}\n onRetry={handleAcceptAction}\n onEdit={handleEditAction}\n translatedDescription={showTranslation ? translation?.actions[action.id] : undefined}\n resolveDiscrepancyDescription={resolveDiscrepancyDescription}\n />\n {action.actionType === 'draft_reply' && (action.status === 'executed' || action.status === 'accepted') && (\n <div className=\"mt-2 pl-7\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n className=\"h-11 md:h-9\"\n disabled={sendingReplyId === action.id}\n onClick={() => handleSendReply(action.id)}\n >\n {sendingReplyId === action.id ? (\n <Loader2 className=\"h-4 w-4 animate-spin mr-1\" />\n ) : (\n <ExternalLink className=\"h-4 w-4 mr-1\" />\n )}\n {sendingReplyId === action.id\n ? t('inbox_ops.reply.sending', 'Sending...')\n : t('inbox_ops.reply.send', 'Send Reply')}\n </Button>\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n </>\n ) : null}\n </div>\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["pendingActions"]
|
|
7
7
|
}
|
|
@@ -32,7 +32,7 @@ import { cn } from "@open-mercato/shared/lib/utils";
|
|
|
32
32
|
import {
|
|
33
33
|
LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID
|
|
34
34
|
} from "@open-mercato/shared/modules/integrations/types";
|
|
35
|
-
import { LoadingMessage, ErrorMessage } from "@open-mercato/ui/backend/detail";
|
|
35
|
+
import { LoadingMessage, ErrorMessage, RecordNotFoundState } from "@open-mercato/ui/backend/detail";
|
|
36
36
|
import { LogList } from "@open-mercato/ui/backend/LogList";
|
|
37
37
|
import { Activity, AlertTriangle, Bell, Calendar, CheckCircle2, CreditCard, FileText, FileX, HardDrive, Key, MessageSquare, RefreshCw, Settings, Truck, Webhook, XCircle, Zap } from "lucide-react";
|
|
38
38
|
import { EmptyState } from "@open-mercato/ui/primitives/empty-state";
|
|
@@ -274,6 +274,7 @@ function IntegrationDetailPage({ params }) {
|
|
|
274
274
|
const [detail, setDetail] = React.useState(null);
|
|
275
275
|
const [isLoading, setIsLoading] = React.useState(true);
|
|
276
276
|
const [error, setError] = React.useState(null);
|
|
277
|
+
const [isNotFound, setIsNotFound] = React.useState(false);
|
|
277
278
|
const [credValues, setCredValues] = React.useState({});
|
|
278
279
|
const [credentialsFormKey, setCredentialsFormKey] = React.useState(0);
|
|
279
280
|
const [isSavingCredentials, setIsSavingCredentials] = React.useState(false);
|
|
@@ -300,6 +301,7 @@ function IntegrationDetailPage({ params }) {
|
|
|
300
301
|
return;
|
|
301
302
|
}
|
|
302
303
|
if (showLoading) setError(null);
|
|
304
|
+
if (showLoading) setIsNotFound(false);
|
|
303
305
|
if (showLoading) setIsLoading(true);
|
|
304
306
|
try {
|
|
305
307
|
const call = await apiCall(
|
|
@@ -308,7 +310,11 @@ function IntegrationDetailPage({ params }) {
|
|
|
308
310
|
{ fallback: null }
|
|
309
311
|
);
|
|
310
312
|
if (!call.ok || !call.result) {
|
|
311
|
-
if (
|
|
313
|
+
if (call.status === 404) {
|
|
314
|
+
if (showLoading) setIsNotFound(true);
|
|
315
|
+
} else {
|
|
316
|
+
if (showLoading) setError(t("integrations.detail.loadError", "Failed to load integration"));
|
|
317
|
+
}
|
|
312
318
|
if (showLoading) setIsLoading(false);
|
|
313
319
|
return;
|
|
314
320
|
}
|
|
@@ -785,6 +791,16 @@ function IntegrationDetailPage({ params }) {
|
|
|
785
791
|
};
|
|
786
792
|
}, [activeTab, refreshRunActivity, runIdFromUrl]);
|
|
787
793
|
if (isLoading) return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(LoadingMessage, { label: t("integrations.detail.title") }) }) });
|
|
794
|
+
if (isNotFound) {
|
|
795
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
796
|
+
RecordNotFoundState,
|
|
797
|
+
{
|
|
798
|
+
label: t("integrations.detail.notFound", "Integration not found."),
|
|
799
|
+
backHref: "/backend/integrations",
|
|
800
|
+
backLabel: t("integrations.detail.backToList", "Back to integrations")
|
|
801
|
+
}
|
|
802
|
+
) }) });
|
|
803
|
+
}
|
|
788
804
|
if (error || !detail || !resolvedIntegration || !resolvedState) {
|
|
789
805
|
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(ErrorMessage, { label: error ?? t("integrations.detail.loadError") }) }) });
|
|
790
806
|
}
|