adding in navbar and other components
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import Conversation from '@nirvana/core/models/conversation.model';
|
||||
import React from 'react';
|
||||
import { Typography } from '@mui/material';
|
||||
import User from '@nirvana/core/models/user.model';
|
||||
import useAuth from '../providers/AuthProvider';
|
||||
|
||||
type IConversationLabel = (
|
||||
| {
|
||||
conversationName?: string;
|
||||
users: User[];
|
||||
}
|
||||
| {
|
||||
conversationName: string;
|
||||
users?: User[];
|
||||
}
|
||||
) & { isSelected?: boolean };
|
||||
|
||||
/**
|
||||
* if there is a name in the conversation, then return that
|
||||
* if not, then return first three names
|
||||
*/
|
||||
export default function ConversationLabel({
|
||||
conversationName,
|
||||
users,
|
||||
isSelected = false,
|
||||
}: IConversationLabel) {
|
||||
const { user } = useAuth();
|
||||
|
||||
if (conversationName) {
|
||||
return (
|
||||
<Typography
|
||||
noWrap
|
||||
variant={'overline'}
|
||||
color={isSelected && 'primary'}
|
||||
sx={{ fontWeight: isSelected && 'bold' }}
|
||||
>
|
||||
{conversationName}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
const filteredUsers = users.filter((convoUser) => convoUser._id !== user._id);
|
||||
|
||||
if (filteredUsers.length === 1) {
|
||||
const firstName = filteredUsers[0].name;
|
||||
|
||||
return (
|
||||
<Typography
|
||||
noWrap
|
||||
variant={'overline'}
|
||||
color={isSelected && 'primary'}
|
||||
sx={{ fontWeight: isSelected && 'bold' }}
|
||||
>
|
||||
{firstName}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
if (filteredUsers.length > 1) {
|
||||
const firstNames = filteredUsers.map((filteredUser) => filteredUser.name);
|
||||
|
||||
const formattedFirstnames = firstNames.slice(0, -1).join(',') + ' and ' + firstNames.slice(-1);
|
||||
|
||||
return (
|
||||
<Typography
|
||||
noWrap
|
||||
variant={'overline'}
|
||||
color={isSelected && 'primary'}
|
||||
sx={{ fontWeight: isSelected && 'bold' }}
|
||||
>
|
||||
{formattedFirstnames}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Box, Paper, Typography } from '@mui/material';
|
||||
|
||||
import { KeyboardShortcuts } from '../util/keyboard';
|
||||
import React from 'react';
|
||||
import { blueGrey } from '@mui/material/colors';
|
||||
|
||||
export default function KeyboardShortcutLabel({
|
||||
label,
|
||||
}: {
|
||||
label: keyof typeof KeyboardShortcuts;
|
||||
}) {
|
||||
return (
|
||||
<Paper
|
||||
elevation={0}
|
||||
variant={'outlined'}
|
||||
sx={{
|
||||
px: 1,
|
||||
py: 0.25,
|
||||
bgcolor: blueGrey[50],
|
||||
color: blueGrey[300],
|
||||
border: 'none',
|
||||
}}
|
||||
>
|
||||
<Typography variant="caption">{label}</Typography>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Avatar, Box, Stack, Typography } from '@mui/material';
|
||||
|
||||
import React from 'react';
|
||||
import User from '@nirvana/core/models/user.model';
|
||||
|
||||
export default function UserDetailRow({
|
||||
user,
|
||||
rightContent,
|
||||
}: {
|
||||
user: User;
|
||||
rightContent?: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<Stack
|
||||
direction={'row'}
|
||||
alignItems="center"
|
||||
spacing={1}
|
||||
sx={{
|
||||
px: 1,
|
||||
}}
|
||||
>
|
||||
<Avatar src={user.picture} alt={user.givenName} />
|
||||
|
||||
<Stack>
|
||||
<Typography variant="subtitle2" color="info" gutterBottom={false}>
|
||||
{user.givenName}
|
||||
</Typography>
|
||||
<Typography variant={'overline'}>{user.email}</Typography>
|
||||
</Stack>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
ml: 'auto',
|
||||
}}
|
||||
>
|
||||
{rightContent}
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import { CircularProgress, IconButton, Input, Stack, Tooltip } from '@mui/material';
|
||||
import { FiSearch, FiUsers } from 'react-icons/fi';
|
||||
import React, { useCallback, useRef, useState } from 'react';
|
||||
import { useKeyPressEvent, useRendersCount } from 'react-use';
|
||||
|
||||
import KeyboardShortcutLabel from '../subcomponents/KeyboardShortcutLabel';
|
||||
import { KeyboardShortcuts } from '../util/keyboard';
|
||||
import NirvanaLogo from '../subcomponents/NirvanaLogo';
|
||||
import { blueGrey } from '@mui/material/colors';
|
||||
import useTerminal from './Terminal';
|
||||
|
||||
const Navbar = () => {
|
||||
const [searchQuery, setSearchQuery] = useState<string>('');
|
||||
|
||||
const searchRef = useRef<HTMLInputElement>(null);
|
||||
const onSearchFocus = useCallback(() => {
|
||||
if (searchRef?.current) searchRef.current.focus();
|
||||
}, [searchRef]);
|
||||
|
||||
useKeyPressEvent(KeyboardShortcuts.search.shortcutKey, onSearchFocus);
|
||||
|
||||
const handleSearchChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchQuery(e.target.value);
|
||||
},
|
||||
[setSearchQuery],
|
||||
);
|
||||
|
||||
const rendersCount = useRendersCount();
|
||||
console.warn('RENDER COUNT | NAVBAR | ', rendersCount);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent={'flex-start'}
|
||||
alignItems={'center'}
|
||||
spacing={2}
|
||||
sx={{
|
||||
WebkitAppRegion: 'drag',
|
||||
cursor: 'pointer',
|
||||
p: 2,
|
||||
}}
|
||||
>
|
||||
<NirvanaLogo />
|
||||
|
||||
<Stack
|
||||
direction={'row'}
|
||||
sx={{
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
bgcolor: blueGrey[100],
|
||||
opacity: '50%',
|
||||
borderRadius: 1,
|
||||
px: 1,
|
||||
py: 0.5,
|
||||
flex: 1,
|
||||
}}
|
||||
alignItems={'center'}
|
||||
spacing={1}
|
||||
>
|
||||
<FiSearch style={{ color: blueGrey[500] }} />
|
||||
|
||||
<Input
|
||||
onChange={handleSearchChange}
|
||||
value={searchQuery}
|
||||
placeholder={'Find or start a conversation'}
|
||||
inputRef={searchRef}
|
||||
/>
|
||||
|
||||
{/* {isSearching && <CircularProgress size={20} />} */}
|
||||
|
||||
{searchQuery ? (
|
||||
<KeyboardShortcutLabel label={KeyboardShortcuts.escape.label} />
|
||||
) : (
|
||||
<KeyboardShortcutLabel label={KeyboardShortcuts.search.label} />
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
<Tooltip title={'Group conversation'}>
|
||||
<IconButton color="default" size={'small'}>
|
||||
<FiUsers />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default Navbar;
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Container, Grid } from '@mui/material';
|
||||
|
||||
import Navbar from './Navbar';
|
||||
import React from 'react';
|
||||
import { blueGrey } from '@mui/material/colors';
|
||||
|
||||
@@ -16,7 +17,7 @@ export default function Terminal() {
|
||||
>
|
||||
<Grid container spacing={0}>
|
||||
<Grid item xs={4}>
|
||||
This is the sidepanel
|
||||
<Navbar />
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={8}>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
type Shortcut = { label: string; shortcutKey: string };
|
||||
|
||||
export const KeyboardShortcuts: Record<string, Shortcut> = {
|
||||
search: {
|
||||
label: '/',
|
||||
shortcutKey: '/',
|
||||
},
|
||||
escape: {
|
||||
shortcutKey: 'Escape',
|
||||
label: 'esc',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
// the rules of the game
|
||||
|
||||
export const NirvanaRules = {
|
||||
maxMembersPerConversation: 8,
|
||||
|
||||
maxPriorityConvos: 5,
|
||||
|
||||
topXConversationsWithShortcuts: 3,
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* The string that should be used to search for the support account, regardless of the environment
|
||||
*/
|
||||
export const SUPPORT_DISPLAY_NAME = 'Nirvana | Team';
|
||||
@@ -0,0 +1,7 @@
|
||||
export const toTitleCase = (str: string) => {
|
||||
return str
|
||||
.toLowerCase()
|
||||
.split(' ')
|
||||
.map((s) => s.charAt(0).toUpperCase() + s.substring(1))
|
||||
.join(' ');
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
import { ContentBlock } from '@nirvana/core/models/content.model';
|
||||
import Conversation from '@nirvana/core/models/conversation.model';
|
||||
import User from '@nirvana/core/models/user.model';
|
||||
|
||||
export type ConversationMap = {
|
||||
[conversationId: string]: Conversation;
|
||||
};
|
||||
|
||||
export type UserMap = {
|
||||
[userId: string]: User;
|
||||
};
|
||||
|
||||
export type ConversationContentMap = {
|
||||
[conversationId: string]: ContentBlock[];
|
||||
};
|
||||
Reference in New Issue
Block a user