mirror of
https://github.com/cssgunc/compass.git
synced 2025-04-06 20:50:17 -04:00
added multiple input functionality
This commit is contained in:
parent
3331c1943d
commit
85d99a0a96
|
@ -1,5 +1,7 @@
|
|||
// pages/index.tsx
|
||||
"use client";
|
||||
import Image from 'next/image';
|
||||
|
||||
|
||||
|
||||
import Drawer from '@/components/page/Drawer';
|
||||
|
@ -18,9 +20,21 @@ export default function Page() {
|
|||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className="text-2xl font-bold text-gray-700 sm:text-3xl">Resources</h1>
|
||||
<Drawer title="My Drawer Title" editableContent={pageContent} onSave={handleDrawerContentChange}>{pageContent}</Drawer>
|
||||
</>
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<div className="pt-16 px-8 pb-4 flex-grow">
|
||||
<div className="mb-4 flex items-center space-x-4">
|
||||
<Image
|
||||
src="/logo.png" // Ensure the path to your logo is correct
|
||||
alt="Compass Center logo"
|
||||
width={25}
|
||||
height={25}
|
||||
// If you are using TypeScript and Next.js Image component, ensure you have set up 'next/image' in your 'next.config.js' for static import
|
||||
/>
|
||||
<h1 className="font-bold text-2xl text-purple-800">Untitled Page</h1>
|
||||
</div>
|
||||
<Drawer title="Sidebar Component" editableContent={pageContent} onSave={handleDrawerContentChange}>{pageContent}</Drawer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
29
compass/components/page/Card.tsx
Normal file
29
compass/components/page/Card.tsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
import React, { ReactNode, useState } from "react";
|
||||
|
||||
|
||||
interface TagProps {
|
||||
text: string;
|
||||
icon: React.ReactNode;
|
||||
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
|
||||
const Card: React.FC<TagProps> = ({children, text, icon, onClick }) => {
|
||||
return (
|
||||
<button
|
||||
onClick={onClick}
|
||||
className="flex flex-row space-x-2 items-start justify-start border border-gray-200 bg-white hover:bg-gray-50 shadow rounded-md p-4 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-opacity-50 w-1/4"
|
||||
>
|
||||
<span className="h-5 text-purple-700 w-5">
|
||||
{icon}
|
||||
</span>
|
||||
<span className="text-sm text-gray-800 font-semibold">
|
||||
{text}
|
||||
</span>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default Card;
|
|
@ -1,8 +1,10 @@
|
|||
import { FunctionComponent, ReactNode } from 'react';
|
||||
import { FunctionComponent, ReactElement, ReactNode } from 'react';
|
||||
import Button from '@/components/Button'
|
||||
import React, { useState } from 'react';
|
||||
import {DATATYPE} from '@/utils/constants'
|
||||
import InlineLink from '@/components/InlineLink'
|
||||
import { ChevronDoubleLeftIcon } from '@heroicons/react/24/solid';
|
||||
import { BookmarkIcon, XMarkIcon } from "@heroicons/react/24/solid";
|
||||
import Card from '@/components/page/Card'
|
||||
|
||||
|
||||
|
||||
type DrawerProps = {
|
||||
|
@ -15,62 +17,134 @@ type DrawerProps = {
|
|||
onSave?: (content: any) => void;
|
||||
};
|
||||
|
||||
interface EditContent {
|
||||
content: string;
|
||||
isEditing: boolean;
|
||||
}
|
||||
|
||||
|
||||
const Drawer: FunctionComponent<DrawerProps> = ({ title, children, onSave, editableContent }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [editContent, setEditContent] = useState(editableContent || '');
|
||||
const [editContents, setEditContents] = useState<EditContent[]>(editableContent || [{ content: '', isEditing: true }]);
|
||||
const [currentCardText, setCurrentCardText] = useState("");
|
||||
const [currentCardIcon, setCurrentCardIcon] = useState<string>('');
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
|
||||
const toggleDrawer = () => setIsOpen(!isOpen);
|
||||
const toggleEditing = () => setIsEditing(!isEditing);
|
||||
const handleContentChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setEditContent(event.target.value);
|
||||
};
|
||||
|
||||
const handleCardClick = (text: string, icon: ReactElement) => {
|
||||
console.log('click')
|
||||
toggleDrawer();
|
||||
setCurrentCardText(text);
|
||||
setCurrentCardIcon(icon)};
|
||||
|
||||
const toggleEditing = () => setIsEditing(!isEditing);
|
||||
const handleInputChange = (index: number) => (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const newContents = editContents.map((item, idx) => idx === index ? { ...item, content: event.target.value } : item);
|
||||
setEditContents(newContents);
|
||||
};
|
||||
const drawerClassName = `fixed top-0 right-0 w-1/2 h-full bg-white shadow-xl transform ease-in-out duration-300 ${
|
||||
isOpen ? "translate-x-0" : "translate-x-full"
|
||||
}`;
|
||||
|
||||
const addInput = () => {
|
||||
setEditContents([...editContents, { content: '', isEditing: true }]);
|
||||
};
|
||||
|
||||
const saveChanges = () => {
|
||||
console.log(editContent);
|
||||
if (onSave) {
|
||||
onSave(editContent);
|
||||
const saveIndividualChange = (index: number) => {
|
||||
const content = editContents[index].content.trim();
|
||||
if (!content) {
|
||||
setError("Input cannot be empty.");
|
||||
return;
|
||||
}
|
||||
setIsEditing(false);
|
||||
|
||||
setError(null); // Clear error state if input passes validation
|
||||
|
||||
const updatedContents = editContents.map((item, idx) => idx === index ? { ...item, isEditing: false } : item);
|
||||
setEditContents(updatedContents);
|
||||
|
||||
if (onSave) {
|
||||
onSave(updatedContents);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleEdit = (index: number) => {
|
||||
const newContents = editContents.map((item, idx) => idx === index ? { ...item, isEditing: !item.isEditing } : item);
|
||||
setEditContents(newContents);
|
||||
};
|
||||
|
||||
const deleteInput = (index: number) => {
|
||||
// Filter out the input at the given index
|
||||
const filteredContents = editContents.filter((_, idx) => idx !== index);
|
||||
setEditContents(filteredContents);
|
||||
};
|
||||
|
||||
const addRow = () => {
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button onClick={toggleDrawer}>{isOpen ? "Close" : "Open"} Drawer</Button>
|
||||
<Card icon={<BookmarkIcon />} text="Resources" onClick={() => handleCardClick("Resources", <BookmarkIcon />)}/>
|
||||
<div className={drawerClassName}>
|
||||
<div className="flex items-center justify-between p-4 border-b">
|
||||
<h2>{title}</h2>
|
||||
<div className="flex items-center justify-between p-4 border-b">
|
||||
<span className="h-5 text-purple-700 w-5">
|
||||
{currentCardIcon}
|
||||
</span>
|
||||
<h2>{currentCardText}</h2>
|
||||
<div>
|
||||
<Button onClick={toggleEditing}>{isEditing ? 'Cancel' : 'Edit'}</Button>
|
||||
<Button onClick={toggleDrawer}>«</Button>
|
||||
<button
|
||||
onClick={toggleDrawer} className="py-2 text-gray-500 hover:text-gray-800"
|
||||
>
|
||||
<ChevronDoubleLeftIcon className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
{isEditing ? (
|
||||
<>
|
||||
<input
|
||||
type= 'text'
|
||||
value={editContent}
|
||||
onChange={handleContentChange}
|
||||
className="border p-2 w-full"
|
||||
/>
|
||||
<InlineLink onClick={saveChanges}>Save</InlineLink>
|
||||
</>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</div>
|
||||
{
|
||||
editContents.map((item, index) => (
|
||||
<div key={index} className="flex mb-2 items-center space-x-2">
|
||||
{item.isEditing ? (
|
||||
<>
|
||||
<input
|
||||
type="text"
|
||||
value={item.content}
|
||||
onChange={handleInputChange(index)}
|
||||
className="border p-2 w-full"
|
||||
/>
|
||||
<button
|
||||
onClick={() => saveIndividualChange(index)}
|
||||
className="py-2 px-4 bg-blue-500 text-white rounded"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="p-2 w-full">{item.content}</span>
|
||||
<button
|
||||
onClick={() => toggleEdit(index)}
|
||||
className="py-2 px-4 bg-green-500 text-white rounded"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{/* Delete button moved here, outside of the editing conditional */}
|
||||
<button
|
||||
onClick={() => deleteInput(index)}
|
||||
className="py-2 text-gray-500 hover:text-gray-800"
|
||||
>
|
||||
<XMarkIcon className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
<button onClick={addInput} className="py-2 px-4 bg-blue-500 text-white rounded my-2">Add New Input</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Drawer;
|
||||
export default Drawer;
|
||||
|
||||
|
|
30
compass/components/page/DropDown.tsx
Normal file
30
compass/components/page/DropDown.tsx
Normal file
|
@ -0,0 +1,30 @@
|
|||
import React, { ChangeEvent, FunctionComponent } from 'react';
|
||||
|
||||
// Define the shape of a single option
|
||||
interface DropdownOption {
|
||||
label: string;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
// Define the props for the Dropdown component
|
||||
interface DropdownProps {
|
||||
options: DropdownOption[];
|
||||
onChange: (event: ChangeEvent<HTMLSelectElement>) => void; // Type for change event on <select>
|
||||
defaultValue?: string | number;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
// Dropdown Component
|
||||
const Dropdown: FunctionComponent<DropdownProps> = ({ options, onChange, defaultValue, id }) => {
|
||||
return (
|
||||
<select id={id} defaultValue={defaultValue} onChange={onChange} className="form-select form-select-lg mb-3">
|
||||
{options.map((option, index) => (
|
||||
<option key={index} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
);
|
||||
};
|
||||
|
||||
export default Dropdown;
|
|
@ -1,4 +0,0 @@
|
|||
// components/Field.tsx
|
||||
import { FunctionComponent, ReactNode } from 'react';
|
||||
import Button from '@/components/Button'
|
||||
import React, { useState } from 'react';
|
Loading…
Reference in New Issue
Block a user