adding in navbar and other components

This commit is contained in:
talksik
2022-06-11 06:06:16 -05:00
parent 8ee5cc0886
commit 11c4ec5a53
10 changed files with 282 additions and 1 deletions
@@ -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>
);
}
+89
View File
@@ -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;
+2 -1
View File
@@ -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}>
+12
View File
@@ -0,0 +1,12 @@
type Shortcut = { label: string; shortcutKey: string };
export const KeyboardShortcuts: Record<string, Shortcut> = {
search: {
label: '/',
shortcutKey: '/',
},
escape: {
shortcutKey: 'Escape',
label: 'esc',
},
};
+9
View File
@@ -0,0 +1,9 @@
// the rules of the game
export const NirvanaRules = {
maxMembersPerConversation: 8,
maxPriorityConvos: 5,
topXConversationsWithShortcuts: 3,
};
+4
View File
@@ -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';
+7
View File
@@ -0,0 +1,7 @@
export const toTitleCase = (str: string) => {
return str
.toLowerCase()
.split(' ')
.map((s) => s.charAt(0).toUpperCase() + s.substring(1))
.join(' ');
};
+15
View File
@@ -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[];
};