A
Anonymous

Membership Dashboard - Copy this React, Tailwind Component to your project

Інтегруй код що ти написав в мій, в моєму navbar залиш import { observer } from "mobx-react-lite"; import React, { useEffect, useState } from "react"; import { Table } from "react-bootstrap"; import "./styles/Clients.css"; import toast from "react-hot-toast"; import ReactMarkdown from "react-markdown"; import remarkBreaks from "remark-breaks"; import useNotifications from "../components/hooks/useNotifications"; import NotificationsRow from "../components/NotificationsRow"; import { postNotification, updateNotification, } from "../http/notificationController"; import { useQueryClient } from "@tanstack/react-query"; import { ITEMS_PER_PAGE_COUNT } from "../utils/consts"; import usePagination from "../components/hooks/usePagination"; import Pagination from "rc-pagination"; import "rc-pagination/assets/index.css"; const Notifications = observer(() => { const { page, handlePageChange } = usePagination(); const { data, isLoading } = useNotifications(page); const [markDown, setMarkDown] = useState(""); const [previewMarkDown, setPreviewMarkDown] = useState(""); const [showModal, setShowModal] = useState(false); const [isEditModal, setIsEditModal] = useState(false); const [notificationToEdit, setNotificationToEdit] = useState({ id: "", text: "", photo: "", link: "", }); const [formValues, setFormValues] = useState({ photo: "", link: "", }); const [isLoadingButton, setIsLoadingButton] = useState(false); const queryClient = useQueryClient(); const resetState = () => { setMarkDown(""); setPreviewMarkDown(""); setFormValues({ link: "", photo: "", }); }; const handleFormChange = (e, name) => { const value = e.target.value; setFormValues((prev) => ({ ...prev, [name]: value, })); }; const handleAddNotification = async (e) => { e.preventDefault(); setIsLoadingButton(true); const newNotification = { text: markDown, photo: formValues.photo, link: formValues.link, }; const result = await postNotification(newNotification); if (result) { toast.success("Оповіщення успішно відправлено!"); setShowModal(false); resetState(); } else { toast.error("Щось пішло не так. Спробуйте пізніше!"); setShowModal(false); resetState(); } queryClient.invalidateQueries("notifications"); setIsLoadingButton(false); }; const handleEditNotification = async (e) => { e.preventDefault(); setIsLoadingButton(true); const newNotification = { text: markDown, photo: formValues.photo, link: formValues.link, }; const result = await updateNotification( notificationToEdit.id, newNotification ); if (result) { toast.success("Оповіщення успішно оновлено!"); } else { toast.error("Щось пішло не так. Спробуйте пізніше!"); } setShowModal(false); resetState(); setIsEditModal(false); queryClient.invalidateQueries("notifications"); setIsLoadingButton(false); }; const handleMarkdown = (e) => { const value = e.target.value; setMarkDown(value); setPreviewMarkDown( value.replace(/__(.*?)__/g, "*$1*").replace(/\*(.*?)\*/g, "**$1**") ); }; useEffect(() => { if (notificationToEdit) { setMarkDown(notificationToEdit.text); setPreviewMarkDown( notificationToEdit.text .replace(/__(.*?)__/g, "*$1*") .replace(/\*(.*?)\*/g, "**$1**") ); setFormValues((prev) => ({ link: notificationToEdit.link, photo: notificationToEdit.photo, })); } }, [notificationToEdit]); if (isLoading) return null; return ( <div className="root"> <button className="add-service" onClick={() => { setShowModal(true); setIsEditModal(false); resetState(); }} > Додати оповіщення </button> {!showModal ? ( <> <div className="user-table"> <Table hover page-size="4"> <thead style={{ width: "100%" }}> <tr> <th style={{ width: "30vw" }}>Текст оповіщення</th> <th style={{ width: "15vw" }}>Фото (посилання)</th> <th style={{ width: "15vw" }}>Трансляція (посилання)</th> <th style={{ width: "10vw" }}>Дії</th> </tr> </thead> <tbody> {data.notifications && data.notifications.length > 0 ? data.notifications.map((not) => { return ( <NotificationsRow key={not.id} notification={not} setIsEditModal={setIsEditModal} setNotification={setNotificationToEdit} setShowEditModal={setShowModal} /> ); }) : null} </tbody> </Table> </div> {data.totalPages <= 1 ? null : ( <Pagination current={page} total={data.totalPages * ITEMS_PER_PAGE_COUNT} pageSize={ITEMS_PER_PAGE_COUNT} onChange={handlePageChange} className="pagination" /> )} </> ) : ( <div className="notify-form"> <form onSubmit={ isEditModal ? handleEditNotification : handleAddNotification } > <div className="input_block"> <p>Текст</p> <textarea value={markDown} onChange={(e) => handleMarkdown(e)} placeholder="Введіть текст: *жирний*, _курсив_, натиснути Enter - перенос рядка, [Перейти на Google](https://www.google.com)" rows={20} cols={50} /> </div> {formValues.photo && ( <div className="image-preview" style={{ backgroundImage: `url(${formValues.photo})` }} /> )} <div className="input_block"> <p>Посилання на фото</p> <input type="text" placeholder="Посилання на фото" onChange={(e) => handleFormChange(e, "photo")} value={formValues.photo} /> </div> <div className="input_block"> <p>Посилання на трансляцію</p> <input type="text" placeholder="Посилання на трансляцію" value={formValues.link} onChange={(e) => handleFormChange(e, "link")} /> </div> <button type="submit" disabled={isLoadingButton}> {isLoadingButton ? "Завантаження..." : isEditModal ? "Зберегти" : "Додати"} </button> <button type="button" onClick={() => { setShowModal(false); resetState(); }} > Скасувати </button> </form> <div className="preview"> <p>Текст preview:</p> <ReactMarkdown remarkPlugins={[remarkBreaks]}> {previewMarkDown} </ReactMarkdown> </div> </div> )} </div> ); }); export default Notifications;

Prompt

About

MembershipDashboard - A sleek, user-friendly interface for managing memberships, built with React and Tailwind. Integrate seamlessly i. Download instantly!

Share

Last updated 1 month ago