Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/app/notes/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use client";

import { FunctionComponent, useState } from 'react';
import Sidebar from '@/components/Sidebar';
import NoteList from '@/components/NoteList';
import NoteModal from '@/components/NoteModal';
import { Button } from '@/components/Button';

interface NotePageProps {}

const notesInitial = [
{ title: 'Magnetism', date: '12/10/23' },
{ title: 'Electricity', date: '11/20/23' }
];

const NotePage: FunctionComponent<NotePageProps> = () => {
const [notes, setNotes] = useState(notesInitial);
const [isModalOpen, setIsModalOpen] = useState(false);

const handleNewNote = (title: string, content: string) => {
// This example does not handle the content, only the title and date is used
const newNote = { title, date: new Date().toLocaleDateString('en-US') };
setNotes([...notes, newNote]);
};

return (
<div className="flex h-screen">
<Sidebar />
<div className="flex-1 p-10 text-2xl font-bold">
<div className="flex justify-between">
<h1 className="text-4xl">Notes</h1>
<Button onClick={() => setIsModalOpen(true)}>
Add Note
</Button>
</div>
<NoteList notes={notes} />
</div>
<NoteModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
onSave={handleNewNote}
/>
</div>
);
};

export default NotePage;
7 changes: 7 additions & 0 deletions src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use client";

import { Button as UIButton } from '@/components/ui/button';

// This component is just re-exporting the existing Button from UI library
// to make it easier to import in our Note application.
export { UIButton as Button };
21 changes: 21 additions & 0 deletions src/components/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"use client";

import {
Card as UICard,
CardHeader as UICardHeader,
CardFooter as UICardFooter,
CardTitle as UICardTitle,
CardDescription as UICardDescription,
CardContent as UICardContent
} from '@/components/ui/card';

// These components are just re-exporting the existing Card components from UI library
// to make it easier to import in our Note application.
export {
UICard as Card,
UICardHeader as CardHeader,
UICardFooter as CardFooter,
UICardTitle as CardTitle,
UICardDescription as CardDescription,
UICardContent as CardContent
};
7 changes: 7 additions & 0 deletions src/components/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use client";

import { Input as UIInput } from '@/components/ui/input';

// This component is just re-exporting the existing Input from UI library
// to make it easier to import in our Note application.
export { UIInput as Input };
7 changes: 7 additions & 0 deletions src/components/Label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use client";

import { Label as UILabel } from '@/components/ui/label';

// This component is just re-exporting the existing Label from UI library
// to make it easier to import in our Note application.
export { UILabel as Label };
20 changes: 20 additions & 0 deletions src/components/NoteCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use client";

import { FunctionComponent } from 'react';

interface NoteCardProps {
title: string;
date: string;
onClick?: () => void;
}

const NoteCard: FunctionComponent<NoteCardProps> = ({ title, date, onClick }) => {
return (
<div className="note-entry p-4 flex justify-between items-center bg-white shadow-md rounded-lg mb-2" onClick={onClick}>
<div>{title}</div>
<div>{date}</div>
</div>
);
};

export default NoteCard;
26 changes: 26 additions & 0 deletions src/components/NoteList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"use client";

import { FunctionComponent } from 'react';
import NoteCard from '@/components/NoteCard';

interface NoteListProps {
notes: Array<{ title: string; date: string; }>; // Define a type for note objects
onNoteClick?: (note: { title: string; date: string; }) => void;
}

const NoteList: FunctionComponent<NoteListProps> = ({ notes, onNoteClick }) => {
return (
<div className="mt-8">
{notes.map((note, index) => (
<NoteCard
key={index}
title={note.title}
date={note.date}
onClick={() => onNoteClick && onNoteClick(note)}
/>
))}
</div>
);
};

export default NoteList;
48 changes: 48 additions & 0 deletions src/components/NoteModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"use client";

import { FunctionComponent, useState } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';

interface NoteModalProps {
isOpen: boolean;
onClose: () => void;
onSave: (title: string, content: string) => void;
}

const NoteModal: FunctionComponent<NoteModalProps> = ({ isOpen, onClose, onSave }) => {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSave(title, content);
setTitle('');
setContent('');
onClose();
};

return (
<div className={`modal ${isOpen ? 'block' : 'hidden'}`}>
<div className="modal-content">
<span className="close" onClick={onClose}>&times;</span>
<form onSubmit={handleSubmit}>
<div className="mb-4">
<Label htmlFor="noteTitle">Title:</Label>
<Input id="noteTitle" name="noteTitle" value={title} onChange={(e) => setTitle(e.target.value)} required />
</div>
<div className="mb-6">
<Label htmlFor="noteContent">Content:</Label>
<textarea id="noteContent" name="noteContent" rows={4} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline" value={content} onChange={(e) => setContent(e.target.value)} required></textarea>
</div>
<div className="flex items-center justify-between">
<Button type="submit">Save Note</Button>
</div>
</form>
</div>
</div>
);
};

export default NoteModal;
51 changes: 51 additions & 0 deletions src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use client";

import { FunctionComponent } from 'react';
import Link from 'next/link';

interface SidebarProps {}

const Sidebar: FunctionComponent<SidebarProps> = () => {
return (
<div className="w-64 bg-white p-5">
<div className="flex items-center space-x-4 p-2 mb-5">
<div className="rounded-full h-12 w-12 flex items-center justify-center border-2 border-gray-300">O</div>
<div>Graham Liu</div>
</div>
<ul className="space-y-2 text-sm">
<li>
<Link href="#">
<a className="flex items-center space-x-3 text-gray-700 p-2 rounded-md font-medium hover:bg-gray-200 focus:shadow-outline">
<span className="text-gray-600">
{/* SVG icon placeholder */}
</span>
<span>Home</span>
</a>
</Link>
</li>
<li>
<Link href="#">
<a className="flex items-center space-x-3 text-gray-700 p-2 rounded-md font-medium hover:bg-gray-200 focus:shadow-outline">
<span className="text-gray-600">
{/* SVG icon placeholder */}
</span>
<span>Physics</span>
</a>
</Link>
</li>
<li>
<Link href="#">
<a className="flex items-center space-x-3 text-gray-700 p-2 rounded-md font-medium hover:bg-gray-200 focus:shadow-outline">
<span className="text-gray-600">
{/* SVG icon placeholder */}
</span>
<span>Chemistry</span>
</a>
</Link>
</li>
</ul>
</div>
);
};

export default Sidebar;