feat: add chat components from jarvis frontend
- Migrated Chat.tsx with message handling and UI structure - Migrated ChatInput.tsx with character limits and keyboard shortcuts - Migrated MessageList.tsx with thinking/reasoning display - Migrated ConversationSidebar.tsx (simplified placeholder) - Migrated BackendStatusBanner.tsx (simplified placeholder) - Created components/chat/index.ts barrel export - Created app/chat/page.tsx placeholder route These components are adapted from jarvis-fe but not yet fully functional: - API calls placeholder (need to wire up /api/brain/query) - Auth hooks stubbed (need useAuth implementation) - Project/conversation hooks stubbed (need implementation) - Imports changed from @jarvis/* to @mosaic/* Next steps: - Implement missing hooks (useAuth, useProjects, useConversations, useApi) - Wire up backend API endpoints - Add proper TypeScript types - Implement full conversation management
This commit is contained in:
98
apps/web/src/components/chat/BackendStatusBanner.tsx
Normal file
98
apps/web/src/components/chat/BackendStatusBanner.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
/**
|
||||
* Banner that displays when the backend is unavailable.
|
||||
* Shows error message, countdown to next retry, and manual retry button.
|
||||
*
|
||||
* TODO: Integrate with actual backend status checking hook
|
||||
*/
|
||||
export function BackendStatusBanner() {
|
||||
const [isAvailable, setIsAvailable] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [retryIn, setRetryIn] = useState(0);
|
||||
|
||||
// TODO: Replace with actual useBackendStatus hook
|
||||
// const { isAvailable, error, retryIn, manualRetry } = useBackendStatus();
|
||||
|
||||
const manualRetry = () => {
|
||||
// TODO: Implement manual retry logic
|
||||
console.log("Manual retry triggered");
|
||||
};
|
||||
|
||||
const handleSignOut = async () => {
|
||||
try {
|
||||
// TODO: Implement signOut
|
||||
// await signOut();
|
||||
} catch (error) {
|
||||
console.warn("Sign-out failed during backend unavailability:", error);
|
||||
}
|
||||
window.location.href = "/login";
|
||||
};
|
||||
|
||||
// Don't render if backend is available
|
||||
if (isAvailable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex items-center justify-between gap-4 px-4 py-2 text-sm"
|
||||
style={{
|
||||
backgroundColor: "#fef3c7", // amber-100
|
||||
borderBottom: "1px solid #fcd34d", // amber-300
|
||||
color: "#92400e", // amber-800
|
||||
}}
|
||||
role="alert"
|
||||
aria-live="polite"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-5 w-5 flex-shrink-0"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
{error || "Backend temporarily unavailable."}
|
||||
{retryIn > 0 && (
|
||||
<span className="ml-1">
|
||||
Retrying in {retryIn}s...
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={manualRetry}
|
||||
className="rounded px-3 py-1 text-xs font-medium transition-colors hover:opacity-80"
|
||||
style={{
|
||||
backgroundColor: "#fcd34d", // amber-300
|
||||
color: "#92400e", // amber-800
|
||||
}}
|
||||
>
|
||||
Retry Now
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSignOut}
|
||||
className="rounded px-3 py-1 text-xs font-medium transition-colors hover:opacity-80"
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
color: "#92400e", // amber-800
|
||||
border: "1px solid #fcd34d", // amber-300
|
||||
}}
|
||||
>
|
||||
Sign in again
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user