fix(ai-advice,ui): Bearer auth for proxy gateways + un-pin contact card + VN diacritics
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 18s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 1m15s
Deploy / Build API Image (push) Failing after 33s
Deploy / Build Web Image (push) Failing after 14s
Deploy / Build AI Services Image (push) Failing after 13s
E2E Tests / Playwright E2E (push) Failing after 11s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 3s
Security Scanning / Trivy Scan — API Image (push) Failing after 2m1s
Security Scanning / Trivy Scan — Web Image (push) Failing after 51s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 47s
Security Scanning / Trivy Filesystem Scan (push) Failing after 35s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Security Scanning / Security Gate (push) Failing after 1s
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 18s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 1m15s
Deploy / Build API Image (push) Failing after 33s
Deploy / Build Web Image (push) Failing after 14s
Deploy / Build AI Services Image (push) Failing after 13s
E2E Tests / Playwright E2E (push) Failing after 11s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 3s
Security Scanning / Trivy Scan — API Image (push) Failing after 2m1s
Security Scanning / Trivy Scan — Web Image (push) Failing after 51s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 47s
Security Scanning / Trivy Filesystem Scan (push) Failing after 35s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Security Scanning / Security Gate (push) Failing after 1s
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
- AI advice handler now sends both `x-api-key` and `Authorization: Bearer` so proxy gateways (e.g. chat.trollllm.xyz) accept the request. Native Anthropic ignores the extra header. - Remove `lg:sticky lg:top-20` from listing detail contact card — sidebar now scrolls with the page. - Fix missing Vietnamese diacritics on AI estimate button: "Dinh gia AI" -> "Định giá AI", "Dang dinh gia..." -> "Đang định giá...". Tests updated accordingly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -207,7 +207,11 @@ export class GetListingAiAdviceHandler
|
|||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
// Support both native Anthropic (x-api-key) and proxy-style gateways
|
||||||
|
// that expect Bearer auth (e.g. chat.trollllm.xyz). Anthropic ignores
|
||||||
|
// unknown headers, so sending both is safe.
|
||||||
'x-api-key': args.apiKey,
|
'x-api-key': args.apiKey,
|
||||||
|
Authorization: `Bearer ${args.apiKey}`,
|
||||||
'anthropic-version': '2023-06-01',
|
'anthropic-version': '2023-06-01',
|
||||||
'anthropic-beta': 'prompt-caching-2024-07-31',
|
'anthropic-beta': 'prompt-caching-2024-07-31',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ export function ListingDetailClient({ listing }: ListingDetailClientProps) {
|
|||||||
{/* Sidebar */}
|
{/* Sidebar */}
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Contact card */}
|
{/* Contact card */}
|
||||||
<Card className="lg:sticky lg:top-20">
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Liên hệ</CardTitle>
|
<CardTitle>Liên hệ</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|||||||
@@ -20,20 +20,20 @@ describe('AiEstimateButton', () => {
|
|||||||
|
|
||||||
it('renders the button', () => {
|
it('renders the button', () => {
|
||||||
render(<AiEstimateButton listingId="listing-1" />);
|
render(<AiEstimateButton listingId="listing-1" />);
|
||||||
expect(screen.getByText('Dinh gia AI')).toBeInTheDocument();
|
expect(screen.getByText('Định giá AI')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls mutate when clicked', async () => {
|
it('calls mutate when clicked', async () => {
|
||||||
const user = userEvent.setup();
|
const user = userEvent.setup();
|
||||||
render(<AiEstimateButton listingId="listing-1" />);
|
render(<AiEstimateButton listingId="listing-1" />);
|
||||||
|
|
||||||
await user.click(screen.getByText('Dinh gia AI'));
|
await user.click(screen.getByText('Định giá AI'));
|
||||||
expect(mockMutate).toHaveBeenCalledWith('listing-1', expect.any(Object));
|
expect(mockMutate).toHaveBeenCalledWith('listing-1', expect.any(Object));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders as a button element', () => {
|
it('renders as a button element', () => {
|
||||||
render(<AiEstimateButton listingId="listing-1" />);
|
render(<AiEstimateButton listingId="listing-1" />);
|
||||||
expect(screen.getByRole('button', { name: /Dinh gia AI/ })).toBeInTheDocument();
|
expect(screen.getByRole('button', { name: /Định giá AI/ })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ describe('AiEstimateButton - loading state', () => {
|
|||||||
|
|
||||||
// This test validates the loading button text exists in the component
|
// This test validates the loading button text exists in the component
|
||||||
render(<AiEstimateButton listingId="listing-1" />);
|
render(<AiEstimateButton listingId="listing-1" />);
|
||||||
// Component shows 'Dinh gia AI' or 'Dang dinh gia...' based on isPending
|
// Component shows 'Định giá AI' or 'Đang định giá...' based on isPending
|
||||||
expect(screen.getByRole('button')).toBeInTheDocument();
|
expect(screen.getByRole('button')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export function AiEstimateButton({ listingId }: AiEstimateButtonProps) {
|
|||||||
d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"
|
d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
{mutation.isPending ? 'Dang dinh gia...' : 'Dinh gia AI'}
|
{mutation.isPending ? 'Đang định giá...' : 'Định giá AI'}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user