nirvana support really awesome right there!
This commit is contained in:
@@ -1,25 +1,33 @@
|
|||||||
/* eslint-disable jsx-a11y/media-has-caption */
|
|
||||||
import { blueGrey } from '@mui/material/colors';
|
|
||||||
import React, { useState, useEffect, useMemo } from 'react';
|
|
||||||
import { joinConversation, leaveConversation } from '../firebase/firestore';
|
|
||||||
import useAuth from '../providers/AuthProvider';
|
|
||||||
import { useImmer } from 'use-immer';
|
|
||||||
import useTerminal from './Terminal';
|
|
||||||
import { User } from '@nirvana/core/src/models/user.model';
|
|
||||||
import {
|
import {
|
||||||
Stack,
|
|
||||||
IconButton,
|
|
||||||
Typography,
|
|
||||||
AvatarGroup,
|
|
||||||
Avatar,
|
Avatar,
|
||||||
|
AvatarGroup,
|
||||||
Box,
|
Box,
|
||||||
Container,
|
Container,
|
||||||
Fab,
|
Fab,
|
||||||
|
IconButton,
|
||||||
Paper,
|
Paper,
|
||||||
|
Stack,
|
||||||
|
Typography,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { FiSun, FiMoreVertical, FiPlay, FiCloudRain } from 'react-icons/fi';
|
import { FiCloudRain, FiMoreVertical, FiPlay, FiSun } from 'react-icons/fi';
|
||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
|
import { joinConversation, leaveConversation } from '../firebase/firestore';
|
||||||
|
|
||||||
import ConversationLabel from '../subcomponents/ConversationLabel';
|
import ConversationLabel from '../subcomponents/ConversationLabel';
|
||||||
|
import { User } from '@nirvana/core/src/models/user.model';
|
||||||
|
/* eslint-disable jsx-a11y/media-has-caption */
|
||||||
|
import { blueGrey } from '@mui/material/colors';
|
||||||
|
import useAuth from '../providers/AuthProvider';
|
||||||
|
import { useImmer } from 'use-immer';
|
||||||
import { useRendersCount } from 'react-use';
|
import { useRendersCount } from 'react-use';
|
||||||
|
import useTerminal from './Terminal';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nice convo history
|
||||||
|
* - chunk has max of 1 minute
|
||||||
|
* - put current clip in next chunk if previous clip was more than 4 hours ago
|
||||||
|
* - put current clip in next chunk if it's after my last active date here
|
||||||
|
*/
|
||||||
|
|
||||||
export default function ConversationDetails() {
|
export default function ConversationDetails() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
|||||||
@@ -1,38 +1,40 @@
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
|
AvatarGroup,
|
||||||
Badge,
|
Badge,
|
||||||
|
Box,
|
||||||
|
CircularProgress,
|
||||||
Divider,
|
Divider,
|
||||||
|
IconButton,
|
||||||
|
Input,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
ListItemButton,
|
ListItemButton,
|
||||||
|
ListItemSecondaryAction,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
ListSubheader,
|
ListSubheader,
|
||||||
Stack,
|
Stack,
|
||||||
Typography,
|
|
||||||
Input,
|
|
||||||
CircularProgress,
|
|
||||||
IconButton,
|
|
||||||
Box,
|
|
||||||
Tooltip,
|
Tooltip,
|
||||||
ListItemSecondaryAction,
|
Typography,
|
||||||
AvatarGroup,
|
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { blueGrey } from '@mui/material/colors';
|
import { FiActivity, FiCircle, FiCoffee, FiInbox, FiSearch, FiSun, FiUsers } from 'react-icons/fi';
|
||||||
import { FiActivity, FiInbox, FiSearch, FiUsers, FiCoffee, FiCircle, FiSun } from 'react-icons/fi';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import NirvanaAvatar from './NirvanaAvatar';
|
|
||||||
import { useDebounce, useKey, useRendersCount } from 'react-use';
|
import { useDebounce, useKey, useRendersCount } from 'react-use';
|
||||||
import { useSnackbar } from 'notistack';
|
|
||||||
import KeyboardShortcutLabel from './KeyboardShortcutLabel';
|
|
||||||
import { searchUsers } from '../firebase/firestore';
|
|
||||||
import { User } from '@nirvana/core/src/models/user.model';
|
|
||||||
import useTerminal from './Terminal';
|
|
||||||
import Conversation from '@nirvana/core/src/models/conversation.model';
|
import Conversation from '@nirvana/core/src/models/conversation.model';
|
||||||
|
import ConversationLabel from '../subcomponents/ConversationLabel';
|
||||||
|
import KeyboardShortcutLabel from './KeyboardShortcutLabel';
|
||||||
|
import NirvanaAvatar from './NirvanaAvatar';
|
||||||
|
import { User } from '@nirvana/core/src/models/user.model';
|
||||||
|
import { blueGrey } from '@mui/material/colors';
|
||||||
|
import { searchUsers } from '../firebase/firestore';
|
||||||
import useAuth from '../providers/AuthProvider';
|
import useAuth from '../providers/AuthProvider';
|
||||||
import { useImmer } from 'use-immer';
|
import { useImmer } from 'use-immer';
|
||||||
import ConversationLabel from '../subcomponents/ConversationLabel';
|
import { useSnackbar } from 'notistack';
|
||||||
|
import useTerminal from './Terminal';
|
||||||
|
|
||||||
|
// sort conversations based on the different data sources: type, conversations, audio clips, etc.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,28 +1,29 @@
|
|||||||
import {
|
import {
|
||||||
Box,
|
|
||||||
Stack,
|
|
||||||
IconButton,
|
|
||||||
Avatar,
|
Avatar,
|
||||||
Tooltip,
|
|
||||||
Switch,
|
|
||||||
Button,
|
|
||||||
AvatarGroup,
|
AvatarGroup,
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Divider,
|
||||||
Fab,
|
Fab,
|
||||||
|
IconButton,
|
||||||
ListItemIcon,
|
ListItemIcon,
|
||||||
Typography,
|
|
||||||
Menu,
|
Menu,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
|
Stack,
|
||||||
|
Switch,
|
||||||
|
Tooltip,
|
||||||
|
Typography,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { blueGrey } from '@mui/material/colors';
|
import { FiHeadphones, FiHelpCircle, FiLogOut, FiSun } from 'react-icons/fi';
|
||||||
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { FiHeadphones, FiSun, FiLogOut } from 'react-icons/fi';
|
|
||||||
import ConversationLabel from '../subcomponents/ConversationLabel';
|
import ConversationLabel from '../subcomponents/ConversationLabel';
|
||||||
import useTerminal from './Terminal';
|
import { blueGrey } from '@mui/material/colors';
|
||||||
import useAuth from '../providers/AuthProvider';
|
import useAuth from '../providers/AuthProvider';
|
||||||
|
import useTerminal from './Terminal';
|
||||||
|
|
||||||
export default function FooterControls() {
|
export default function FooterControls() {
|
||||||
const { selectedConversation } = useTerminal();
|
const { selectedConversation, handleOmniSearch } = useTerminal();
|
||||||
const { user, logout } = useAuth();
|
const { user, logout } = useAuth();
|
||||||
|
|
||||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||||
@@ -34,6 +35,10 @@ export default function FooterControls() {
|
|||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleQuickDialSupport = useCallback(() => {
|
||||||
|
handleOmniSearch('Nirvana Support');
|
||||||
|
}, [handleOmniSearch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@@ -158,36 +163,17 @@ export default function FooterControls() {
|
|||||||
id="account-menu"
|
id="account-menu"
|
||||||
open={open}
|
open={open}
|
||||||
onClose={handleCloseProfileMenu}
|
onClose={handleCloseProfileMenu}
|
||||||
onClick={handleCloseProfileMenu}
|
transformOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||||
PaperProps={{
|
anchorOrigin={{ horizontal: 'right', vertical: 'top' }}
|
||||||
elevation: 0,
|
|
||||||
sx: {
|
|
||||||
overflow: 'visible',
|
|
||||||
filter: 'drop-shadow(0px 2px 8px rgba(0,0,0,0.32))',
|
|
||||||
mt: 1.5,
|
|
||||||
'& .MuiAvatar-root': {
|
|
||||||
width: 32,
|
|
||||||
height: 32,
|
|
||||||
ml: -0.5,
|
|
||||||
mr: 1,
|
|
||||||
},
|
|
||||||
'&:before': {
|
|
||||||
content: '""',
|
|
||||||
display: 'block',
|
|
||||||
position: 'absolute',
|
|
||||||
top: 0,
|
|
||||||
right: 14,
|
|
||||||
width: 10,
|
|
||||||
height: 10,
|
|
||||||
bgcolor: 'background.paper',
|
|
||||||
transform: 'translateY(-50%) rotate(45deg)',
|
|
||||||
zIndex: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
|
||||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
|
||||||
>
|
>
|
||||||
|
<MenuItem onClick={handleQuickDialSupport}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<FiHelpCircle />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography>Help</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
<MenuItem onClick={logout}>
|
<MenuItem onClick={logout}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<FiLogOut />
|
<FiLogOut />
|
||||||
|
|||||||
@@ -1,36 +1,32 @@
|
|||||||
import React, { useContext, useState, useCallback, useMemo, useEffect } from 'react';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
|
AvatarGroup,
|
||||||
Box,
|
Box,
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
Divider,
|
||||||
|
Fab,
|
||||||
Grid,
|
Grid,
|
||||||
IconButton,
|
IconButton,
|
||||||
Tooltip,
|
|
||||||
Stack,
|
|
||||||
Divider,
|
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
Button,
|
|
||||||
ListItemButton,
|
ListItemButton,
|
||||||
|
ListItemIcon,
|
||||||
ListItemSecondaryAction,
|
ListItemSecondaryAction,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
ListSubheader,
|
ListSubheader,
|
||||||
Typography,
|
|
||||||
Menu,
|
Menu,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
ListItemIcon,
|
Stack,
|
||||||
Fab,
|
|
||||||
Switch,
|
Switch,
|
||||||
Dialog,
|
Tooltip,
|
||||||
AvatarGroup,
|
Typography,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { blueGrey } from '@mui/material/colors';
|
import { ContentBlock, ContentType } from '@nirvana/core/src/models/content.model';
|
||||||
import { FiZap, FiHeadphones, FiLogOut, FiMonitor, FiSun } from 'react-icons/fi';
|
import { FiHeadphones, FiLogOut, FiMonitor, FiSun, FiZap } from 'react-icons/fi';
|
||||||
import { useSnackbar } from 'notistack';
|
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { Unsubscribe, onSnapshot } from 'firebase/firestore';
|
||||||
import Conversation from '@nirvana/core/src/models/conversation.model';
|
|
||||||
import useAuth from '../providers/AuthProvider';
|
|
||||||
import {
|
import {
|
||||||
createOneOnOneConversation,
|
createOneOnOneConversation,
|
||||||
getConversationContentQueryLIVE,
|
getConversationContentQueryLIVE,
|
||||||
@@ -39,21 +35,23 @@ import {
|
|||||||
searchUsers,
|
searchUsers,
|
||||||
sendContentBlockToConversation,
|
sendContentBlockToConversation,
|
||||||
} from '../firebase/firestore';
|
} from '../firebase/firestore';
|
||||||
import { useImmer } from 'use-immer';
|
|
||||||
import { User } from '@nirvana/core/src/models/user.model';
|
|
||||||
import { onSnapshot, Unsubscribe } from 'firebase/firestore';
|
|
||||||
|
|
||||||
import { useDebounce, useKeyPressEvent, useRendersCount, useUnmount } from 'react-use';
|
import { useDebounce, useKeyPressEvent, useRendersCount, useUnmount } from 'react-use';
|
||||||
|
|
||||||
import { uploadAudioClip } from '../firebase/firebaseStorage';
|
import Conversation from '@nirvana/core/src/models/conversation.model';
|
||||||
import { ContentBlock, ContentType } from '@nirvana/core/src/models/content.model';
|
|
||||||
import Navbar from './Navbar';
|
|
||||||
import MainPanel from './MainPanel';
|
|
||||||
import { ConversationList } from './ConversationList';
|
|
||||||
import NewConversationDialog from './NewConversationDialog';
|
|
||||||
import { createGroupConversation } from '../firebase/firestore';
|
|
||||||
import ConversationLabel from '../subcomponents/ConversationLabel';
|
import ConversationLabel from '../subcomponents/ConversationLabel';
|
||||||
|
import { ConversationList } from './ConversationList';
|
||||||
import FooterControls from './FooterControls';
|
import FooterControls from './FooterControls';
|
||||||
|
import MainPanel from './MainPanel';
|
||||||
|
import Navbar from './Navbar';
|
||||||
|
import NewConversationDialog from './NewConversationDialog';
|
||||||
|
import { User } from '@nirvana/core/src/models/user.model';
|
||||||
|
import { blueGrey } from '@mui/material/colors';
|
||||||
|
import { createGroupConversation } from '../firebase/firestore';
|
||||||
|
import { uploadAudioClip } from '../firebase/firebaseStorage';
|
||||||
|
import useAuth from '../providers/AuthProvider';
|
||||||
|
import { useImmer } from 'use-immer';
|
||||||
|
import { useSnackbar } from 'notistack';
|
||||||
|
|
||||||
type ConversationMap = {
|
type ConversationMap = {
|
||||||
[conversationId: string]: Conversation;
|
[conversationId: string]: Conversation;
|
||||||
};
|
};
|
||||||
@@ -84,6 +82,8 @@ interface ITerminalContext {
|
|||||||
handleShowCreateConvoForm?: () => void;
|
handleShowCreateConvoForm?: () => void;
|
||||||
|
|
||||||
handleEscape?: () => void;
|
handleEscape?: () => void;
|
||||||
|
|
||||||
|
handleOmniSearch?: (searchQuery: string) => void; // handle searching for anything globally
|
||||||
}
|
}
|
||||||
|
|
||||||
const TerminalContext = React.createContext<ITerminalContext>({
|
const TerminalContext = React.createContext<ITerminalContext>({
|
||||||
@@ -106,60 +106,6 @@ const handleOnStartRecording = (e: BlobEvent) => {
|
|||||||
audioChunks = [];
|
audioChunks = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODOS
|
|
||||||
// fetch all conversations that I am part of
|
|
||||||
|
|
||||||
// create a convo
|
|
||||||
// 1. search
|
|
||||||
// 2. click on person
|
|
||||||
// 3. search database if there is already a convo for this
|
|
||||||
// - if yes: select this one
|
|
||||||
// - if no: create one
|
|
||||||
// 4. show the conversation details page show on right
|
|
||||||
// 5. connect live if other person there
|
|
||||||
// 6. send first clip
|
|
||||||
// 7. display all blocks/clips for convo simple and separate
|
|
||||||
|
|
||||||
// if no conversations, show stale state + create one with nirvana
|
|
||||||
|
|
||||||
// 1. create group conversation page
|
|
||||||
// you know what to do...simple row of selected users...dropdown options should show searched user list
|
|
||||||
// use material selects for this dropdown to avoid all the work...and hide select-like things
|
|
||||||
// 2. auto select that conversation and have it show up
|
|
||||||
// 3. allow adding name when creating convo
|
|
||||||
// 4.
|
|
||||||
// 5. convo settings: add people (simple add method with firestore), change name | max 8 people
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Streaming stuff:
|
|
||||||
* - join a stream room if 2 or more in the list
|
|
||||||
* - leave on unmount
|
|
||||||
* - timer to unselect a conversation after 30 minutes...no fancy checking if user is there/active
|
|
||||||
* - show little control to see if
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* media stuff:
|
|
||||||
* - paste image + view in history + with modal nice and big
|
|
||||||
* - paste a link + see in a content block
|
|
||||||
* - paste link of image and have it save as image
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* tech debt: now go back and make convo line and side panel name and icons and all legit
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* nice convo history
|
|
||||||
* - chunk has max of 1 minute
|
|
||||||
* - put current clip in next chunk if previous clip was more than 4 hours ago
|
|
||||||
* - put current clip in next chunk if it's after my last active date here
|
|
||||||
*/
|
|
||||||
|
|
||||||
// sort based on the different data sources: conversations, audio clips, etc.
|
|
||||||
|
|
||||||
// todo: extract each use effect to custom hook and will be clean
|
// todo: extract each use effect to custom hook and will be clean
|
||||||
export function TerminalProvider({ children }: { children?: React.ReactNode }) {
|
export function TerminalProvider({ children }: { children?: React.ReactNode }) {
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
@@ -493,14 +439,25 @@ export function TerminalProvider({ children }: { children?: React.ReactNode }) {
|
|||||||
[searchVal, enqueueSnackbar, setSearchUsersResults, user],
|
[searchVal, enqueueSnackbar, setSearchUsersResults, user],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleChangeSearchInput = useCallback(
|
const handleOmniSearch = useCallback(
|
||||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
(searchQuery: string) => {
|
||||||
|
if (!searchQuery) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setSearching(true);
|
setSearching(true);
|
||||||
setSearchVal(e.target.value.replace('/', ''));
|
setSearchVal(searchQuery.replace('/', ''));
|
||||||
},
|
},
|
||||||
[setSearching, setSearchVal],
|
[setSearching, setSearchVal],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleChangeSearchInput = useCallback(
|
||||||
|
(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
handleOmniSearch(e.target.value);
|
||||||
|
},
|
||||||
|
[handleOmniSearch],
|
||||||
|
);
|
||||||
|
|
||||||
const selectConversation = useCallback(
|
const selectConversation = useCallback(
|
||||||
(conversationId: string) => setSelectedConversationId(conversationId),
|
(conversationId: string) => setSelectedConversationId(conversationId),
|
||||||
[setSelectedConversationId],
|
[setSelectedConversationId],
|
||||||
@@ -571,6 +528,7 @@ export function TerminalProvider({ children }: { children?: React.ReactNode }) {
|
|||||||
createConversationMode,
|
createConversationMode,
|
||||||
handleShowCreateConvoForm,
|
handleShowCreateConvoForm,
|
||||||
handleEscape,
|
handleEscape,
|
||||||
|
handleOmniSearch,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Stack direction={'column'} sx={{ flex: 1 }}>
|
<Stack direction={'column'} sx={{ flex: 1 }}>
|
||||||
|
|||||||
@@ -1,39 +1,40 @@
|
|||||||
//TODO: move all of this to core or common and separate out files
|
//TODO: move all of this to core or common and separate out files
|
||||||
|
|
||||||
import {
|
|
||||||
setDoc,
|
|
||||||
getFirestore,
|
|
||||||
doc,
|
|
||||||
collection,
|
|
||||||
QueryDocumentSnapshot,
|
|
||||||
Timestamp,
|
|
||||||
FieldValue,
|
|
||||||
getDoc,
|
|
||||||
query,
|
|
||||||
where,
|
|
||||||
getDocs,
|
|
||||||
orderBy,
|
|
||||||
limit,
|
|
||||||
startAt,
|
|
||||||
endAt,
|
|
||||||
addDoc,
|
|
||||||
arrayUnion,
|
|
||||||
updateDoc,
|
|
||||||
arrayRemove,
|
|
||||||
serverTimestamp,
|
|
||||||
} from 'firebase/firestore';
|
|
||||||
|
|
||||||
import { User as FirebaseUser } from 'firebase/auth';
|
|
||||||
import { firestoreDb } from './connect';
|
|
||||||
import { User } from '@nirvana/core/src/models/user.model';
|
|
||||||
import Conversation, {
|
import Conversation, {
|
||||||
ConversationMember,
|
ConversationMember,
|
||||||
MemberMap,
|
MemberMap,
|
||||||
MemberRole,
|
MemberRole,
|
||||||
MemberState,
|
MemberState,
|
||||||
} from '@nirvana/core/src/models/conversation.model';
|
} from '@nirvana/core/src/models/conversation.model';
|
||||||
import useAuth from '../providers/AuthProvider';
|
import {
|
||||||
|
FieldValue,
|
||||||
|
QueryDocumentSnapshot,
|
||||||
|
Timestamp,
|
||||||
|
addDoc,
|
||||||
|
arrayRemove,
|
||||||
|
arrayUnion,
|
||||||
|
collection,
|
||||||
|
doc,
|
||||||
|
endAt,
|
||||||
|
getDoc,
|
||||||
|
getDocs,
|
||||||
|
getFirestore,
|
||||||
|
limit,
|
||||||
|
orderBy,
|
||||||
|
query,
|
||||||
|
serverTimestamp,
|
||||||
|
setDoc,
|
||||||
|
startAt,
|
||||||
|
updateDoc,
|
||||||
|
where,
|
||||||
|
} from 'firebase/firestore';
|
||||||
|
|
||||||
import { ContentBlock } from '@nirvana/core/src/models/content.model';
|
import { ContentBlock } from '@nirvana/core/src/models/content.model';
|
||||||
|
import { User as FirebaseUser } from 'firebase/auth';
|
||||||
|
import { User } from '@nirvana/core/src/models/user.model';
|
||||||
|
import { firestoreDb } from './connect';
|
||||||
|
import { toTitleCase } from '../util/text';
|
||||||
|
import useAuth from '../providers/AuthProvider';
|
||||||
|
|
||||||
interface Document {
|
interface Document {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -108,8 +109,7 @@ export const searchUsers = async (searchQuery: string): Promise<User[] | undefin
|
|||||||
limit(5),
|
limit(5),
|
||||||
);
|
);
|
||||||
|
|
||||||
const nameManipulatedQuery =
|
const nameManipulatedQuery = toTitleCase(searchQuery);
|
||||||
searchQuery[0].toUpperCase() + searchQuery.slice(1).toLocaleLowerCase();
|
|
||||||
const nameSearchQuery = query(
|
const nameSearchQuery = query(
|
||||||
db.users,
|
db.users,
|
||||||
orderBy('displayName'),
|
orderBy('displayName'),
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export const toTitleCase = (str: string) => {
|
||||||
|
return str
|
||||||
|
.toLowerCase()
|
||||||
|
.split(' ')
|
||||||
|
.map((s) => s.charAt(0).toUpperCase() + s.substring(1))
|
||||||
|
.join(' ');
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user