Chat Header
This commit is contained in:
parent
15ad8bf8dd
commit
f98c849ed9
|
@ -7,6 +7,7 @@
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
transition: background 0.3s ease-in-out;
|
transition: background 0.3s ease-in-out;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #f7f7f7;
|
background: #f7f7f7;
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
|
|
||||||
.name,
|
.name,
|
||||||
.message {
|
.message {
|
||||||
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import styles from './DialogCard.module.scss'
|
import { Show, Switch, Match, createMemo, For } from 'solid-js'
|
||||||
import DialogAvatar from './DialogAvatar'
|
import DialogAvatar from './DialogAvatar'
|
||||||
import type { ChatMember } from '../../graphql/types.gen'
|
import type { ChatMember } from '../../graphql/types.gen'
|
||||||
import GroupDialogAvatar from './GroupDialogAvatar'
|
import GroupDialogAvatar from './GroupDialogAvatar'
|
||||||
import { Show } from 'solid-js'
|
import { clsx } from 'clsx'
|
||||||
|
import styles from './DialogCard.module.scss'
|
||||||
|
|
||||||
type DialogProps = {
|
type DialogProps = {
|
||||||
online?: boolean
|
online?: boolean
|
||||||
|
@ -11,37 +12,50 @@ type DialogProps = {
|
||||||
title?: string
|
title?: string
|
||||||
ownSlug: string
|
ownSlug: string
|
||||||
members: ChatMember[]
|
members: ChatMember[]
|
||||||
onClick: () => void
|
onClick?: () => void
|
||||||
|
isChatHeader?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const DialogCard = (props: DialogProps) => {
|
const DialogCard = (props: DialogProps) => {
|
||||||
const companions = props.members && props.members.filter((member) => member.slug !== props.ownSlug)
|
const companions = createMemo(
|
||||||
|
() => props.members && props.members.filter((member) => member.slug !== props.ownSlug)
|
||||||
|
)
|
||||||
|
const names = createMemo(() =>
|
||||||
|
companions()
|
||||||
|
.map((companion) => companion.name)
|
||||||
|
.join(', ')
|
||||||
|
)
|
||||||
|
console.log('!!! names:', names())
|
||||||
return (
|
return (
|
||||||
<Show when={props.members}>
|
<Show when={props.members}>
|
||||||
<div class={styles.DialogCard} onClick={props.onClick}>
|
<div class={clsx(styles.DialogCard, { [styles.header]: props.isChatHeader })} onClick={props.onClick}>
|
||||||
<div class={styles.avatar}>
|
<div class={styles.avatar}>
|
||||||
{companions.length > 2 ? (
|
<Switch fallback={<DialogAvatar name={props.members[0].name} url={props.members[0].userpic} />}>
|
||||||
<GroupDialogAvatar users={companions} />
|
<Match when={companions().length > 2}>
|
||||||
) : (
|
<GroupDialogAvatar users={companions()} />
|
||||||
<DialogAvatar name={props.members[0].name} url={props.members[0].userpic} />
|
</Match>
|
||||||
)}
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
<div class={styles.row}>
|
<div class={styles.row}>
|
||||||
{companions.length > 1 ? (
|
<Switch fallback={<div class={styles.name}>{companions()[0].name}</div>}>
|
||||||
<div class={styles.name}>{props.title}</div>
|
<Match when={companions().length > 1}>
|
||||||
) : (
|
<div class={styles.name}>{props.title}</div>
|
||||||
<div class={styles.name}>{companions[0].name}</div>
|
</Match>
|
||||||
)}
|
</Switch>
|
||||||
<div class={styles.message}>
|
<div class={styles.message}>
|
||||||
Указать предпочтительные языки для результатов поиска можно в разделе
|
<Switch fallback={'Chat last message'}>
|
||||||
|
<Match when={props.isChatHeader && companions().length > 1}>{names}</Match>
|
||||||
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class={styles.activity}>
|
<Show when={!props.isChatHeader}>
|
||||||
<div class={styles.time}>22:22</div>
|
<div class={styles.activity}>
|
||||||
<div class={styles.counter}>
|
<div class={styles.time}>22:22</div>
|
||||||
<span>12</span>
|
<div class={styles.counter}>
|
||||||
|
<span>12</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
)
|
)
|
||||||
|
|
9
src/components/Inbox/DialogHeader.module.scss
Normal file
9
src/components/Inbox/DialogHeader.module.scss
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.DialogHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 3px solid #141414;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
}
|
23
src/components/Inbox/DialogHeader.tsx
Normal file
23
src/components/Inbox/DialogHeader.tsx
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import type { Chat } from '../../graphql/types.gen'
|
||||||
|
import styles from './DialogHeader.module.scss'
|
||||||
|
import DialogCard from './DialogCard'
|
||||||
|
|
||||||
|
type DialogHeader = {
|
||||||
|
chat: Chat
|
||||||
|
currentSlug: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const DialogHeader = (props: DialogHeader) => {
|
||||||
|
return (
|
||||||
|
<header class={styles.DialogHeader}>
|
||||||
|
<DialogCard
|
||||||
|
isChatHeader={true}
|
||||||
|
title={props.chat.title}
|
||||||
|
members={props.chat.members}
|
||||||
|
ownSlug={props.currentSlug}
|
||||||
|
/>
|
||||||
|
</header>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DialogHeader
|
|
@ -16,6 +16,7 @@ import CreateModalContent from '../Inbox/CreateModalContent'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import '../../styles/Inbox.scss'
|
import '../../styles/Inbox.scss'
|
||||||
import { useInbox } from '../../context/inbox'
|
import { useInbox } from '../../context/inbox'
|
||||||
|
import DialogHeader from '../Inbox/DialogHeader'
|
||||||
|
|
||||||
const OWNER_ID = '501'
|
const OWNER_ID = '501'
|
||||||
const client = createClient({
|
const client = createClient({
|
||||||
|
@ -70,6 +71,7 @@ export const InboxView = () => {
|
||||||
const [loading, setLoading] = createSignal<boolean>(false)
|
const [loading, setLoading] = createSignal<boolean>(false)
|
||||||
const [sortByGroup, setSortByGroup] = createSignal<boolean>(false)
|
const [sortByGroup, setSortByGroup] = createSignal<boolean>(false)
|
||||||
const [sortByPerToPer, setSortByPerToPer] = createSignal<boolean>(false)
|
const [sortByPerToPer, setSortByPerToPer] = createSignal<boolean>(false)
|
||||||
|
const [selectedChat, setSelectedChat] = createSignal<Chat | undefined>(undefined)
|
||||||
const { session } = useSession()
|
const { session } = useSession()
|
||||||
const currentSlug = createMemo(() => session()?.user?.slug)
|
const currentSlug = createMemo(() => session()?.user?.slug)
|
||||||
|
|
||||||
|
@ -84,10 +86,11 @@ export const InboxView = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let chatWindow
|
let chatWindow
|
||||||
const handleOpenChat = async (chatId) => {
|
const handleOpenChat = async (chat) => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
setSelectedChat(chat)
|
||||||
try {
|
try {
|
||||||
await loadMessages({ chat: chatId })
|
await loadMessages({ chat: chat.id })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
console.error('[loadMessages]', error)
|
console.error('[loadMessages]', error)
|
||||||
|
@ -193,7 +196,7 @@ export const InboxView = () => {
|
||||||
<For each={chatsToShow()}>
|
<For each={chatsToShow()}>
|
||||||
{(chat) => (
|
{(chat) => (
|
||||||
<DialogCard
|
<DialogCard
|
||||||
onClick={() => handleOpenChat(chat.id)}
|
onClick={() => handleOpenChat(chat)}
|
||||||
title={chat.title}
|
title={chat.title}
|
||||||
members={chat.members}
|
members={chat.members}
|
||||||
ownSlug={currentSlug()}
|
ownSlug={currentSlug()}
|
||||||
|
@ -205,10 +208,9 @@ export const InboxView = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-8 conversation">
|
<div class="col-md-8 conversation">
|
||||||
<div class="interlocutor user--online">
|
<Show when={selectedChat()}>
|
||||||
<AuthorCard author={{} as Author} hideFollow={true} />
|
<DialogHeader currentSlug={currentSlug()} chat={selectedChat()} />
|
||||||
<div class="user-status">Online</div>
|
</Show>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="conversation__messages">
|
<div class="conversation__messages">
|
||||||
<div class="conversation__messages-container" ref={chatWindow}>
|
<div class="conversation__messages-container" ref={chatWindow}>
|
||||||
|
|
|
@ -88,8 +88,7 @@ main {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-list__search,
|
.chat-list__search {
|
||||||
.interlocutor {
|
|
||||||
border-bottom: 3px solid #141414;
|
border-bottom: 3px solid #141414;
|
||||||
padding: 1em 0;
|
padding: 1em 0;
|
||||||
}
|
}
|
||||||
|
@ -122,44 +121,6 @@ main {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.interlocutor {
|
|
||||||
height: 56px;
|
|
||||||
box-sizing: content-box;
|
|
||||||
|
|
||||||
.circlewrap {
|
|
||||||
height: 56px;
|
|
||||||
max-width: 56px;
|
|
||||||
width: 56px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.author {
|
|
||||||
margin-bottom: 0;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
left: 40px !important;
|
|
||||||
height: 8px !important;
|
|
||||||
width: 8px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.author__name {
|
|
||||||
@include font-size(1.7rem);
|
|
||||||
|
|
||||||
margin: 0.4em 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.author__details,
|
|
||||||
.user-status {
|
|
||||||
margin-left: 6.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-status {
|
|
||||||
@include font-size(1.2rem);
|
|
||||||
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.conversation {
|
.conversation {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user