feat: implement US-1 - add print button to MonthCard with i18n support
- Add PrintButton component with card styling matching AddLocationButton - Integrate print button next to "Add a new realestate" with centered layout - Add English/Croatian translations for print tooltips and labels - Implement click handler to open print preview in new tab - Create Sprint Playbook for barcode print functionality 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import { AddMonthButton } from "./AddMonthButton";
|
|||||||
import { MonthCard } from "./MonthCard";
|
import { MonthCard } from "./MonthCard";
|
||||||
import Pagination from "./Pagination";
|
import Pagination from "./Pagination";
|
||||||
import { LocationCard } from "./LocationCard";
|
import { LocationCard } from "./LocationCard";
|
||||||
|
import { PrintButton } from "./PrintButton";
|
||||||
import { BillingLocation, YearMonth } from "../lib/db-types";
|
import { BillingLocation, YearMonth } from "../lib/db-types";
|
||||||
import { useRouter, useSearchParams } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
import { ToastContainer } from 'react-toastify';
|
import { ToastContainer } from 'react-toastify';
|
||||||
@@ -83,7 +84,10 @@ export const MonthLocationList:React.FC<MonthLocationListProps > = ({
|
|||||||
locations.map((location, ix) => <LocationCard key={`location-${location._id}`} location={location} />)
|
locations.map((location, ix) => <LocationCard key={`location-${location._id}`} location={location} />)
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
<div className="flex gap-2 justify-center">
|
||||||
<AddLocationButton yearMonth={yearMonth} />
|
<AddLocationButton yearMonth={yearMonth} />
|
||||||
|
<PrintButton yearMonth={yearMonth} />
|
||||||
|
</div>
|
||||||
</MonthCard>
|
</MonthCard>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
32
app/ui/PrintButton.tsx
Normal file
32
app/ui/PrintButton.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { PrinterIcon } from '@heroicons/react/24/outline';
|
||||||
|
import { useTranslations } from 'next-intl';
|
||||||
|
import { YearMonth } from '../lib/db-types';
|
||||||
|
|
||||||
|
export interface PrintButtonProps {
|
||||||
|
yearMonth: YearMonth;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PrintButton: React.FC<PrintButtonProps> = ({ yearMonth }) => {
|
||||||
|
const t = useTranslations("home-page.month-card");
|
||||||
|
|
||||||
|
const handlePrintClick = () => {
|
||||||
|
window.open(`/print/${yearMonth.year}/${yearMonth.month}`, '_blank');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="card card-compact card-bordered bg-base-100 shadow-s my-1">
|
||||||
|
<button
|
||||||
|
className="card-body tooltip self-center cursor-pointer"
|
||||||
|
onClick={handlePrintClick}
|
||||||
|
data-tip={t("print-codes-tooltip")}
|
||||||
|
>
|
||||||
|
<span className='flex self-center mr-[-3em]'>
|
||||||
|
<PrinterIcon className="h-[1em] w-[1em] cursor-pointer text-4xl" />
|
||||||
|
<span className="ml-1 mt-[.4em] text-xs text-left leading-[1.2em] w-[6em]">{t("print-codes-label")}</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
196
docs/sprints/sprint-01-barcode-print.md
Normal file
196
docs/sprints/sprint-01-barcode-print.md
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
# 📑 Sprint Playbook: Barcode Print Support
|
||||||
|
|
||||||
|
## 0. Sprint Status
|
||||||
|
|
||||||
|
```
|
||||||
|
Status: 🔲 not started
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Sprint Metadata
|
||||||
|
|
||||||
|
* **Sprint ID:** 01
|
||||||
|
* **Start Date:** 2025-01-14
|
||||||
|
* **End Date:** 2025-01-16
|
||||||
|
* **Sprint Goal:** Add capability to print a table containing all 2D barcode images for a given month
|
||||||
|
* **Team/Agent Responsible:** AI-Agent (Claude Sonnet 4)
|
||||||
|
* **Branch Name (Git):** feature/sprint-01
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Current State of Software
|
||||||
|
|
||||||
|
*(Snapshot of the project before Sprint work begins)*
|
||||||
|
|
||||||
|
* **Main Features Available:**
|
||||||
|
- Multi-user utility bills tracking system
|
||||||
|
- Monthly billing periods with expandable MonthCard UI components
|
||||||
|
- Location and bill management with CRUD operations
|
||||||
|
- 2D barcode scanning and storage (bills already have `barcodeImage` field)
|
||||||
|
- PDF processing capabilities with `@zxing/library` and `pdfjs-dist`
|
||||||
|
- Internationalization support (Croatian/English)
|
||||||
|
|
||||||
|
* **Known Limitations / Issues:**
|
||||||
|
- No print functionality for barcode overview
|
||||||
|
- Barcode images stored as base64 strings but not displayed in bulk format
|
||||||
|
- No print-optimized styling or layout
|
||||||
|
|
||||||
|
* **Relevant Files / Modules:**
|
||||||
|
- `app/ui/MonthCard.tsx` - Monthly accordion components
|
||||||
|
- `app/ui/MonthLocationList.tsx` - Main month listing container
|
||||||
|
- `app/lib/db-types.ts` - Bill interface with `barcodeImage` field
|
||||||
|
- `app/lib/actions/locationActions.ts` - Data fetching for locations/bills
|
||||||
|
- Package dependencies: `@zxing/library`, `@zxing/browser`, `pdfjs-dist`
|
||||||
|
|
||||||
|
* **Environment / Dependencies:**
|
||||||
|
- Node.js >=18.17.0
|
||||||
|
- Next.js 14 with App Router and TypeScript
|
||||||
|
- Tailwind CSS 3.4.0 with DaisyUI 4.5.0
|
||||||
|
- MongoDB 6.3.0 for data persistence
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Desired State of Software
|
||||||
|
|
||||||
|
*(Target state after Sprint is complete)*
|
||||||
|
|
||||||
|
* **New Features:**
|
||||||
|
- Print 2D codes button in each MonthCard
|
||||||
|
- Print preview page with barcode table layout
|
||||||
|
- Print-optimized styling with 58mm barcode width specification
|
||||||
|
- Fixed print icon for triggering native print dialog
|
||||||
|
|
||||||
|
* **Modified Features:**
|
||||||
|
- MonthCard component enhanced with print button
|
||||||
|
- New print route and page component added to Next.js routing
|
||||||
|
|
||||||
|
* **Expected Behavior Changes:**
|
||||||
|
- Users can access print functionality from month view
|
||||||
|
- Print preview opens in new tab/window
|
||||||
|
- Barcode table displays with row index, bill info, and barcode image
|
||||||
|
- Print layout optimized for A4 paper in B&W
|
||||||
|
|
||||||
|
* **External Dependencies / Integrations:**
|
||||||
|
- Native browser print dialog integration
|
||||||
|
- CSS print media queries for optimized print output
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. User Stories
|
||||||
|
|
||||||
|
| Story ID | Title | Description | Acceptance Criteria | Definition of Done | Assignee | Status |
|
||||||
|
| -------- | ----- | ----------- | ------------------- | ------------------ | -------- | ------ |
|
||||||
|
| US-1 | Add Print Button | Add print 2D codes button to MonthCard component | Button appears next to "Add a new realestate", has printer icon, tooltips in EN/HR, opens print preview on click | Button implemented, styled with DaisyUI, tooltips working, click handler implemented, **user testing completed** | AI-Agent | ✅ done |
|
||||||
|
| US-2 | Create Print Route | Implement Next.js route for print preview | Route `/print/[year]/[month]` exists and loads barcode data | Route created, data fetching implemented, proper error handling, **user testing completed** | AI-Agent | 🚧 in progress |
|
||||||
|
| US-3 | Build Print Layout | Create print preview page with barcode table | Table has 3 columns: row index, bill info (yyyy-mm, realestate name, bill name), 2D barcode image | Print page component created, table layout implemented, data properly displayed, **user testing completed** | AI-Agent | 🔲 todo |
|
||||||
|
| US-4 | Print Optimization | Apply print-specific CSS styling | 58mm barcode width, A4 paper size, B&W print, fixed print icon (hidden in print) | CSS print media queries added, barcode sizing correct, print icon positioned and hidden from print, **user testing completed** | AI-Agent | 🔲 todo |
|
||||||
|
|
||||||
|
**Status options:** `🔲 todo`, `🚧 in progress`, `🚫 blocked`, `✅ done`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Technical Instructions
|
||||||
|
|
||||||
|
*(Guidance to help AI converge quickly on the correct solution)*
|
||||||
|
|
||||||
|
* **Code Snippets / Patterns:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Print button component pattern (integrate into MonthCard.tsx)
|
||||||
|
import { PrinterIcon } from '@heroicons/react/24/outline';
|
||||||
|
|
||||||
|
const handlePrintClick = () => {
|
||||||
|
window.open(`/print/${yearMonth.year}/${yearMonth.month}`, '_blank');
|
||||||
|
};
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="btn btn-ghost btn-sm"
|
||||||
|
onClick={handlePrintClick}
|
||||||
|
title={t("print-codes-tooltip")}
|
||||||
|
>
|
||||||
|
<PrinterIcon className="h-4 w-4" />
|
||||||
|
{t("print-codes-label")}
|
||||||
|
</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Print page route structure: app/[locale]/print/[year]/[month]/page.tsx
|
||||||
|
interface PrintPageProps {
|
||||||
|
params: { year: string; month: string; locale: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function PrintPage({ params }: PrintPageProps) {
|
||||||
|
const locations = await fetchAllLocations(parseInt(params.year));
|
||||||
|
// Filter for specific month and extract bills with barcodes
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```css
|
||||||
|
/* Print-specific CSS */
|
||||||
|
@media print {
|
||||||
|
.no-print { display: none !important; }
|
||||||
|
.barcode-cell img { width: 58mm; height: auto; }
|
||||||
|
@page { size: A4; margin: 1in; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* **Architecture Guidelines:**
|
||||||
|
- Follow existing Next.js App Router patterns with `[locale]` prefix
|
||||||
|
- Use server components for data fetching, client components only when needed
|
||||||
|
- Apply existing `withUser` HOF pattern for authenticated data access
|
||||||
|
- Maintain separation between UI components (`app/ui/`) and business logic
|
||||||
|
|
||||||
|
* **Coding Style Conventions:**
|
||||||
|
- Use TypeScript with existing interface patterns from `db-types.ts`
|
||||||
|
- Follow DaisyUI component classes and Tailwind utilities
|
||||||
|
- Use existing translation pattern with `useTranslations()` hook
|
||||||
|
- Maintain existing file naming conventions (PascalCase for components)
|
||||||
|
|
||||||
|
* **Testing Strategy:**
|
||||||
|
- AI agent implements feature and stops at testing checkpoint
|
||||||
|
- AI provides specific test instructions with expected behavior to user
|
||||||
|
- User performs manual testing and reports results (pass/fail with details)
|
||||||
|
- AI iterates on failures until user confirms all tests pass
|
||||||
|
- Process repeats for each user story until sprint completion
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Risks and Dependencies
|
||||||
|
|
||||||
|
* **Risks:**
|
||||||
|
- Browser print dialog compatibility across different browsers
|
||||||
|
- Barcode image quality in print output
|
||||||
|
- CSS print media query support variations
|
||||||
|
- Large number of barcodes may cause performance issues in print preview
|
||||||
|
|
||||||
|
* **Dependencies:**
|
||||||
|
- Existing barcode data in `Bill.barcodeImage` field
|
||||||
|
- `@heroicons/react` for printer icon
|
||||||
|
- Tailwind CSS print utilities
|
||||||
|
- Next.js routing and internationalization setup
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Sprint Definition of Done (DoD)
|
||||||
|
|
||||||
|
The Sprint is complete when:
|
||||||
|
|
||||||
|
**AI-Responsible Items** (AI agent can verify and tick):
|
||||||
|
* [ ] Print button added to MonthCard with proper styling and tooltips
|
||||||
|
* [ ] Print route `/[locale]/print/[year]/[month]` implemented and functional
|
||||||
|
* [ ] Print preview page displays barcode table with correct layout
|
||||||
|
* [ ] CSS print media queries applied with 58mm barcode width specification
|
||||||
|
* [ ] Print icon positioned fixed and hidden from print output
|
||||||
|
* [ ] All user stories meet their individual Definition of Done
|
||||||
|
* [ ] Code compiles and passes automated tests (`npm run build`)
|
||||||
|
* [ ] Code formatting validated (`npm run prettier:check`)
|
||||||
|
* [ ] Code is committed and pushed on branch `feature/sprint-01`
|
||||||
|
* [ ] Sprint status updated to `✅ done`
|
||||||
|
|
||||||
|
**User-Only Items** (Only user can verify and tick):
|
||||||
|
* [ ] Branch is merged into main
|
||||||
|
* [ ] Print functionality tested across target browsers
|
||||||
|
* [ ] Print output quality validated on physical printer
|
||||||
|
|
||||||
|
---
|
||||||
@@ -58,7 +58,9 @@
|
|||||||
"link-copy-message": "Link copied to clipboard"
|
"link-copy-message": "Link copied to clipboard"
|
||||||
},
|
},
|
||||||
"month-card": {
|
"month-card": {
|
||||||
"payed-total-label": "Total monthly expenditure:"
|
"payed-total-label": "Total monthly expenditure:",
|
||||||
|
"print-codes-tooltip": "Print 2D codes",
|
||||||
|
"print-codes-label": "Print codes"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bill-delete-form": {
|
"bill-delete-form": {
|
||||||
|
|||||||
@@ -58,7 +58,9 @@
|
|||||||
"link-copy-message": "Link kopiran na clipboard"
|
"link-copy-message": "Link kopiran na clipboard"
|
||||||
},
|
},
|
||||||
"month-card": {
|
"month-card": {
|
||||||
"payed-total-label": "Ukupni mjesečni trošak:"
|
"payed-total-label": "Ukupni mjesečni trošak:",
|
||||||
|
"print-codes-tooltip": "Ispis 2d kodova",
|
||||||
|
"print-codes-label": "Ispis kodova"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bill-delete-form": {
|
"bill-delete-form": {
|
||||||
|
|||||||
Reference in New Issue
Block a user