// Dependencies import { uiRoles as roles } from '@freesewing/config' import { userAvatarUrl } from '@freesewing/utils' // Hooks import React, { useState, useContext, useEffect } from 'react' import { useAccount } from '@freesewing/react/hooks/useAccount' import { useBackend } from '@freesewing/react/hooks/useBackend' // Context import { LoadingStatusContext } from '@freesewing/react/context/LoadingStatus' import { ModalContext } from '@freesewing/react/context/Modal' // Components import { Spinner } from '@freesewing/react/components/Spinner' //import { Hits } from 'shared/components/admin.mjs' import { Link as WebLink } from '@freesewing/react/components/Link' import { SearchIcon } from '@freesewing/react/components/Icon' import { KeyVal } from '@freesewing/react/components/KeyVal' import { Markdown } from '@freesewing/react/components/Markdown' import { ModalWrapper } from '@freesewing/react/components/Modal' import { AccountStatus, UserRole } from '@freesewing/react/components/Account' export const SubscriberAdministration = ({ page }) => { const [subscribers, setSubscribers] = useState() const [q, setQ] = useState() const [hits, setHits] = useState([]) const backend = useBackend() const loadSubscribers = async () => { const [status, body] = await backend.adminLoadSubscribers() if (status === 200 && body.subscribers) setSubscribers(body.subscribers) } const search = async () => { if (!subscribers) await loadSubscribers() const found = [] for (const lang in subscribers) { found.push( ...subscribers[lang] .filter((sub) => sub.email.toLowerCase().includes(q.toLowerCase())) .map((sub) => ({ ...sub, lang })) ) } setHits(found) } const unsubscribe = async (ehash) => { await backend.newsletterUnsubscribe(ehash) await loadSubscribers() await search() } return ( <> {subscribers ? ( <>
Search subscribers
setQ(evt.target.value)} className="tw-daisy-input tw-w-full tw-daisy-input-bordered tw-flex tw-flex-row" type="text" placeholder="Username, ID, or E-mail address" />
{hits.map((hit, i) => ( ))}
Email Language Unsubscribe
{hit.email} {hit.lang.toUpperCase()}
) : ( )} ) } export const UserAdministration = ({ Link = false }) => { const backend = useBackend() const [q, setQ] = useState('') const [results, setResults] = useState() const [loading, setLoading] = useState(false) const search = async () => { /* * Search backend */ setLoading(true) const [status, body] = await backend.adminSearchUsers(q) if (status === 200 && body.result === 'success' && body.users) { setResults(body.users) } setLoading(false) } return ( <>
Search users
setQ(evt.target.value)} className="tw-daisy-input tw-w-full tw-daisy-input-bordered tw-flex tw-flex-row" type="text" placeholder="Username, ID, or E-mail address" />
{loading ? : }
) } export const Hits = ({ results, Link = false }) => { if (!Link) Link = WebLink return ( <> {results && results.username && results.username.length > 0 && ( <>

Results based on username

{results.username.map((user) => ( ))} )} {results && results.email && results.email.length > 0 && ( <>

Results based on E-mail address

{results.email.map((user) => ( ))} )} ) } export const User = ({ user, Link }) => { const { setModal } = useContext(ModalContext) return (
{user.username}
) } export const ImpersonateButton = ({ userId }) => { const backend = useBackend() const { setLoadingStatus } = useContext(LoadingStatusContext) const { impersonate } = useAccount() if (!userId) return null const impersonateUser = async () => { setLoadingStatus([true, 'Contacting backend']) const [status, body] = await backend.adminImpersonateUser(userId) if (status === 200 && body.result === 'success') { impersonate(body) setLoadingStatus([true, 'Now impersonating', true, true]) } else setLoadingStatus([true, 'An error occured', true, false]) } return ( ) } export const Row = ({ title, val }) => ( {title} {val} ) export const ManageUser = ({ userId }) => { // Hooks const backend = useBackend() const { setLoadingStatus } = useContext(LoadingStatusContext) const { account } = useAccount() const { role } = account // State const [user, setUser] = useState({}) const [patterns, setPatterns] = useState({}) const [sets, setSets] = useState({}) // Effect useEffect(() => { const loadUser = async () => { const result = await backend.adminLoadUser(userId) if (result.success) { setUser(result.data.user) setPatterns(result.data.patterns) setSets(result.data.sets) } } loadUser() }, [userId]) const updateUser = async (data) => { setLoadingStatus([true, 'status:contactingBackend']) const result = await backend.adminUpdateUser({ id: userId, data }) if (result.success) { setLoadingStatus([true, 'status:settingsSaved', true, true]) setUser(result.data.user) } else setLoadingStatus([true, 'status:backendError', true, false]) } return user.id ? (
: null} /> {role === 'admin' ? (
{roles.map((role) => ( ))}
) : null}
{user.mfaEnabled && ( )} {Object.keys(freeSewingConfig.statuses).map((status) => ( ))}
{user.id ? : null} {patterns ? : null} {sets ? : null}
) : ( ) }