xcage88

input

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