13 KiB
Adding New Tools and Functionality Guide
This document provides a comprehensive guide for adding new tools and functionality to the Wastpol web application. It's designed to help developers (including AI agents) integrate new tools from separate projects into the main application.
Project Overview
The Wastpol application is a Next.js-based web application with the following key characteristics:
- Framework: Next.js 12 with React 17
- Styling: Tailwind CSS with custom UI components
- Authentication: NextAuth.js
- Architecture: Pages-based routing with component-driven design
- UI Library: Custom components + Evergreen UI + Heroicons
Project Structure
web-app/
├── pages/ # Next.js pages (routes)
│ ├── api/ # API endpoints
│ ├── index.js # Main dashboard with tabs
│ ├── cross.js # Grid tool
│ ├── uziomy.js # Ground connections tool
│ ├── tracking.js # Package tracking
│ └── [other-tools].js # Additional tools
├── components/
│ ├── ui/ # Reusable UI components
│ │ ├── Layout.js # Main layout with navigation
│ │ └── components.js # UI component library
│ └── templates/ # Tool-specific components
├── styles/ # Global styles
├── public/ # Static assets
└── externals/ # External data files
Adding a New Tool - Step by Step
1. Planning Phase
Before adding a new tool, define:
- Tool Purpose: What does the tool do?
- Tool Name: Short, descriptive name
- Route: URL path (e.g.,
/new-tool) - Icon: Choose from Heroicons
- Dependencies: Any new packages needed
- API Requirements: Backend processing needs
2. Tool Integration Checklist
A. Create the Main Page Component
Create a new file: pages/[tool-name].js
Template Structure:
import { useState, useCallback } from "react";
import { useSession, signIn } from "next-auth/react";
import Layout from "../components/ui/Layout";
import { Card, CardHeader, CardContent, CardTitle, CardDescription, Button, Alert } from "../components/ui/components";
import { [ToolIcon] } from '@heroicons/react/24/outline';
export default function NewTool() {
const { data: session } = useSession();
const [isLoading, setIsLoading] = useState(false);
// Tool-specific state variables
const [toolData, setToolData] = useState(null);
// Authentication check
if (!session) {
return (
<Layout title="Wastpol - New Tool">
<div className="flex items-center justify-center min-h-screen">
<Card className="w-full max-w-md">
<CardContent className="text-center p-6">
<h2 className="text-xl font-semibold mb-4">Wymagane logowanie</h2>
<Button onClick={() => signIn()}>
Zaloguj się
</Button>
</CardContent>
</Card>
</div>
</Layout>
);
}
return (
<Layout title="Wastpol - New Tool">
<div className="p-6 max-w-7xl mx-auto">
{/* Page Header */}
<div className="mb-8">
<h1 className="text-3xl font-bold text-gray-900 mb-2">
New Tool Name
</h1>
<p className="text-gray-600">
Tool description here
</p>
</div>
{/* Main Content */}
<Card>
<CardHeader>
<CardTitle className="flex items-center">
<[ToolIcon] className="w-6 h-6 mr-2" />
Tool Interface
</CardTitle>
<CardDescription>
Brief description of what this tool does
</CardDescription>
</CardHeader>
<CardContent>
{/* Tool-specific UI goes here */}
</CardContent>
</Card>
</div>
</Layout>
);
}
B. Add Navigation Entry
Update components/ui/Layout.js:
- Import the icon:
import {
// ...existing imports
[NewToolIcon]
} from '@heroicons/react/24/outline';
- Add to navigationItems array:
const navigationItems = [
// ...existing items
{ name: 'New Tool Name', href: '/new-tool', icon: NewToolIcon },
];
C. Create API Endpoint (if needed)
Create pages/api/[tool-name].js:
import formidable from 'formidable';
import { getSession } from 'next-auth/react';
export const config = {
api: {
bodyParser: false,
},
};
export default async function handler(req, res) {
// Authentication check
const session = await getSession({ req });
if (!session) {
return res.status(401).json({ error: 'Unauthorized' });
}
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
// Tool-specific processing logic
const form = new formidable.IncomingForm();
const [fields, files] = await form.parse(req);
// Process the request
const result = await processToolData(fields, files);
res.status(200).json({
success: true,
data: result
});
} catch (error) {
console.error('Tool processing error:', error);
res.status(500).json({
error: 'Internal server error',
details: error.message
});
}
}
async function processToolData(fields, files) {
// Implement tool-specific logic here
return {};
}
D. Add Tool-Specific Components (Optional)
Create reusable components in components/templates/[tool-name]/:
// components/templates/new-tool/ToolComponent.js
import { useState } from 'react';
import { Button, Alert } from '../../ui/components';
export default function ToolComponent({ onSubmit, isLoading }) {
const [inputData, setInputData] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
onSubmit(inputData);
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
{/* Tool-specific form elements */}
<Button
type="submit"
disabled={isLoading}
className="w-full"
>
{isLoading ? 'Processing...' : 'Submit'}
</Button>
</form>
);
}
3. Integration from Separate Project
A. Identify Components to Port
When integrating from a separate project:
- Identify core functionality files
- Extract reusable components
- Map dependencies and APIs
- Identify data processing logic
B. Dependency Management
- Check existing dependencies in
package.json - Add new dependencies if needed:
npm install [new-package]
- Update package.json if manual editing is needed
C. Asset Management
- Static files: Place in
public/directory - External data: Place in
externals/directory - Uploads: Use
public/uploads/for user uploads
4. Common Integration Patterns
File Upload Pattern
import { FileUploader, FileCard } from "evergreen-ui";
const [files, setFiles] = useState([]);
const handleChange = useCallback((files) => setFiles([files[0]]), []);
API Call Pattern
import axios from "axios";
const handleSubmit = async (data) => {
setIsLoading(true);
try {
const formData = new FormData();
formData.append("data", JSON.stringify(data));
const response = await axios.post("/api/new-tool", formData);
setResult(response.data);
} catch (error) {
setError(error.message);
} finally {
setIsLoading(false);
}
};
State Management Pattern
const [isLoading, setIsLoading] = useState(false);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
5. Styling Guidelines
Use Existing UI Components
import {
Card,
CardHeader,
CardContent,
CardTitle,
CardDescription,
Button,
Alert
} from "../components/ui/components";
Consistent Layout Classes
- Container:
p-6 max-w-7xl mx-auto - Page Header:
mb-8 - Title:
text-3xl font-bold text-gray-900 mb-2 - Description:
text-gray-600 - Cards: Use existing Card components
- Spacing:
space-y-4for form elements
6. Error Handling Best Practices
Client-Side Error Handling
const [error, setError] = useState(null);
// Clear error on new action
const clearError = () => setError(null);
// Display errors
{error && (
<Alert variant="destructive" className="mb-4">
{error}
</Alert>
)}
Server-Side Error Handling
try {
// Process request
} catch (error) {
console.error('Tool error:', error);
return res.status(500).json({
error: 'Processing failed',
details: process.env.NODE_ENV === 'development' ? error.message : undefined
});
}
7. Testing Integration
Manual Testing Checklist
- Tool loads without errors
- Authentication works correctly
- Navigation item appears and works
- File uploads work (if applicable)
- API endpoints respond correctly
- Results display properly
- Error handling works
- Mobile responsiveness
- Loading states display correctly
Console Testing
- Check browser console for errors
- Verify API responses in Network tab
- Test with different user roles
8. AI Agent Instructions
When an AI agent is adding a new tool:
Information to Gather
- Tool description and purpose
- Required input/output formats
- Processing logic requirements
- UI/UX preferences
- Integration points with existing system
Step-by-Step Process
- Analyze the existing project structure
- Identify the closest existing tool for reference
- Create the main page component
- Add navigation entry
- Create API endpoint if needed
- Test the integration
- Handle any errors or conflicts
Code Quality Standards
- Follow existing naming conventions
- Use consistent styling patterns
- Implement proper error handling
- Add loading states for async operations
- Ensure responsive design
- Maintain authentication requirements
9. Example Tool Addition
Here's how to add a hypothetical "Document Generator" tool:
Step 1: Create pages/document-generator.js
import { useState } from "react";
import { useSession, signIn } from "next-auth/react";
import Layout from "../components/ui/Layout";
import { Card, CardHeader, CardContent, CardTitle } from "../components/ui/components";
import { DocumentTextIcon } from '@heroicons/react/24/outline';
export default function DocumentGenerator() {
const { data: session } = useSession();
// Component implementation...
}
Step 2: Update components/ui/Layout.js
import { DocumentTextIcon } from '@heroicons/react/24/outline';
const navigationItems = [
// ...existing items
{ name: 'Generator dokumentów', href: '/document-generator', icon: DocumentTextIcon },
];
Step 3: Create pages/api/document-generator.js
export default async function handler(req, res) {
// API implementation...
}
10. Maintenance and Updates
Version Control
- Commit changes with descriptive messages
- Tag releases for major tool additions
- Document breaking changes
Documentation Updates
- Update this guide when patterns change
- Document new dependencies
- Keep API documentation current
Performance Considerations
- Monitor bundle size with new dependencies
- Optimize images and assets
- Consider lazy loading for heavy components
Quick Reference Commands
# Install new dependency
npm install [package-name]
# Run development server
npm run dev
# Build for production
npm run build
# Deploy changes
npm run deploy
Common File Locations
- New page:
pages/[tool-name].js - API endpoint:
pages/api/[tool-name].js - Components:
components/templates/[tool-name]/ - Navigation:
components/ui/Layout.js - Styles:
styles/globals.css - Assets:
public/
This guide should provide everything needed to successfully integrate new tools into the Wastpol application while maintaining consistency and code quality.