-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNavbar.tsx
125 lines (116 loc) · 4.72 KB
/
Navbar.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { Fragment, useState } from "react"
import { Link, useHistory, useLocation } from "react-router-dom"
import algoliasearch from "algoliasearch/lite"
import { SearchInput } from "./SearchInput"
import { ProfileImage } from "./ProfileImage"
import { User } from "../models"
import { useAuth } from "../context"
import styles from "./Navbar.module.css"
import { ReactComponent as AlgoliaLogo } from "./algolia-logo.svg"
import convergentLogo from "./convergent_logo.png"
// Algolia API we'll use to get our search results, only works if you've set up cloud functions before
const algolia = algoliasearch(process.env.REACT_APP_ALGOLIA_APP_ID!, process.env.REACT_APP_ALGOLIA_SEARCH_KEY!)
const index = algolia.initIndex("Accounts")
interface NavbarProps {
profile?: User
title?: string
onSearch?: (text: string) => void
}
// Navbar component at the top of the screen, with embedded user search bar and link to profile page
// Handles algolia search for new conversations
export function Navbar({ profile, title }: NavbarProps) {
const { currentUser } = useAuth()
const [suggestions, setSuggestions] = useState<any[]>([]) // stores search suggestions
const history = useHistory()
const location = useLocation()
// Each time we type a key, we update our search suggestions using our Algolia index
const handleKeyDown = async (currentText: string) => {
const results = await index.search<any>(currentText, { hitsPerPage: 8 })
setSuggestions(
results.hits
.filter((v) => v.objectID !== currentUser!.id)
.map((result) => {
return {
name: result.name,
username: result.username,
imageUrl: result.imageUrl,
uid: result.objectID,
}
})
)
}
// If we press enter, find the user matching our current string
const handleSearch = async (text: string) => {
history.push(`/user/${text}`)
}
return (
<nav className={styles.navbar}>
<div className={styles.navLogo}>
<img src={convergentLogo} alt="Website Logo" />
</div>
<div className={styles.navTitle}>
<h3>{title}</h3>
</div>
<div className={styles.navSearch}>
{/* Suggestions passed into our search input from our state */}
<SearchInput
limit={8}
onKeyDown={handleKeyDown}
onSearch={handleSearch}
suggestions={suggestions.map((props, i) => (
<NavbarSearchSuggestions key={i} onClick={() => setSuggestions([])} {...props} />
))}
/>
</div>
<div className={styles.profileContainer}>
<button>
<ProfileImage user={currentUser!} className={styles.profileImage} />
</button>
<menu className={styles.profileDropdown}>
<Link
to={{
pathname: "/profile",
state: { background: location },
}}
className={styles.dropdownItem}
>
Edit Profile
</Link>
<Link to="/logout" className={styles.dropdownItem}>
Logout
</Link>
</menu>
</div>
</nav>
)
}
interface NavbarSearchSuggestionsProps {
name?: string
username: string
imageUrl?: string
uid: string
onClick: () => void
}
function NavbarSearchSuggestions({ name, username, imageUrl, uid, onClick }: NavbarSearchSuggestionsProps) {
return (
<Link onClick={onClick} to={`/user/${uid}`} className={styles.navSearchResult}>
<div className={styles.navSearchResultImage}>
<ProfileImage className={styles.profileImage} imageUrl={imageUrl} name={name} username={username} />
</div>
<div className={styles.navSearchResultText}>
{name ? (
<Fragment>
<h5 className={styles.navSearchResultTitle}>{name}</h5>
<div className={styles.navSearchResultSubtitle}>{username}</div>
</Fragment>
) : (
<h5 className={styles.navSearchResultTitle}>{username}</h5>
)}
</div>
<div className={styles.navSearchResultAlgolia}>
{/* Logo here so we don't get sued */}
<AlgoliaLogo />
</div>
</Link>
)
}