Skip to content

Commit

Permalink
0.0.4a
Browse files Browse the repository at this point in the history
- add dummy UI for idea
- break page components into smaller
  • Loading branch information
tanghoong committed Sep 13, 2024
1 parent bbbbcf0 commit df4cc90
Show file tree
Hide file tree
Showing 6 changed files with 345 additions and 134 deletions.
68 changes: 68 additions & 0 deletions src/app/components/BoardLists.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import Accordion from '@/components/Accordion';
import BoardList from '@/components/BoardList';
import { Board } from '@/types';

interface BoardListsProps {
isLoading: boolean;
error: Error | null;
pinnedBoards: Board[];
allBoards: Board[];
expandedSection: string | null;
onToggleSection: (section: string) => void;
onMoveBoard: (dragIndex: number, hoverIndex: number) => void;
onEditBoard: (board: Board) => void;
onViewBoard: (boardId: string) => void;
onDeleteBoard: (boardId: string) => void;
onPinBoard: (boardId: string) => void;
}

const BoardLists: React.FC<BoardListsProps> = ({
isLoading,
error,
pinnedBoards,
allBoards,
expandedSection,
onToggleSection,
onMoveBoard,
onEditBoard,
onViewBoard,
onDeleteBoard,
onPinBoard
}) => {
if (isLoading) return <p className="text-solarized-base1">Loading boards...</p>;
if (error) return <p className="text-solarized-red">Error loading boards: {error instanceof Error ? error.message : 'Unknown error'}</p>;

return (
<>
<Accordion
title="Pinned Boards"
isExpanded={expandedSection === 'pinned'}
onToggle={() => onToggleSection('pinned')}
>
<BoardList
boards={pinnedBoards}
onMoveBoard={onMoveBoard}
onEditBoard={onEditBoard}
onViewBoard={onViewBoard}
onDeleteBoard={onDeleteBoard}
onPinBoard={onPinBoard} title={''} />
</Accordion>
<Accordion
title="All Boards"
isExpanded={expandedSection === 'all'}
onToggle={() => onToggleSection('all')}
>
<BoardList
boards={allBoards}
onMoveBoard={onMoveBoard}
onEditBoard={onEditBoard}
onViewBoard={onViewBoard}
onDeleteBoard={onDeleteBoard}
onPinBoard={onPinBoard} title={''} />
</Accordion>
</>
);
};

export default BoardLists;
77 changes: 77 additions & 0 deletions src/app/components/GetThingsDone.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from 'react';
import { Trophy, Target, TrendingUp, Activity } from 'lucide-react';

interface GetThingsDoneProps {
gamifyData: {
tasksCompleted: number;
streakDays: number;
productivityScore: number;
productivityTrend: number[];
};
}

const GetThingsDone: React.FC<GetThingsDoneProps> = ({ gamifyData }) => {
const generateChartPoints = (data: number[], width: number, height: number) => {
const linePoints = data.map((value, index) => {
const x = (index / (data.length - 1)) * width;
const y = height - (value / 100) * height;
return `${x},${y}`;
}).join(' ');

const curvedLinePoints = `M${linePoints}`;
const areaPoints = `${curvedLinePoints} L ${width},${height} L 0,${height} Z`;

return { curvedLinePoints, areaPoints };
};

return (
<div className="bg-solarized-base02 rounded-lg p-4 mb-8 relative overflow-hidden">
<svg className="absolute inset-0 w-full h-full" viewBox="0 0 300 150" preserveAspectRatio="none">
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stopColor="rgba(38, 139, 210, 0.1)" />
<stop offset="100%" stopColor="rgba(38, 139, 210, 0)" />
</linearGradient>
</defs>
<path
d={generateChartPoints(gamifyData.productivityTrend, 300, 150).areaPoints}
fill="url(#gradient)"
/>
<path
d={generateChartPoints(gamifyData.productivityTrend, 300, 150).curvedLinePoints}
fill="none"
stroke="#268bd2"
strokeWidth="1"
opacity="0.5"
/>
</svg>
<div className="relative z-10">
<div className="flex justify-between items-center mb-2">
<h2 className="text-xl font-bold text-solarized-base1">Get Things Done</h2>
<div className="flex space-x-2">
<Trophy size={16} className="text-solarized-yellow" />
<Target size={16} className="text-solarized-magenta" />
<TrendingUp size={16} className="text-solarized-green" />
<Activity size={16} className="text-solarized-cyan" />
</div>
</div>
<div className="grid grid-cols-3 gap-2 text-center">
<div className="bg-solarized-base03 p-2 rounded">
<p className="text-sm text-solarized-base1">Tasks</p>
<p className="text-lg font-bold text-solarized-cyan">{gamifyData.tasksCompleted}</p>
</div>
<div className="bg-solarized-base03 p-2 rounded">
<p className="text-sm text-solarized-base1">Streak</p>
<p className="text-lg font-bold text-solarized-yellow">{gamifyData.streakDays}</p>
</div>
<div className="bg-solarized-base03 p-2 rounded">
<p className="text-sm text-solarized-base1">Score</p>
<p className="text-lg font-bold text-solarized-green">{gamifyData.productivityScore}</p>
</div>
</div>
</div>
</div>
);
};

export default GetThingsDone;
31 changes: 31 additions & 0 deletions src/app/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import { Plus, PanelRight } from 'lucide-react';
import ResetDatabaseButton from '@/components/ResetDatabaseButton';

interface HeaderProps {
onNewBoard: () => void;
onToggleAgenda: () => void;
}

const Header: React.FC<HeaderProps> = ({ onNewBoard, onToggleAgenda }) => (
<div className="flex justify-between items-center mb-8">
<h1 className="text-3xl font-bold text-solarized-cyan">Welcome, Charlie</h1>
<div className="flex items-center space-x-4">
<ResetDatabaseButton />
<button
onClick={onNewBoard}
className="bg-solarized-blue text-solarized-base3 hover:bg-opacity-80 transition-colors p-1 rounded-full"
>
<Plus size={16} />
</button>
<button
onClick={onToggleAgenda}
className="text-solarized-base1 hover:text-solarized-base0 p-2 rounded-full hover:bg-solarized-base02"
>
<PanelRight size={24} />
</button>
</div>
</div>
);

export default Header;
32 changes: 32 additions & 0 deletions src/app/components/RecentActivities.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { Activity } from 'lucide-react';

interface RecentActivitiesProps {
activities: Array<{
id: string;
type: string;
description: string;
timestamp: string;
}>;
}

const RecentActivities: React.FC<RecentActivitiesProps> = ({ activities }) => {
return (
<div className="bg-solarized-base02 rounded-lg p-3 mb-4">
<h2 className="text-lg font-semibold text-solarized-blue mb-2 flex items-center">
<Activity size={18} className="mr-2" />
Recent Activities
</h2>
<ul className="text-sm">
{activities.map((activity) => (
<li key={activity.id} className="flex justify-between items-center py-1 border-b border-solarized-base01 last:border-b-0">
<span className="text-solarized-base1">{activity.description}</span>
<span className="text-solarized-base01 text-xs">{activity.timestamp}</span>
</li>
))}
</ul>
</div>
);
};

export default RecentActivities;
76 changes: 76 additions & 0 deletions src/app/components/TemplateSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState, useMemo } from 'react';
import Accordion from '@/components/Accordion';
import TemplateList from '@/components/TemplateList';
import { Search } from 'lucide-react';

interface TemplateSectionProps {
expandedSection: string | null;
onToggleSection: (section: string) => void;
boardTemplates: Array<{
name: string;
type: string;
description: string;
lists: string[];
}>;
onSelectTemplate: (template: any) => void;
}

const TemplateSection: React.FC<TemplateSectionProps> = ({
expandedSection,
onToggleSection,
boardTemplates,
onSelectTemplate
}) => {
const [searchTerm, setSearchTerm] = useState('');
const [activeTag, setActiveTag] = useState('all');

const filteredTemplates = useMemo(() => {
return boardTemplates.filter(template =>
(activeTag === 'all' || template.type === activeTag) &&
(template.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
template.type.toLowerCase().includes(searchTerm.toLowerCase()))
);
}, [searchTerm, activeTag, boardTemplates]);

const tags = ['all', ...Array.from(new Set(boardTemplates.map(template => template.type)))];

return (
<Accordion
title="Board Templates"
isExpanded={expandedSection === 'templates'}
onToggle={() => onToggleSection('templates')}
>
<div className="p-4">
<div className="relative mb-4">
<input
type="text"
placeholder="Search templates..."
className="w-full px-4 py-2 border rounded-md pl-10"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" size={20} />
</div>
<div className="flex flex-wrap gap-2 mb-4">
{tags.map(tag => (
<button
key={tag}
className={`px-3 py-1 rounded-full text-sm ${
activeTag === tag ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-700'
}`}
onClick={() => setActiveTag(tag)}
>
{tag}
</button>
))}
</div>
<TemplateList
templates={filteredTemplates}
onSelectTemplate={onSelectTemplate}
/>
</div>
</Accordion>
);
};

export default TemplateSection;
Loading

0 comments on commit df4cc90

Please sign in to comment.