Implementing Calculators and Checklist Features with a Clean Sidebar
TL;DR: I added calculator and checklist tools to the Riviera Industrial ERP, along with a cleaned-up sidebar. This involved updating several components, adding new files, and configuring environment variables.
The Problem
The Riviera Industrial ERP needed additional tools to enhance user productivity. Specifically, we required engineering calculators and a diagnostic checklist. The sidebar also needed a redesign for better navigation.
What I Tried First
Initially, I attempted to integrate the calculator and checklist features into existing components. However, this approach led to code clutter and made maintenance more difficult. I realized that creating separate components for each tool would be a better approach.
The Implementation
Environment Variables
I started by updating the .env file to include a ClickUp API key:
# .env
SUPABASE_BUCKET="riviera-docs"
# Test helpers
DISABLE_RATE_LIMIT=true
# ClickUp
CLICKUP_API_KEY=pk_204263176_CAJOXIE5XPFY5D5TYMXTQKQMZH0EGC5K
This change allows us to use the ClickUp API for future integrations.
Calculator Component
Next, I created a new component for the calculator feature in src/components/shared/CalculatorApp.tsx:
// src/components/shared/CalculatorApp.tsx
"use client";
import { useState } from "react";
// ── Tipos ──────────────────────────────────────────────────────────────────────
type CalcId = "tolerancias" | "ajustes" | "velocidad";
const calculators: Record<CalcId, (inputs: any) => number> = {
tolerancias: (inputs) => inputs.length * 0.01,
ajustes: (inputs) => inputs.width * inputs.height,
velocidad: (inputs) => inputs.distance / inputs.time,
};
const CalculatorApp = () => {
const [calcId, setCalcId] = useState<CalcId>("tolerancias");
const [inputs, setInputs] = useState({ length: 0 });
const handleCalcChange = (id: CalcId) => {
setCalcId(id);
};
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputs({ ...inputs, [e.target.name]: e.target.value });
};
const result = calculators[calcId](inputs);
return (
<div>
<select value={calcId} onChange={(e) => handleCalcChange(e.target.value as CalcId)}>
{Object.keys(calculators).map((id) => (
<option key={id} value={id}>
{id}
</option>
))}
</select>
<input type="number" name="length" value={inputs.length} onChange={handleInputChange} />
<p>Result: {result}</p>
</div>
);
};
export default CalculatorApp;
This component allows users to select a calculator type and input values to get a result.
Checklist Component
Similarly, I created a new component for the checklist feature in src/components/shared/ChecklistApp.tsx:
// src/components/shared/ChecklistApp.tsx
"use client";
import { useState } from "react";
type CheckItem = { id: string; label: string; required?: boolean };
type Section = { id: string; icon: string; title: string; items: CheckItem[] };
const checklist: Section[] = [
{
id: "section1",
icon: "📝",
title: "Section 1",
items: [
{ id: "item1", label: "Item 1", required: true },
{ id: "item2", label: "Item 2" },
],
},
];
const ChecklistApp = () => {
const [checkedItems, setCheckedItems] = useState<Record<string, boolean>>({});
const handleCheckChange = (itemId: string) => {
setCheckedItems((prev) => ({ ...prev, [itemId]: !prev[itemId] }));
};
return (
<div>
{checklist.map((section) => (
<div key={section.id}>
<h2>{section.title}</h2>
<ul>
{section.items.map((item) => (
<li key={item.id}>
<input
type="checkbox"
checked={checkedItems[item.id] || false}
onChange={() => handleCheckChange(item.id)}
/>
<span>{item.label}</span>
</li>
))}
</ul>
</div>
))}
</div>
);
};
export default ChecklistApp;
This component displays a checklist with sections and items, allowing users to check and uncheck items.
Sidebar Updates
I updated the Sidebar.tsx component to include links to the new calculator and checklist features:
// src/components/layout/Sidebar.tsx
const NAV_ALL = [
// ...
{ section: "Herramientas", items: [
{ href: "/tools/calculators", icon: "📊", label: "Calculadoras" },
{ href: "/tools/checklist", icon: "📝", label: "Checklist" },
]},
];
Page Updates
Finally, I updated the page.tsx files for the calculator and checklist features:
// src/app/tools/calculators/page.tsx
import { PageHeader } from "@/components/shared/PageHeader";
import CalculatorApp from "@/components/shared/CalculatorApp";
export default function CalculatorsPage() {
return (
<div>
<PageHeader title="Calculadoras" />
<CalculatorApp />
</div>
);
}
// src/app/tools/checklist/page.tsx
import { PageHeader } from "@/components/shared/PageHeader";
import ChecklistApp from "@/components/shared/ChecklistApp";
export default function ChecklistPage() {
return (
<div>
<PageHeader title="Checklist" />
<ChecklistApp />
</div>
);
}
Key Takeaway
The key takeaway from this implementation is the importance of breaking down complex features into separate, reusable components. This approach makes maintenance and updates easier, allowing for a more scalable and efficient development process.
What's Next
Next, I plan to integrate the ClickUp API to enhance the checklist feature with task management capabilities. This will involve updating the ChecklistApp component to use the ClickUp API for creating and managing tasks.
Part of my Build in Public series — sharing the real process of building Building Riviera Industrial ERP from Playa del Carmen, México.
Repo: zaerohell/riviera-industrial-erp · 2026-07-06
#playadev #buildinpublic
Top comments (0)