diff --git a/src/components/Button.jsx b/src/components/Button.jsx index b965282cf8aa61a0c5906ec447f9eaaaaf7be1bd..3e7b79152138a6784b0478ddc1c2cb0c547a1efa 100644 --- a/src/components/Button.jsx +++ b/src/components/Button.jsx @@ -4,6 +4,7 @@ import classNames from "classnames"; const Button = ({ className, + bodyClassName, icon, color = "black", hoverActive = true, @@ -25,9 +26,11 @@ const Button = ({ className ); + const bodyClass = classNames("btn__body", bodyClassName); + const inner = ( <div className="btn__body-wrap"> - <div className="btn__body">{children}</div> + <div className={bodyClass}>{children}</div> {!!icon && ( <div className="btn__icon"> <i className={icon}></i> diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index 9c6298aa1eae93bfa0fc464a8251bde768f8d7e9..4a5fb9ca55913d488a3d5cb2329e1b5ebd87e460 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -36,23 +36,28 @@ const Navbar = () => { }; const connectionIndicator = ( - <span - className="relative inline-flex h-4 w-4 mr-4" - title={connectionStateCaption} - > + <div className="inline-flex items-center order-first md:order-last md:ml-8 lg:order-first lg:mr-8 lg:ml-0"> <span - className={classNames( - "animate-ping absolute inline-flex h-full w-full rounded-full opacity-75", - indicatorClass - )} - /> - <span - className={classNames( - "inline-flex rounded-full w-4 h-4", - indicatorClass - )} - /> - </span> + className="relative inline-flex h-4 w-4 mr-4" + title={connectionStateCaption} + > + <span + className={classNames( + "animate-ping absolute inline-flex h-full w-full rounded-full opacity-75", + indicatorClass + )} + /> + <span + className={classNames( + "inline-flex rounded-full w-4 h-4", + indicatorClass + )} + /> + </span> + <span className="hidden md:block text-grey-200"> + {connectionStateCaption} + </span> + </div> ); return ( @@ -113,7 +118,10 @@ const Navbar = () => { alt="Avatar" /> </div> - <button onClick={logout}> + <button + onClick={logout} + className="text-grey-200 hover:text-white" + > <i className="ico--log-out"></i> </button> </div> diff --git a/src/components/annoucements/Announcement.jsx b/src/components/annoucements/Announcement.jsx index 0d9f9c1db37ffd5729ade4d18d5591f9b9d89dff..1cd7e38088b55084f9aa2c08e78b3ed57e94babd 100644 --- a/src/components/annoucements/Announcement.jsx +++ b/src/components/annoucements/Announcement.jsx @@ -105,13 +105,13 @@ const Announcement = ({ {showEdit && ( <DropdownMenuItem onClick={onEdit} - icon="ico--edit-pencil" + icon="ico--pencil" title="Upravit" /> )} <DropdownMenuItem onClick={onDelete} - icon="ico--trashcan" + icon="ico--bin" title="Smazat" /> </DropdownMenu> diff --git a/src/components/annoucements/AnnouncementEditModal.jsx b/src/components/annoucements/AnnouncementEditModal.jsx index 795d696d104f4e081be75f38e6387ba9418c8f97..2f666543e7a0bbea47605a5a5448c67d1a63f7be 100644 --- a/src/components/annoucements/AnnouncementEditModal.jsx +++ b/src/components/annoucements/AnnouncementEditModal.jsx @@ -72,7 +72,7 @@ const AnnouncementEditModal = ({ <div className="flex items-center justify-between mb-4"> <CardHeadline>Upravit oznámení</CardHeadline> <button onClick={onCancel} type="button"> - <i className="ico--close"></i> + <i className="ico--cross"></i> </button> </div> <MarkdownEditor @@ -104,7 +104,7 @@ const AnnouncementEditModal = ({ onChange={(evt) => onLinkInput(evt.target.value)} /> <div className="text-input-addon text-input-addon--l order-first"> - <i className="ico--link1"></i> + <i className="ico--link"></i> </div> </div> {linkValid === false && ( diff --git a/src/components/annoucements/AnnouncementList.jsx b/src/components/annoucements/AnnouncementList.jsx index 7df00e6a4be87324de89dbdc0c3d90dd7677468d..3e3ba8df05e29b83a605095569dc509ad3a48ff8 100644 --- a/src/components/annoucements/AnnouncementList.jsx +++ b/src/components/annoucements/AnnouncementList.jsx @@ -23,10 +23,23 @@ const AnnouncementList = ({ onSeen(announcement); }; + const getClassName = (idx) => { + if (idx === 0) { + return "pt-4 lg:pt-8"; + } + + if (idx === items.length - 1) { + return "pb-4 lg:pb-8"; + } + + return ""; + }; + return ( <div className={classNames("space-y-px", className)}> - {items.map((item) => ( + {items.map((item, idx) => ( <Announcement + className={getClassName(idx)} key={item.id} datetime={item.datetime} type={item.type} diff --git a/src/components/modals/ModalConfirm.jsx b/src/components/modals/ModalConfirm.jsx index 52cf87a3eed5453383ec5b25ea1f7f93ada600dc..cfe8d26e1ae800e43bdc94a27122247d2cda665e 100644 --- a/src/components/modals/ModalConfirm.jsx +++ b/src/components/modals/ModalConfirm.jsx @@ -30,7 +30,7 @@ const ModalConfirm = ({ <div className="flex items-center justify-between mb-4"> <CardHeadline>{title}</CardHeadline> <button onClick={onCancel} type="button"> - <i className="ico--close"></i> + <i className="ico--cross"></i> </button> </div> <CardBodyText>{children}</CardBodyText> diff --git a/src/components/posts/PostEditModal.jsx b/src/components/posts/PostEditModal.jsx index edbae531b246e0ccb829dc17f3ed90a13a851470..e880b05d5b608f3a58a961a8d17903fb5313cbab 100644 --- a/src/components/posts/PostEditModal.jsx +++ b/src/components/posts/PostEditModal.jsx @@ -43,7 +43,7 @@ const PostEditModal = ({ <div className="flex items-center justify-between mb-4"> <CardHeadline>Upravit text příspěvku</CardHeadline> <button onClick={onCancel} type="button"> - <i className="ico--close"></i> + <i className="ico--cross"></i> </button> </div> <MarkdownEditor diff --git a/src/components/posts/PostList.jsx b/src/components/posts/PostList.jsx index 170a9587eb770d8fae8703a18c4fea16300abe7b..48caa5b08f0b6979e63414e3c789b4063c1465f4 100644 --- a/src/components/posts/PostList.jsx +++ b/src/components/posts/PostList.jsx @@ -6,6 +6,7 @@ import Post from "./Post"; const PostList = ({ className, items, + showAddPostCta, currentUser, canThumb, dimArchived, @@ -83,7 +84,7 @@ const PostList = ({ onSeen={onPostSeen(item)} /> ))} - {!items.length && ( + {showAddPostCta && !items.length && ( <p className="p-4 lg:p-0 lg:py-3 leading-snug text-sm md:text-base"> Nikdo zatím žádný odpovídající příspěvek do rozpravy nepřidal. Budeš první? diff --git a/src/components/program/ProgramEntryEditModal.jsx b/src/components/program/ProgramEntryEditModal.jsx index 90b5385514fa5d3424277ad6d8865334b52b64e3..37ce3f44cd6326da5bec318be4fb736f0ebcc904 100644 --- a/src/components/program/ProgramEntryEditModal.jsx +++ b/src/components/program/ProgramEntryEditModal.jsx @@ -29,7 +29,7 @@ const ProgramEntryEditModal = ({ <div className="flex items-center justify-between mb-4"> <CardHeadline>Upravit název programového bodu</CardHeadline> <button onClick={onCancel}> - <i className="ico--close"></i> + <i className="ico--cross"></i> </button> </div> <div className="form-field"> diff --git a/src/containers/AddAnnouncementForm.jsx b/src/containers/AddAnnouncementForm.jsx index 3f964577056a48705f6d0cde617b311ebfc30f30..1413ece707368cf4676ca8b1ef6abb3d9ec9aec9 100644 --- a/src/containers/AddAnnouncementForm.jsx +++ b/src/containers/AddAnnouncementForm.jsx @@ -135,7 +135,7 @@ const AddAnnouncementForm = ({ className }) => { onChange={(evt) => onLinkInput(evt.target.value)} /> <div className="text-input-addon text-input-addon--l order-first"> - <i className="ico--link1"></i> + <i className="ico--link"></i> </div> </div> {linkValid === false && ( diff --git a/src/containers/JitsiInviteCard.jsx b/src/containers/JitsiInviteCard.jsx new file mode 100644 index 0000000000000000000000000000000000000000..5f480dd86196fe9dcbfb553b7af1fc2bb62d43dd --- /dev/null +++ b/src/containers/JitsiInviteCard.jsx @@ -0,0 +1,38 @@ +import React from "react"; + +import Button from "components/Button"; +import { Card, CardBody } from "components/cards"; +import { AuthStore } from "stores"; + +const JitsiInviteCard = () => { + const { showJitsiInvitePopup } = AuthStore.useState(); + + if (!showJitsiInvitePopup) { + return null; + } + + return ( + <Card className="lg:card bg-violet-300 relative" elevation={16}> + <i className="ico--jitsi text-9xl mr-2 text-violet-500 absolute right-0 top-0 opacity-25 z-0" /> + <CardBody className="text-white relative z-10"> + <div className="flex items-center justify-between mb-4"> + <h2 className="head-heavy-xs"> + <span>Pozvánka do Jitsi</span> + </h2> + <button type="button"> + <i className="ico--cross"></i> + </button> + </div> + <p className="leading-snug text-sm mb-4"> + Někdo tě pozval do <strong>chráněného Jitsi kanálu</strong>{" "} + celeostátního fóra. Ke kanálu se připojíš kliknutím na tlačítko níže. + </p> + <Button color="violet-500" className="btn--fullwidth"> + Otevřít Jitsi kanál + </Button> + </CardBody> + </Card> + ); +}; + +export default JitsiInviteCard; diff --git a/src/containers/PostsContainer.jsx b/src/containers/PostsContainer.jsx index fdfb5157e12fcd19e742f173900ab98b1f2609d9..daf2a39ccb9609dac229d5f8ed9122ddca04b299 100644 --- a/src/containers/PostsContainer.jsx +++ b/src/containers/PostsContainer.jsx @@ -22,7 +22,7 @@ import PostList from "components/posts/PostList"; import { useActionState, useItemActionConfirm } from "hooks"; import { AuthStore, PostStore } from "stores"; -const PostsContainer = ({ className }) => { +const PostsContainer = ({ className, showAddPostCta }) => { const [postToEdit, setPostToEdit] = useState(null); const [confirmingEdit, setConfirmingEdit] = useState(false); const [editError, setEditError] = useState(null); @@ -165,6 +165,7 @@ const PostsContainer = ({ className }) => { )} <PostList items={windowItems.slice(sliceStart, sliceEnd)} + showAddPostCta={showAddPostCta} canThumb={isAuthenticated} onLike={like.run} onDislike={dislike.run} diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index 06ebfcf5f2d14591f081cbe90a7fd3a21e579a69..f6ecd8c39115ecced44b65d6a6f3253db50e85ec 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -17,6 +17,7 @@ import AddAnnouncementForm from "containers/AddAnnouncementForm"; import AddPostForm from "containers/AddPostForm"; import AnnouncementsContainer from "containers/AnnoucementsContainer"; import GlobalStats from "containers/GlobalStats"; +import JitsiInviteCard from "containers/JitsiInviteCard"; import PostFilters from "containers/PostFilters"; import PostsContainer from "containers/PostsContainer"; import { useActionConfirm } from "hooks"; @@ -167,7 +168,7 @@ const Home = () => { > <DropdownMenuItem onClick={() => setShowProgramEditModal(true)} - icon="ico--edit-pencil" + icon="ico--pencil" title="Přejmenovat bod programu" titleSize="base" iconSize="base" @@ -225,12 +226,10 @@ const Home = () => { </div> </section> - <section className="cf2021__notifications"> - <div className="lg:card lg:elevation-10"> - <div className="lg:card__body pb-2 lg:py-6"> - <h2 className="head-heavy-xs md:head-heavy-sm">Oznámení</h2> - </div> + <section className="cf2021__notifications space-y-8"> + <JitsiInviteCard /> + <div className="lg:card lg:elevation-10"> <AnnouncementsContainer className="container-padding--zero lg:container-padding--auto" /> {isAuthenticated && user.role === "chairman" && ( <AddAnnouncementForm className="lg:card__body pt-4 lg:py-6" /> @@ -248,17 +247,21 @@ const Home = () => { title="Rozprava je uzavřena" /> )} - {programEntry.discussionOpened && ( - <i - className="ico--lock-open text-black ml-1 opacity-50 hover:opacity-100 transition duration-500 text-xl" - title="Probíhá rozprava" - /> - )} </h2> <PostFilters /> </div> - <PostsContainer className="container-padding--zero lg:container-padding--auto" /> + <PostsContainer + className="container-padding--zero lg:container-padding--auto" + showAddPostCta={programEntry.discussionOpened} + /> + {!programEntry.discussionOpened && + isAuthenticated && + !user.isBanned && ( + <p className="leading-normal"> + Rozprava je uzavřena - příspěvky teď nelze přidávat. + </p> + )} {programEntry.discussionOpened && isAuthenticated && !user.isBanned && <AddPostForm className="my-8 space-y-4" />} diff --git a/src/stores.js b/src/stores.js index 38a0dfa80bd0654ff3f3e2161c7e04ed7a9bf716..ef639cdf0967da211d67cd280a1b4169546642d2 100644 --- a/src/stores.js +++ b/src/stores.js @@ -15,6 +15,7 @@ export const GlobalInfoStore = new Store(globalInfoStoreInitial); /** @type {CF2021.AuthStorePayload} */ const authStoreInitial = { isAuthenticated: false, + showJitsiInvitePopup: false, }; export const AuthStore = new Store(authStoreInitial); diff --git a/typings/cf2021.d.ts b/typings/cf2021.d.ts index 154eab942829e0aa72758d97b8da0273eaeca055..45723320406ec4fa10f0f1f553160028e52a0ef6 100644 --- a/typings/cf2021.d.ts +++ b/typings/cf2021.d.ts @@ -49,6 +49,8 @@ declare namespace CF2021 { group?: string; secret?: string; }; + showJitsiInvitePopup: boolean; + jitsiInviteToken?: string; } export type AuthStorePayload =