123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import { FunctionComponent } from 'react'
- import AdminPage from './AdminPage'
- import Link from 'next/link'
- import theme from '../../styles/theme'
- import { QueryResult, MutationTuple, QueryHookOptions, MutationHookOptions } from '@apollo/client'
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
- import { faEdit, faTrash, faPlusCircle } from '@fortawesome/free-solid-svg-icons'
- interface IAdminList<TQueryData, TQueryVariables, TDeleteData, TDeleteVariables> {
- name: string
- adminMenu?: string
- dataKey: keyof TQueryData
- get: (
- baseOptions?: QueryHookOptions<TQueryData, TQueryVariables>
- ) => QueryResult<TQueryData, TQueryVariables>
- remove?: (
- baseOptions?: MutationHookOptions<TDeleteData, TDeleteVariables>
- ) => MutationTuple<TDeleteData, TDeleteVariables>
- Component: FunctionComponent<any>
- }
- const AdminList = <
- TQueryData extends { [dataKey: string]: any[] },
- TQueryVariables,
- TDeleteData,
- TDeleteVariables
- >({
- name,
- adminMenu,
- dataKey,
- get,
- remove,
- Component,
- }: IAdminList<TQueryData, TQueryVariables, TDeleteData, TDeleteVariables>) => {
- const [removeFunction, removeResult] = remove ? remove() : [undefined, undefined]
- const { data, error, loading, refetch } = get({ fetchPolicy: 'network-only' })
- let content
- if (loading) content = <p>Loading data...</p>
- else if (error) content = <p>Error loading data.</p>
- else if (!data) content = <p>No data found.</p>
- else
- content = (
- <ul>
- {data[dataKey].map((item: any) => (
- <li key={item.id}>
- <Component key={item.id} item={item} className='admin-component' />
- <div className='admin-toolbar'>
- <Link href={`/${adminMenu}/[id]`} as={`${adminMenu}/${item.id}`}>
- <a title='edit'>
- <button type='button'>
- <FontAwesomeIcon icon={faEdit} height={16} />
- </button>
- </a>
- </Link>
- {removeFunction && (
- <button
- onClick={async (event) => {
- const deletedItem = await removeFunction({ variables: { id: item.id } } as any)
- if (deletedItem) refetch()
- }}
- disabled={removeResult?.loading}
- title='delete'
- >
- <FontAwesomeIcon icon={faTrash} height={16} />
- </button>
- )}
- </div>
- </li>
- ))}
- <style jsx>{`
- ul {
- padding: 0;
- }
- ul :global(li) {
- padding: 0.2em 0.5em;
- display: flex;
- list-style: none;
- align-items: center;
- background-color: #0770;
- transition: background-color 250ms ease-in-out;
- border-top: 1px solid #0002;
- position: relative;
- }
- ul :global(li:last-child) {
- border-bottom: 1px solid #0002;
- }
- ul :global(li:hover) {
- background-color: ${theme.colors.formHighlightBackground}22;
- }
- ul :global(.admin-component) {
- flex-grow: 1;
- }
- ul :global(.admin-toolbar button) {
- padding: 0.4em;
- margin: 0;
- color: ${theme.colors.buttonBackground};
- background-color: transparent;
- }
- ul :global(a) {
- color: ${theme.colors.highlight};
- text-decoration: none;
- }
- ul :global(button > a) {
- color: ${theme.colors.button};
- text-decoration: none;
- }
- ul :global(li .admin-toolbar) {
- display: none;
- position: absolute;
- top: 0;
- right: 0;
- width: 80px;
- background-color: ${theme.colors.background};
- box-shadow: ${theme.bsSmall};
- }
- ul :global(li:hover .admin-toolbar) {
- display: flex;
- }
- `}</style>
- </ul>
- )
- return (
- <AdminPage>
- <h2>{name}</h2>
- <Link href={`${adminMenu}/create`}>
- <a>
- <button>
- <FontAwesomeIcon icon={faPlusCircle} height={36} />
- </button>
- </a>
- </Link>
- {content}
- <style jsx>{`
- button {
- color: ${theme.colors.buttonBackground};
- background-color: transparent;
- display: inline;
- margin: 0.4rem;
- padding: 0;
- }
- `}</style>
- </AdminPage>
- )
- }
- export default AdminList
|