Drawer opens and closes
This commit is contained in:
parent
4330bd4b7c
commit
8f6c39c3f7
@ -15,8 +15,16 @@ import {
|
|||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
Avatar,
|
Avatar,
|
||||||
Grid
|
Drawer,
|
||||||
|
useTheme,
|
||||||
|
useMediaQuery,
|
||||||
|
Fab
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
import {
|
||||||
|
ChevronLeft,
|
||||||
|
ChevronRight,
|
||||||
|
Chat as ChatIcon
|
||||||
|
} from '@mui/icons-material';
|
||||||
import { useUser } from 'hooks/useUser';
|
import { useUser } from 'hooks/useUser';
|
||||||
import { ChatMessageBase, ChatMessage, ChatSession } from 'types/types';
|
import { ChatMessageBase, ChatMessage, ChatSession } from 'types/types';
|
||||||
import { ConversationHandle } from 'components/Conversation';
|
import { ConversationHandle } from 'components/Conversation';
|
||||||
@ -27,13 +35,20 @@ import { CandidateSessionsResponse } from 'services/api-client';
|
|||||||
import { CandidateInfo } from 'components/CandidateInfo';
|
import { CandidateInfo } from 'components/CandidateInfo';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
const DRAWER_WIDTH = 300;
|
||||||
|
const HANDLE_WIDTH = 48;
|
||||||
|
|
||||||
const CandidateChatPage = forwardRef<ConversationHandle, BackstoryPageProps>((props: BackstoryPageProps, ref) => {
|
const CandidateChatPage = forwardRef<ConversationHandle, BackstoryPageProps>((props: BackstoryPageProps, ref) => {
|
||||||
const { apiClient, candidate } = useUser();
|
const { apiClient, candidate } = useUser();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const theme = useTheme();
|
||||||
|
const isMdUp = useMediaQuery(theme.breakpoints.up('md'));
|
||||||
|
|
||||||
const {
|
const {
|
||||||
setSnack,
|
setSnack,
|
||||||
submitQuery,
|
submitQuery,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [sessions, setSessions] = useState<CandidateSessionsResponse | null>(null);
|
const [sessions, setSessions] = useState<CandidateSessionsResponse | null>(null);
|
||||||
const [chatSession, setChatSession] = useState<ChatSession | null>(null);
|
const [chatSession, setChatSession] = useState<ChatSession | null>(null);
|
||||||
const [messages, setMessages] = useState([]);
|
const [messages, setMessages] = useState([]);
|
||||||
@ -42,6 +57,14 @@ const CandidateChatPage = forwardRef<ConversationHandle, BackstoryPageProps>((pr
|
|||||||
const [streaming, setStreaming] = useState(false);
|
const [streaming, setStreaming] = useState(false);
|
||||||
const messagesEndRef = useRef(null);
|
const messagesEndRef = useRef(null);
|
||||||
|
|
||||||
|
// Drawer state - defaults to open on md+ screens or when no session is selected
|
||||||
|
const [drawerOpen, setDrawerOpen] = useState(() => isMdUp || !chatSession);
|
||||||
|
|
||||||
|
// Update drawer state when screen size or session changes
|
||||||
|
useEffect(() => {
|
||||||
|
setDrawerOpen(isMdUp || !chatSession);
|
||||||
|
}, [isMdUp, chatSession]);
|
||||||
|
|
||||||
// Load sessions for the candidate
|
// Load sessions for the candidate
|
||||||
const loadSessions = async () => {
|
const loadSessions = async () => {
|
||||||
if (!candidate) return;
|
if (!candidate) return;
|
||||||
@ -156,13 +179,8 @@ const CandidateChatPage = forwardRef<ConversationHandle, BackstoryPageProps>((pr
|
|||||||
navigate('/find-a-candidate');
|
navigate('/find-a-candidate');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const drawerContent = (
|
||||||
<Box ref={ref} sx={{ width: "100%", height: "100%", display: "flex", flexGrow: 1, flexDirection: "column" }}>
|
<Box sx={{ height: '100%', display: 'flex', flexDirection: 'column', p: 2 }}>
|
||||||
{candidate && <CandidateInfo action={`Chat with Backstory about ${candidate.firstName}`} elevation={4} candidate={candidate} sx={{ minHeight: "max-content" }} />}
|
|
||||||
|
|
||||||
< Box sx={{ display: "flex", mt: 1, gap: 1, height: "100%" }}>
|
|
||||||
{/* Sessions Sidebar */}
|
|
||||||
<Paper sx={{ p: 2, height: '100%', minWidth: { sm: "200px", md: "300px", lg: "400px" }, display: 'flex', flexDirection: 'column' }}>
|
|
||||||
<Typography variant="h6" gutterBottom>
|
<Typography variant="h6" gutterBottom>
|
||||||
Chat Sessions
|
Chat Sessions
|
||||||
{sessions && (
|
{sessions && (
|
||||||
@ -189,8 +207,13 @@ const CandidateChatPage = forwardRef<ConversationHandle, BackstoryPageProps>((pr
|
|||||||
{sessions.sessions.data.map((session: any) => (
|
{sessions.sessions.data.map((session: any) => (
|
||||||
<ListItem
|
<ListItem
|
||||||
key={session.id}
|
key={session.id}
|
||||||
// selected={chatSession?.id === session.id}
|
onClick={() => {
|
||||||
onClick={() => setChatSession(session)}
|
setChatSession(session);
|
||||||
|
// Auto-close drawer on smaller screens when session is selected
|
||||||
|
if (!isMdUp) {
|
||||||
|
setDrawerOpen(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
mb: 1,
|
mb: 1,
|
||||||
borderRadius: 1,
|
borderRadius: 1,
|
||||||
@ -215,10 +238,85 @@ const CandidateChatPage = forwardRef<ConversationHandle, BackstoryPageProps>((pr
|
|||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
const drawerHandle = (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: 'fixed',
|
||||||
|
left: drawerOpen ? DRAWER_WIDTH : 0,
|
||||||
|
top: '50%',
|
||||||
|
transform: 'translateY(-50%)',
|
||||||
|
zIndex: theme.zIndex.drawer + 1,
|
||||||
|
transition: theme.transitions.create('left', {
|
||||||
|
easing: theme.transitions.easing.sharp,
|
||||||
|
duration: theme.transitions.duration.standard,
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Fab
|
||||||
|
size="small"
|
||||||
|
color="primary"
|
||||||
|
onClick={() => setDrawerOpen(!drawerOpen)}
|
||||||
|
sx={{
|
||||||
|
borderRadius: '0 50% 50% 0',
|
||||||
|
width: 32,
|
||||||
|
height: 64,
|
||||||
|
minHeight: 64,
|
||||||
|
boxShadow: 2,
|
||||||
|
'&:hover': {
|
||||||
|
boxShadow: 4,
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{drawerOpen ? <ChevronLeft /> : <ChatIcon />}
|
||||||
|
</Fab>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box ref={ref} sx={{ width: "100%", height: "100%", display: "flex", flexGrow: 1, flexDirection: "column" }}>
|
||||||
|
{candidate && <CandidateInfo action={`Chat with Backstory about ${candidate.firstName}`} elevation={4} candidate={candidate} sx={{ minHeight: "max-content" }} />}
|
||||||
|
|
||||||
|
<Box sx={{ display: "flex", mt: 1, gap: 1, height: "100%", position: 'relative' }}>
|
||||||
|
{/* Drawer */}
|
||||||
|
<Drawer
|
||||||
|
variant="persistent"
|
||||||
|
anchor="left"
|
||||||
|
open={drawerOpen}
|
||||||
|
sx={{
|
||||||
|
width: drawerOpen ? DRAWER_WIDTH : 0,
|
||||||
|
flexShrink: 0,
|
||||||
|
'& .MuiDrawer-paper': {
|
||||||
|
width: DRAWER_WIDTH,
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
position: 'relative',
|
||||||
|
height: '100%',
|
||||||
|
border: 'none',
|
||||||
|
borderRight: '1px solid',
|
||||||
|
borderColor: 'divider',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{drawerContent}
|
||||||
|
</Drawer>
|
||||||
|
|
||||||
|
{/* Drawer Handle */}
|
||||||
|
{drawerHandle}
|
||||||
|
|
||||||
{/* Chat Interface */}
|
{/* Chat Interface */}
|
||||||
<Paper sx={{ display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
|
<Paper
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
flexGrow: 1,
|
||||||
|
transition: theme.transitions.create('margin', {
|
||||||
|
easing: theme.transitions.easing.sharp,
|
||||||
|
duration: theme.transitions.duration.standard,
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
>
|
||||||
{chatSession?.id ? (
|
{chatSession?.id ? (
|
||||||
<>
|
<>
|
||||||
{/* Messages Area */}
|
{/* Messages Area */}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user