diff --git a/public/icons/cross.svg b/public/icons/cross.svg new file mode 100644 index 00000000..0ded326d --- /dev/null +++ b/public/icons/cross.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/plus-button.svg b/public/icons/plus-button.svg new file mode 100644 index 00000000..90a81b02 --- /dev/null +++ b/public/icons/plus-button.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/plus.svg b/public/icons/plus.svg new file mode 100644 index 00000000..d9f84d23 --- /dev/null +++ b/public/icons/plus.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Inbox/CreateModalContent.module.scss b/src/components/Inbox/CreateModalContent.module.scss new file mode 100644 index 00000000..fc1b2f1b --- /dev/null +++ b/src/components/Inbox/CreateModalContent.module.scss @@ -0,0 +1,9 @@ +.CreateModalContent { + padding: 24px; + .footer { + padding-top: 12px; + display: flex; + justify-content: space-around; + gap: 12px; + } +} diff --git a/src/components/Inbox/CreateModalContent.tsx b/src/components/Inbox/CreateModalContent.tsx new file mode 100644 index 00000000..c1f927c8 --- /dev/null +++ b/src/components/Inbox/CreateModalContent.tsx @@ -0,0 +1,112 @@ +import { createSignal, For, createEffect } from 'solid-js' +import styles from './CreateModalContent.module.scss' +import { t } from '../../utils/intl' +import InviteUser from './InviteUser' +import type { Author } from '../../graphql/types.gen' +import { hideModal } from '../../stores/ui' +import { useInbox } from '../../context/inbox' + +type inviteUser = Author & { selected: boolean } +type query = + | { + theme: string + members: string[] + } + | undefined +type Props = { + users: Author[] +} + +const CreateModalContent = (props: Props) => { + const inviteUsers: inviteUser[] = props.users.map((user) => ({ ...user, selected: false })) + const [theme, setTheme] = createSignal('') + const [slugs, setSlugs] = createSignal([]) + const [collectionToInvite, setCollectionToInvite] = createSignal(inviteUsers) + let textInput: HTMLInputElement + + const reset = () => { + setTheme('') + setSlugs([]) + hideModal() + } + + createEffect(() => { + setSlugs(() => { + return collectionToInvite() + .filter((user) => { + return user.selected === true + }) + .map((user) => { + return user['slug'] + }) + }) + if (slugs().length > 2 && theme().length === 0) { + setTheme(t('group_chat')) + } + }) + + const handleSetTheme = () => { + setTheme(textInput.value.length > 0 && textInput.value) + } + + const handleClick = (user) => { + setCollectionToInvite((userCollection) => { + return userCollection.map((clickedUser) => + user.slug === clickedUser.slug ? { ...clickedUser, selected: !clickedUser.selected } : clickedUser + ) + }) + } + + const { chatEntities, actions } = useInbox() + + console.log('!!! chatEntities:', chatEntities) + + const handleCreate = async () => { + try { + const initChat = await actions.createChat(slugs(), theme()) + console.debug('[initChat]', initChat) + } catch (error) { + console.error(error) + } + } + + return ( +
+

{t('create_chat')}

+ {slugs().length > 2 && ( + + )} + +
+ + {(author) => ( + handleClick(author)} author={author} selected={author.selected} /> + )} + +
+ +
+ + +
+
+ ) +} + +export default CreateModalContent diff --git a/src/components/Inbox/DialogCard.tsx b/src/components/Inbox/DialogCard.tsx index dcfb7021..5d19919e 100644 --- a/src/components/Inbox/DialogCard.tsx +++ b/src/components/Inbox/DialogCard.tsx @@ -1,6 +1,6 @@ import styles from './DialogCard.module.scss' import DialogAvatar from './DialogAvatar' -import type { Author } from '../../graphql/types.gen' +import type { Author, User } from '../../graphql/types.gen' import { apiClient } from '../../utils/apiClient' import { t } from '../../utils/intl' import { useInbox } from '../../context/inbox' @@ -9,29 +9,21 @@ type DialogProps = { online?: boolean message?: string counter?: number - author?: Author - ownSlug: Author['slug'] + users: User[] + ownSlug: User['slug'] } const DialogCard = (props: DialogProps) => { - const { chatEntities, actions } = useInbox() - const handleOpenChat = async () => { - try { - const initChat = await actions.createChat([props.author.slug, props.ownSlug]) - console.debug('[initChat]', initChat) - } catch (error) { - console.error(error) - } - } - + // @ts-ignore + const participants = props.users.filter((user) => user !== props.ownSlug) + console.log('!!! participants:', participants) + // @ts-ignore return ( //DialogCardView - подумать -
-
- -
+
+
{/**/}
-
{props.author.name}
+ {/*
{participants[0]}
*/}
Указать предпочтительные языки для результатов поиска можно в разделе
diff --git a/src/components/Inbox/InviteUser.module.scss b/src/components/Inbox/InviteUser.module.scss new file mode 100644 index 00000000..6f4804ac --- /dev/null +++ b/src/components/Inbox/InviteUser.module.scss @@ -0,0 +1,35 @@ +.InviteUser { + display: flex; + align-items: center; + justify-content: space-between; + flex-basis: 0; + flex-grow: 1; + min-width: 0; + padding: 12px; + gap: 10px; + cursor: pointer; + transition: all 0.3s ease-in-out; + + &:hover { + background: rgba(#f7f7f7, 0.65); + } + + .name { + flex-grow: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-weight: 500; + font-size: 14px; + } + + .action { + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + background: #f7f7f7; + border-radius: 6px; + } +} diff --git a/src/components/Inbox/InviteUser.tsx b/src/components/Inbox/InviteUser.tsx new file mode 100644 index 00000000..4fe85ed8 --- /dev/null +++ b/src/components/Inbox/InviteUser.tsx @@ -0,0 +1,22 @@ +import styles from './InviteUser.module.scss' +import DialogAvatar from './DialogAvatar' +import type { Author } from '../../graphql/types.gen' +import { Icon } from '../_shared/Icon' + +type DialogProps = { + author: Author + selected: boolean + onClick: () => void +} + +const InviteUser = (props: DialogProps) => { + return ( +
+ +
{props.author.name}
+
{props.selected ? : }
+
+ ) +} + +export default InviteUser diff --git a/src/components/Inbox/Search.module.scss b/src/components/Inbox/Search.module.scss index 207ad6a6..a92c66bc 100644 --- a/src/components/Inbox/Search.module.scss +++ b/src/components/Inbox/Search.module.scss @@ -8,7 +8,7 @@ input { display: block; - height: 40px; + height: 36px; border: none; box-shadow: none; padding: 10px 36px 10px 12px; @@ -38,7 +38,7 @@ position: absolute; width: 16px; height: 16px; - top: 12px; + top: 10px; right: 12px; opacity: 0.5; } diff --git a/src/components/Nav/Header.tsx b/src/components/Nav/Header.tsx index 7eb8356d..cb8d364e 100644 --- a/src/components/Nav/Header.tsx +++ b/src/components/Nav/Header.tsx @@ -84,7 +84,7 @@ export const Header = (props: Props) => { [styles.headerWithTitle]: Boolean(props.title) }} > - + diff --git a/src/components/Nav/Modal.scss b/src/components/Nav/Modal.module.scss similarity index 75% rename from src/components/Nav/Modal.scss rename to src/components/Nav/Modal.module.scss index 8c7bc2f0..746202e0 100644 --- a/src/components/Nav/Modal.scss +++ b/src/components/Nav/Modal.module.scss @@ -1,4 +1,4 @@ -.modalwrap { +.backdrop { align-items: center; background: rgb(20 20 20 / 70%); display: flex; @@ -10,9 +10,16 @@ position: fixed; top: 0; width: 100%; - z-index: 10; + z-index: 100; +} - .close-control { +.modal { + background: #fff; + max-width: 1000px; + position: relative; + width: 80%; + + .close { position: absolute; top: 1em; cursor: pointer; @@ -41,19 +48,16 @@ // top: 11em; } } -} -.modalwrap__inner { - background: #fff; - max-width: 1000px; - position: relative; - width: 80%; -} - -.modalwrap__content { - padding: $container-padding-x; - - @media (min-width: 800px) and (max-width: 991px) { - padding: 10rem 6rem; + &.narrow { + max-width: 460px; + width: 50%; + @media (min-width: 800px) and (max-width: 991px) { + width: 80%; + } + .close { + right: 12px; + top: 12px; + } } } diff --git a/src/components/Nav/Modal.tsx b/src/components/Nav/Modal.tsx index 2ebe709d..51b55eac 100644 --- a/src/components/Nav/Modal.tsx +++ b/src/components/Nav/Modal.tsx @@ -1,22 +1,24 @@ import { createEffect, createSignal, Show } from 'solid-js' import type { JSX } from 'solid-js' import { getLogger } from '../../utils/logger' -import './Modal.scss' import { hideModal, useModalStore } from '../../stores/ui' import { useEscKeyDownHandler } from '../../utils/useEscKeyDownHandler' +import { clsx } from 'clsx' +import styles from './Modal.module.scss' const log = getLogger('modal') interface ModalProps { name: string + variant: 'narrow' | 'wide' children: JSX.Element } export const Modal = (props: ModalProps) => { const { modal } = useModalStore() - const wrapClick = (event: { target: Element }) => { - if (event.target.classList.contains('modalwrap')) hideModal() + const backdropClick = (event: Event) => { + hideModal() } useEscKeyDownHandler(() => hideModal()) @@ -30,10 +32,16 @@ export const Modal = (props: ModalProps) => { return ( -
-
+
+
event.stopPropagation()} + > {props.children} -
+
{ return ( - + - +
diff --git a/src/components/Views/Inbox.tsx b/src/components/Views/Inbox.tsx index 18095ecc..f339cc84 100644 --- a/src/components/Views/Inbox.tsx +++ b/src/components/Views/Inbox.tsx @@ -1,5 +1,5 @@ import { For, createSignal, Show, onMount, createEffect, createMemo } from 'solid-js' -import type { Author } from '../../graphql/types.gen' +import type { Author, Chat } from '../../graphql/types.gen' import { AuthorCard } from '../Author/Card' import { Icon } from '../_shared/Icon' import { Loading } from '../Loading' @@ -12,6 +12,10 @@ import { loadRecipients, loadChats } from '../../stores/inbox' import { t } from '../../utils/intl' import '../../styles/Inbox.scss' import { useInbox } from '../../context/inbox' +import { Modal } from '../Nav/Modal' +import { showModal } from '../../stores/ui' +import InviteUser from '../Inbox/InviteUser' +import CreateModalContent from '../Inbox/CreateModalContent' const OWNER_ID = '501' const client = createClient({ @@ -54,18 +58,10 @@ const postMessage = async (msg: string) => { return response.data.createComment } -const handleGetChats = async () => { - try { - const response = await loadChats() - console.log('!!! handleGetChats:', response) - } catch (error) { - console.log(error) - } -} - export const InboxView = () => { const [messages, setMessages] = createSignal([]) const [recipients, setRecipients] = createSignal([]) + const [chats, setChats] = createSignal([]) const [cashedRecipients, setCashedRecipients] = createSignal([]) const [postMessageText, setPostMessageText] = createSignal('') const [loading, setLoading] = createSignal(false) @@ -112,6 +108,13 @@ export const InboxView = () => { } catch (error) { console.log(error) } + + try { + const response = await loadChats() + setChats(response as unknown as Chat[]) + } catch (error) { + console.log(error) + } }) const handleSubmit = async () => { @@ -125,36 +128,46 @@ export const InboxView = () => { } } - let formParent // autoresize ghost element + let textareaParent // textarea autoresize ghost element const handleChangeMessage = (event) => { setPostMessageText(event.target.value) } createEffect(() => { - formParent.dataset.replicatedValue = postMessageText() + textareaParent.dataset.replicatedValue = postMessageText() }) - // FIXME: прописать типы - // const { chatEntitieies, actions: { createCaht }} = useInbox() - // const { actions: { createCaht }} = useInbox() + const handleOpenInviteModal = (event: Event) => { + event.preventDefault() + showModal('inviteToChat') + } return (
+ + +
- + +
  • {t('All')}
  • -
  • {t('Conversations')}
  • +
  • {t('Personal')}
  • {t('Groups')}
- - {(author) => } + + {(chat) => }
@@ -185,7 +198,7 @@ export const InboxView = () => {
-
+