|
|
import FormGroup from "@/Components/FormGroup"; import InputError from "@/Components/InputError"; import InputLabel from "@/Components/InputLabel"; import TextInput from "@/Components/TextInput"; import Authenticated from "@/Layouts/AuthenticatedLayout"; import { PageProps } from "@/types"; import { Head, Link, useForm } from "@inertiajs/react"; import { Book, Box, CheckCircle, FileText, Paperclip, Plus, PlusCircle, XCircle, XOctagon } from "react-feather"; import 'codemirror/lib/codemirror.css'; import 'codemirror/mode/javascript/javascript'; import PrimaryButton from "@/Components/PrimaryButton"; import Instructions from "./InstructionsForm"; import Modal from "@/Components/Modal"; import ModalButton from "@/Components/ModalButton"; import { FormEventHandler, useEffect, useState } from "react"; import AddCategoryModal from "../SubjectCategory/AddModal"; import axios from "axios"; import SuccessButton from "@/Components/SuccessButton"; import ErrorButton from "@/Components/ErrorButton"; import dayjs from "dayjs";
interface Category { id: number; subject_title: string; description?: string; }
export default function Create({ auth }: PageProps) { const thisUser = auth.user;
const { data, setData, processing, errors } = useForm({ pageTitle: '', category: '', introduction:'', });
const [isAddCategoryModalOpen, setIsAddCategoryModalOpen] = useState(false); const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => { const selectedValue = e.target.value; setData('category', selectedValue); if (selectedValue === "0") { setIsAddCategoryModalOpen(true); } }
const [status, setStatus] = useState(''); const [feedback, setFeedback] = useState(''); const [isSuccessModalOpen, setIsSuccessModalOpen] = useState(false); const [isErrorModalOpen, setIsErrorModalOpen] = useState(false); const [categories, setCategories] = useState<Category[]>([]);
const fetchCategories = async () => { try { const response = await axios.get<Category[]>(route('categories.index')); setCategories(response.data); } catch (e) { setStatus('Function Failure'); setFeedback('Failed to fetch categories'); setIsErrorModalOpen(true); } };
useEffect(() => { if (thisUser.role_id !== 1) { setStatus('Warning'); setFeedback('You are unauthorized to access this page'); setIsErrorModalOpen(true); } else { fetchCategories(); } }, [thisUser.role_id]);
const handleCloseSuccessModal = () => { setIsSuccessModalOpen(false); window.location.href = '/dashboard'; }
const handleCloseErrorModal = () => { setIsErrorModalOpen(false); window.location.href = '/dashboard'; };
const [instructions, setInstructions] = useState<{ id: number; steps: any[]; frameworkID: string; }[]>([]); const [nextId, setNextId] = useState<number>(0); const handleAddInstruction = () => { setInstructions([...instructions, { id: nextId, steps: [], frameworkID: '' }]); setNextId(nextId + 1); }; const handleRemoveInstruction = (id: number) => { setInstructions(prevInstructions => prevInstructions.filter(instruction => instruction.id !== id) ); }; const handleUpdateInstruction = (id: number, steps: any[], frameworkID: string) => { setInstructions(prevInstructions => prevInstructions.map(instruction => instruction.id === id ? { ...instruction, steps, frameworkID } : instruction ) ); };
const submit: FormEventHandler = async (e) => { e.preventDefault();
if (data.category==="0" || data.category==="") { alert('Please choose a valid category.') return }
try { const response = await axios.post(route('page.add'), data); const pageID = response.data.page.id;
await Promise.all(instructions.map(async (instruction) => { if (instruction.frameworkID === "0" || instruction.frameworkID === "") { alert('Please choose a valid framework for each instruction.'); return; }
const timestamp = dayjs().format('YYYYMMDDHHmmss'); const jsonString = JSON.stringify({ steps: instruction.steps }); const blob = new Blob([jsonString], { type: 'application/json' }); const file = new File([blob], `${timestamp}.json`, { type: 'application/json' });
const formData = new FormData(); formData.append('file', file); formData.append('frameworkID', instruction.frameworkID); formData.append('pageID', pageID.toString());
await axios.post(route('instruction.add'), formData, { headers: { 'Content-Type': 'multipart/form-data', }, }); }));
setStatus('Success'); setFeedback(response.data.message); setIsSuccessModalOpen(true); } catch (error) { setStatus('Error') if (axios.isAxiosError(error)) { setFeedback(error.response?.data.message || 'An error occurred'); } else { setFeedback('An unexpected error occurred'); } setIsErrorModalOpen(true); } }
const renderIfAdmin = () => { if (thisUser.role_id === 1) { return ( <div> <div className="breadcrumbs text-sm"> <ul> <li><Link href="/dashboard">Home</Link></li> <li><a>Repository Pages</a></li> <li>Add New Repository Page</li> </ul> </div>
<h1 className="font-bold text-xl text-primary-main flex items-center my-2"><FileText className="stroke-primary-main mr-2" />Create Repository Page</h1> <div className="divider"></div> <form id="CreateRepositoryPageForm" onSubmit={submit}> <div> <FormGroup> <InputLabel htmlFor="pageTitle"><Box className='stroke-neutral-10' /></InputLabel> <label htmlFor="pageTitle" className="mx-2 font-semibold">Page Title:</label> </FormGroup> <TextInput id='pageTitle' name='pageTitle' value={data.pageTitle} autoComplete='off' required onChange={(e) => setData('pageTitle', e.target.value)} /> <InputError message={errors.pageTitle} className="mt-2" /> </div> <div> <FormGroup> <InputLabel htmlFor="category"><Book className='stroke-neutral-10' /></InputLabel> <label htmlFor="category" className="mx-2 font-semibold">Subject Category:</label> </FormGroup> <select name="category" id="category" value={data.category} onChange={handleChange} className='px-2 py-0 flex-grow w-full h-[30px] bg-primary-background border border-primary-hover focus:outline-none focus:bg-neutral-10 focus:border focus:border-primary-hover'> <option value="" selected disabled></option> {categories.map(category => ( <option key={category.id} value={category.id}> {category.subject_title} </option> ))} <option value="0" className="text-secondary-main font-semibold">Add new framework</option> </select> </div> <div> <FormGroup> <InputLabel htmlFor="description"><Paperclip className='stroke-neutral-10' /></InputLabel> <label htmlFor="description" className="mx-2 font-semibold">Introduction:</label> </FormGroup> <textarea className='px-2 flex-grow w-full bg-primary-background border border-primary-hover focus:outline-none focus:bg-neutral-10 focus:border-2 focus:border-primary-hover ' onChange={(e) => setData('introduction', e.target.value)} /> </div> {instructions.map((instruction) => ( <Instructions key={instruction.id} instruction_id={instruction.id} onDelete={handleRemoveInstruction} onUpdate={handleUpdateInstruction} /> ))} <PrimaryButton type='button' disabled={processing} onClick={handleAddInstruction} className="w-full"> <Plus className='stroke-neutral-10' /> Add Instruction </PrimaryButton> <div className="divider"></div> <div className="flex"> <ErrorButton className="w-1/2" onClick={() => window.location.href = '/dashboard'}> <XCircle className='stroke-neutral-10' /> Cancel </ErrorButton> <SuccessButton type="submit" className="w-1/2"> <PlusCircle className='stroke-neutral-10' /> Save Repository Page </SuccessButton> </div> </form> </div> ); } }
return ( <Authenticated user={thisUser}> <Head title="Repository Page" />
<div id="CreateRepositoryPage" className="drawer lg:drawer-open"> <input id="my-drawer-2" type="checkbox" className="drawer-toggle" /> <div className="drawer-content flex flex-row justify-between p-6 bg-neutral-20"> <div className="h-full w-full bg-neutral-10 shadow-md p-6 rounded-lg"> {renderIfAdmin()} </div> </div> <div className="drawer-side"> <label htmlFor="my-drawer-2" aria-label="close sidebar" className="drawer-overlay"></label> <ul className="menu p-4 w-56 h-full bg-primary-background text-base-content"> {/* Sidebar content here */} <li><a>Sidebar Item 1</a></li> <li><a>Sidebar Item 2</a></li> </ul> </div> </div>
<AddCategoryModal show={isAddCategoryModalOpen} onClose={() => setIsAddCategoryModalOpen(false)} onCategoryAdded={fetchCategories} />
<Modal show={isSuccessModalOpen} onClose={() => setIsSuccessModalOpen(false)} maxWidth="lg" styling='success'> <div className="p-4 flex flex-col items-center"> <CheckCircle className='stroke-success-main' size={80} /> <h2 className="text-xl font-bold mt-2">{ status }</h2> <p className="mt-4">{ feedback }</p> <ModalButton onClick={handleCloseSuccessModal} className="bg-success-main text-white hover:bg-success-hover active:bg-success-pressed"> Close </ModalButton> </div> </Modal>
<Modal show={isErrorModalOpen} onClose={() => setIsErrorModalOpen(false)} maxWidth="lg" styling='error'> <div className="p-4 flex flex-col items-center"> <XOctagon className='stroke-error-main' size={80} /> <h2 className="text-xl font-bold mt-2">{ status }</h2> <p className="mt-4">{ feedback }</p> <ModalButton onClick={handleCloseErrorModal} className="bg-error-main text-white hover:bg-error-hover active:bg-error-pressed"> Close </ModalButton> </div> </Modal> </Authenticated> ); }
|