xcage88

index

Nov 29th, 2023
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { showMessage } from '@/components/reuseable/ShowMessage';
  2. import { config } from '@/configs';
  3. import { cookieExpirationMiddleware } from '@/middlewares/WithAuth';
  4. import { IRootState } from '@/store';
  5. import { userLoginAzure, userLogout } from '@/store/azure-auth/actions';
  6. import { setPageTitle } from '@/store/themeConfigSlice';
  7. import { deleteData, deleteFile, getData, previewFile } from '@/utils/fetch';
  8. import { PaginationType } from '@/utils/interface';
  9. import { LifeFriendActivityType } from '@/utils/interface/life-activity';
  10. import showDialog from '@/utils/showDialog';
  11. import showDialogAction from '@/utils/showDialogAction';
  12. import { getCookie } from 'cookies-next';
  13. import sortBy from 'lodash/sortBy';
  14. import { DataTable, DataTableSortStatus } from 'mantine-datatable';
  15. import { useRouter } from 'next/router';
  16. import { useEffect, useState } from 'react';
  17. import { BsPencilFill } from 'react-icons/bs';
  18. import { FaTrash } from 'react-icons/fa';
  19. import { useDispatch, useSelector } from 'react-redux';
  20. import { useDebounce } from 'use-debounce';
  21.  
  22. const ActivityList = ({ token, name, username }: any) => {
  23.     const router = useRouter();
  24.     const dispatch = useDispatch();
  25.     const { token: tokenBackup }: any = useSelector((state: IRootState) => state.azureAuth);
  26.  
  27.     useEffect(() => {
  28.         if (token) {
  29.             dispatch(userLoginAzure(token, name, username));
  30.         }
  31.     }, []);
  32.  
  33.     useEffect(() => {
  34.         // const checkSession = async () => {
  35.         const check = cookieExpirationMiddleware(token, tokenBackup);
  36.         if (check) {
  37.             showMessage('Sesi telah berakhir, Silahkan login kembali', 'error');
  38.             dispatch(userLogout());
  39.             router.push('/auth/login-v2');
  40.         }
  41.         // };
  42.         // checkSession();
  43.     }, []);
  44.  
  45.     const [page, setPage] = useState(1);
  46.     const PAGE_SIZES = [10, 20, 30, 50, 100];
  47.     const [pageSize, setPageSize] = useState(PAGE_SIZES[0]);
  48.     const [initialRecords, setInitialRecords] = useState<LifeFriendActivityType[]>([]);
  49.     const [recordsData, setRecordsData] = useState<LifeFriendActivityType[]>(initialRecords);
  50.     const [selectedRecords, setSelectedRecords] = useState<any>([]);
  51.     const [sortStatus, setSortStatus] = useState<DataTableSortStatus>({
  52.         columnAccessor: 'id',
  53.         direction: 'asc',
  54.     });
  55.     const [search, setSearch] = useState('');
  56.     const [searchKey] = useDebounce(search, 500);
  57.     const [pagination, setPagination] = useState<PaginationType>();
  58.     const [indicator, setIndicator] = useState<boolean>(false);
  59.     const [isLoading, setisLoading] = useState<boolean>(false);
  60.  
  61.     const formatDate = (dateString: any) => {
  62.         const date = new Date(dateString);
  63.         const year = date.getFullYear();
  64.         const month = String(date.getMonth() + 1).padStart(2, '0');
  65.         const day = String(date.getDate()).padStart(2, '0');
  66.         return `${year}-${month}-${day}`;
  67.     };
  68.  
  69.     const handleDeleteItem = async (id?: string, fileName?: string, fileName2?: string) => {
  70.         if (selectedRecords?.length) {
  71.             const payload = selectedRecords?.map((item: any) => item.id);
  72.             const selectedDelete = selectedRecords.map((item: any) => item.desktop_link);
  73.             const selectedDelete2 = selectedRecords.map((item: any) => item.mobile_link);
  74.             //* delete all
  75.             showDialogAction(async () => {
  76.                 try {
  77.                     await deleteData(`/lifefriend-activity/batch-delete`, payload);
  78.                     await deleteFile({ paths: selectedDelete });
  79.                     await deleteFile({ paths: selectedDelete2 });
  80.                     console.log(payload)
  81.                     console.log(selectedDelete)
  82.                     setIndicator(!indicator);
  83.                     setSelectedRecords([]);
  84.                     showDialog('delete', 'success');
  85.                 } catch (error: any) {
  86.                     error.response.data.message === 'Sesi Anda telah berakhir!' ? null : showDialog('delete', 'failed');
  87.                 }
  88.             });
  89.         } else {
  90.             //* delete one
  91.             showDialogAction(async () => {
  92.                 try {
  93.                     await deleteData(`/lifefriend-activity/delete/${id}`);
  94.                     await deleteFile({ paths: [fileName] });
  95.                     await deleteFile({ paths: [fileName2] });
  96.                     setIndicator(!indicator);
  97.                     showDialog('delete', 'success');
  98.                 } catch (error: any) {
  99.                     error.response.data.message === 'Sesi Anda telah berakhir!' ? null : error.response.data.message === 'Sesi Anda telah berakhir!' ? null : showDialog('delete', 'failed');
  100.                 }
  101.             });
  102.         }
  103.     };
  104.  
  105.     //* get data
  106.     useEffect(() => {
  107.         if (token) {
  108.             const getDataBanner = async () => {
  109.                 try {
  110.                     setisLoading(true);
  111.                     const { data } = await getData('/lifefriend-activity', { page: page, limit: pageSize, search: searchKey });
  112.                     setInitialRecords(data.activities);
  113.                     setPagination(data.pagination);
  114.                     setisLoading(false);
  115.                 } catch (error: any) {
  116.                     setisLoading(false);
  117.                 }
  118.             };
  119.             getDataBanner();
  120.         }
  121.     }, [indicator, page, pageSize, searchKey]);
  122.  
  123.     useEffect(() => {
  124.         if (page == 1) return;
  125.         if (initialRecords.length == 0) return setPage(page - 1);
  126.     }, [initialRecords]);
  127.  
  128.     useEffect(() => {
  129.         setPage(1);
  130.     }, [pageSize]);
  131.  
  132.     useEffect(() => {
  133.         setRecordsData([...initialRecords]);
  134.     }, [page, pageSize, initialRecords]);
  135.  
  136.     useEffect(() => {
  137.         const data = sortBy(initialRecords, sortStatus.columnAccessor);
  138.         setInitialRecords(sortStatus.direction === 'desc' ? data.reverse() : data);
  139.     }, [sortStatus]);
  140.  
  141.     useEffect(() => {
  142.         dispatch(setPageTitle('Life Friend Activity List'));
  143.     });
  144.  
  145.     return (
  146.         <div className="banner">
  147.             <div className="mb-4 flex justify-between">
  148.                 <div>
  149.                     <h5 className="title-banner  text-lg dark:text-white-light">Activity List</h5>
  150.                     <div className="subtitle-banner">Daftar Activity List.</div>
  151.                 </div>
  152.                 <div className="flex gap-2">
  153.                     {selectedRecords.length >= 1 ? (
  154.                         <div
  155.                             className="btn-delete-item-banner flex items-center"
  156.                             onClick={() => {
  157.                                 handleDeleteItem('yang terpilih');
  158.                             }}
  159.                         >
  160.                             Hapus Terpilih
  161.                         </div>
  162.                     ) : (
  163.                         <></>
  164.                     )}
  165.  
  166.                     <div className="btn-add-item-banner flex items-center" onClick={() => router.push('activity-list/input')}>
  167.                         Tambah
  168.                     </div>
  169.                 </div>
  170.             </div>
  171.             <div className="mb-5 flex flex-col gap-5 md:flex-row md:items-center">
  172.                 <div className="flex items-center gap-2 ltr:ml-auto rtl:mr-auto">
  173.                     <label
  174.                         htmlFor="search"
  175.                         style={{
  176.                             marginBottom: '0',
  177.                         }}
  178.                     >
  179.                         Search :{' '}
  180.                     </label>
  181.                     <input type="text" name="search" className="form-input w-auto" placeholder="Search..." value={search} onChange={(e) => setSearch(e.target.value)} />
  182.                 </div>
  183.             </div>
  184.             <div className="datatables">
  185.                 <DataTable
  186.                     className="table-hover whitespace-normal"
  187.                     records={recordsData}
  188.                     columns={[
  189.                         {
  190.                             accessor: 'created_at',
  191.                             title: 'Tanggal',
  192.                             sortable: true,
  193.                             render: ({ created_at }) => (
  194.                                 <div className="flex items-center gap-2">
  195.                                     <div className="title-item-table font-semibold">{formatDate(created_at)}</div>
  196.                                 </div>
  197.                             ),
  198.                         },
  199.                         {
  200.                             accessor: 'link_image',
  201.                             title: 'Cover Gambar',
  202.                             sortable: true,
  203.                             render: ({ link_image }) => (
  204.                                 <div className="flex items-center gap-2">
  205.                                     <div className="title-item-table font-semibold">
  206.                                         <a href={config.BASE_URL_IMG + link_image} target='_blank' rel="noreferrer" className='text-blue-600'>
  207.                                             image.jpeg
  208.                                         </a>
  209.                                     </div>
  210.                                 </div>
  211.                             ),
  212.                         },
  213.                         {
  214.                             accessor: 'alt_text',
  215.                             title: 'Alternatif Teks',
  216.                             sortable: true,
  217.                             render: ({ alt_text }) => (
  218.                                 <div className="flex items-center gap-2">
  219.                                     <div className="title-item-table font-semibold">{alt_text}</div>
  220.                                 </div>
  221.                             ),
  222.                         },
  223.                         {
  224.                             accessor: 'title',
  225.                             title: 'Title',
  226.                             sortable: true,
  227.                         },
  228.                         {
  229.                             accessor: 'description',
  230.                             title: 'Deskripsi',
  231.                             sortable: true,
  232.                             render: ({ description }) => <p className={`truncateTd whitespace-nowrap xl:whitespace-normal`}>{description}</p>,
  233.                         },
  234.                         {
  235.                             accessor: 'status',
  236.                             title: 'Status',
  237.                             sortable: true,
  238.                             render: ({ status }) => <div className={`flex justify-center ${status.toLocaleLowerCase() == 'active' ? 'active-status-tabel' : 'notactive-status-tabel'}`}>{status}</div>,
  239.                         },
  240.                         {
  241.                             accessor: 'item_activities',
  242.                             title: 'Content Image',
  243.                             sortable: true,
  244.                             render: ({item_activities}) => (
  245.                                 <div className='text-center'>
  246.                                     <p>{item_activities.map(item => item.link_image).length} image</p>
  247.                                 </div>
  248.                             )
  249.                         },
  250.                         {
  251.                             accessor: '',
  252.                             title: 'Action',
  253.                             render: ({ id, title, description, alt_text, link_image, status }) => (
  254.                                 <div className={`flex gap-3 `}>
  255.                                     <BsPencilFill
  256.                                         size={20}
  257.                                         className="cursor-pointer"
  258.                                         color="#0083F5"
  259.                                         onClick={() => {
  260.                                             router.push(
  261.                                                 {
  262.                                                     pathname: 'activity/input',
  263.                                                     query: { id, title, description, alt_text, link_image, status },
  264.                                                 },
  265.                                                 'activity/input'
  266.                                             );
  267.                                         }}
  268.                                     />
  269.                                     <FaTrash
  270.                                         size={20}
  271.                                         className="cursor-pointer"
  272.                                         color=" #E30008"
  273.                                         onClick={() => {
  274.                                             handleDeleteItem(id, link_image);
  275.                                         }}
  276.                                     />
  277.                                 </div>
  278.                             ),
  279.                         },
  280.                     ]}
  281.                     fetching={isLoading}
  282.                     highlightOnHover
  283.                     totalRecords={pagination?.total}
  284.                     recordsPerPage={pageSize}
  285.                     page={page}
  286.                     onPageChange={(p) => setPage(p)}
  287.                     recordsPerPageOptions={PAGE_SIZES}
  288.                     onRecordsPerPageChange={setPageSize}
  289.                     sortStatus={sortStatus}
  290.                     onSortStatusChange={setSortStatus}
  291.                     selectedRecords={selectedRecords}
  292.                     onSelectedRecordsChange={setSelectedRecords}
  293.                     minHeight={200}
  294.                     paginationText={({ from, to, totalRecords }) => `Showing  ${from} to ${to} of ${pagination?.total} entries`}
  295.                 />
  296.             </div>
  297.         </div>
  298.     );
  299. };
  300.  
  301. export default ActivityList;
  302.  
  303. export async function getServerSideProps({ req }: any) {
  304.     const token = getCookie('access_token', { req });
  305.     const name = getCookie('name', { req });
  306.     const username = getCookie('username', { req });
  307.     // if (!token) {
  308.     //     return {
  309.     //         redirect: {
  310.     //             destination: '/auth/login-v2',
  311.     //             permanent: false,
  312.     //         },
  313.     //     };
  314.     // }
  315.  
  316.     if (token) {
  317.         return {
  318.             props: { token, name, username },
  319.         };
  320.     }
  321.  
  322.     return {
  323.         props: {},
  324.     };
  325. }
  326.  
Add Comment
Please, Sign In to add comment