UNPKG

leumas-private-shared

Version:

Private React JSX Package For Leumas Shared Components, Headers, Footers, Asides, Login Pages, API Key Manager and much more. Styles and everything reusable to avoid DRY code across all of our subdomains

218 lines (198 loc) 8.62 kB
import React, { useState } from 'react'; import { saveAs } from 'file-saver'; const ColumnBuilder = () => { const [columns, setColumns] = useState(['Column 1']); const [rows, setRows] = useState(['Row 1']); const [grid, setGrid] = useState([['#ffffff']]); const [cellData, setCellData] = useState([['']]); const [showJsonModal, setShowJsonModal] = useState(false); const [showCellModal, setShowCellModal] = useState(false); const [selectedCell, setSelectedCell] = useState({ rowIdx: 0, colIdx: 0 }); const [cellJson, setCellJson] = useState(''); const handleColorChange = (rowIdx, colIdx, color) => { const newGrid = [...grid]; newGrid[rowIdx][colIdx] = color; setGrid(newGrid); }; const handleCellClick = (rowIdx, colIdx) => { setSelectedCell({ rowIdx, colIdx }); setCellJson(cellData[rowIdx][colIdx] || ''); setShowCellModal(true); }; const handleCellJsonChange = (event) => { setCellJson(event.target.value); }; const saveCellJson = () => { const newCellData = [...cellData]; newCellData[selectedCell.rowIdx][selectedCell.colIdx] = cellJson; setCellData(newCellData); setShowCellModal(false); }; const addColumn = () => { setColumns([...columns, `Column ${columns.length + 1}`]); setGrid(grid.map(row => [...row, '#ffffff'])); setCellData(cellData.map(row => [...row, ''])); }; const addRow = () => { setRows([...rows, `Row ${rows.length + 1}`]); setGrid([...grid, Array(columns.length).fill('#ffffff')]); setCellData([...cellData, Array(columns.length).fill('')]); }; const handleColumnTitleChange = (index, newTitle) => { const newColumns = [...columns]; newColumns[index] = newTitle; setColumns(newColumns); }; const handleRowTitleChange = (index, newTitle) => { const newRows = [...rows]; newRows[index] = newTitle; setRows(newRows); }; const exportJson = () => { const data = { columns, rows, grid, cellData, }; const jsonString = JSON.stringify(data, null, 2); const blob = new Blob([jsonString], { type: 'application/json' }); saveAs(blob, 'grid-data.json'); }; const importJson = (event) => { const file = event.target.files[0]; const reader = new FileReader(); reader.onload = (e) => { const data = JSON.parse(e.target.result); setColumns(data.columns); setRows(data.rows); setGrid(data.grid); setCellData(data.cellData); }; reader.readAsText(file); }; return ( <div className="p-4"> <div className="flex justify-between mb-4 text-[6px] border border-blue-400 rounded-lg shadow-xl"> <div className='flex items-center justify-start gap-2 p-2'> <button onClick={addColumn} className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"> Add Column </button> <button onClick={addRow} className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"> Add Row </button> <button onClick={() => setShowJsonModal(true)} className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"> Show JSON </button> <button onClick={exportJson} className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"> Export JSON </button> </div> <div className='flex items-center justify-start gap-2 p-2'> <input type="file" accept="application/json" onChange={importJson} className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700" /> </div> </div> <div className="overflow-auto max-w-full max-h-[500px] relative"> <div className="inline-block min-w-full align-middle"> <div className="shadow overflow-auto border-b border-gray-200 sm:rounded-lg"> <table className="min-w-full divide-y divide-gray-200"> <thead className="sticky top-0 "> <tr> <th className=" min-w-[100px] sticky left-0 z-10"></th> {columns.map((col, colIdx) => ( <th key={colIdx} className="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider min-w-[100px] border border-blue-400 max-w-[100px]"> <input type="text" value={col} onChange={(e) => handleColumnTitleChange(colIdx, e.target.value)} className="w-full border p-1 text-center" /> </th> ))} </tr> </thead> <tbody className="divide-y divide-gray-200"> {rows.map((row, rowIdx) => ( <tr key={rowIdx}> <td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 min-w-[100px] sticky left-0 border border-blue-400 max-w-[100px] "> <input type="text" value={row} onChange={(e) => handleRowTitleChange(rowIdx, e.target.value)} className="w-full border text-center" /> </td> {columns.map((col, colIdx) => ( <td key={colIdx} className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 text-center min-w-[100px] min-h-[50px] border border-blue-400 "> <div className="flex justify-center items-center space-x-2"> <input type="color" value={grid[rowIdx][colIdx]} onChange={(e) => handleColorChange(rowIdx, colIdx, e.target.value)} className="h-10 w-10 p-0 border-border-blue-400" /> <button onClick={() => handleCellClick(rowIdx, colIdx)} className="px-2 py-1 bg-gray-200 text-gray-700 rounded hover:bg-gray-300" > + </button> </div> </td> ))} </tr> ))} </tbody> </table> </div> </div> </div> {showJsonModal && ( <div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 max-h-screen py-4 text-black z-30"> <div className="bg-white p-4 rounded shadow-lg w-3/4"> <div className="flex justify-between items-center mb-4"> <h2 className="text-xl">Grid JSON</h2> <button onClick={() => setShowJsonModal(false)} className="px-4 py-2 bg-red-600 rounded hover:bg-red-700 text-white"> Close </button> </div> <pre className="border border-blue-400 max-h-[300px] p-4 rounded overflow-x-auto text-black"> {JSON.stringify({ columns, rows, grid, cellData }, null, 2)} </pre> </div> </div> )} {showCellModal && ( <div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-30"> <div className="bg-white p-4 rounded shadow-lg w-3/4 z-30"> <div className="flex justify-between items-center mb-4"> <h2 className="text-xl">Edit Cell JSON</h2> <button onClick={() => setShowCellModal(false)} className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"> Close </button> </div> <textarea value={cellJson} onChange={handleCellJsonChange} className="w-full h-64 p-2 border rounded" /> <button onClick={saveCellJson} className="mt-4 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"> Save JSON </button> </div> </div> )} </div> ); }; export default ColumnBuilder; // Usage example: // import React from 'react'; // import ReactDOM from 'react-dom'; // import ColumnBuilder from './ColumnBuilder'; // ReactDOM.render(<ColumnBuilder />, document.getElementById('root'));