Skip to content

Commit 467041d

Browse files
committed
doc: add more comments on new components
1 parent 082a073 commit 467041d

File tree

5 files changed

+315
-26
lines changed

5 files changed

+315
-26
lines changed

client/src/pages/page-components/ActionCell.tsx

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,70 @@
1+
/**
2+
* MIT License
3+
*
4+
* Copyright (c) 2025 Ronan LE MEILLAT
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
125
import { Button } from "@heroui/button";
226
import { useTranslation } from "react-i18next";
327
import ButtonAddFeedbackOrReturn from "@/components/button-add-feedback-or-return";
428
import { PurchaseStatus } from "@/types/db";
529

30+
/**
31+
* Props interface for the ActionCell component
32+
* Defines the structure of data and callback functions needed
33+
*/
634
interface ActionCellProps {
35+
/** The purchase item data containing status information */
736
item: PurchaseStatus;
37+
/** Whether the current user has write permissions (null while loading) */
838
hasWritePermission: boolean | null;
39+
/** Callback function to create feedback for a purchase */
940
onCreateFeedback: (purchaseId: string, amount: number) => void;
41+
/** Callback function to return/return a purchase */
1042
onReturnItem: (purchaseId: string, amount: number) => void;
43+
/** Callback function to publish feedback for a purchase */
1144
onPublishFeedback: (purchaseId: string, amount: number) => void;
45+
/** Callback function to refund a purchase */
1246
onRefundPurchase: (purchaseId: string, amount: number) => void;
1347
}
1448

1549
/**
16-
* Component for rendering the action column in the purchase table
17-
* Shows different actions based on purchase status and user permissions
50+
* ActionCell Component
51+
*
52+
* This component renders the action buttons for each row in the purchase table.
53+
* The actions available depend on the purchase status and user permissions:
54+
*
55+
* - If the purchase is refunded: Shows "Refunded" status text
56+
* - If no feedback exists and user has write permission: Shows buttons to create feedback or return item
57+
* - If feedback exists but not published and user has write permission: Shows "Publish Feedback" button
58+
* - If feedback is published and user has write permission: Shows "Refund" button
59+
* - If user lacks write permission: Shows no actions
60+
*
61+
* The component uses conditional rendering to display appropriate actions based on:
62+
* 1. Purchase status (refunded, hasFeedback, hasPublication)
63+
* 2. User permissions (hasWritePermission)
64+
* 3. Loading state (when permissions are still being checked)
65+
*
66+
* @param props - The component props containing item data and callback functions
67+
* @returns JSX element representing the action cell content
1868
*/
1969
export const ActionCell = ({
2070
item,
@@ -24,27 +74,35 @@ export const ActionCell = ({
2474
onPublishFeedback,
2575
onRefundPurchase,
2676
}: ActionCellProps) => {
77+
// Hook to access translation functions for internationalization
2778
const { t } = useTranslation();
2879

29-
// Early return if permissions are still loading
80+
// Show loading text while permissions are being checked
81+
// This prevents showing incorrect action buttons during the loading phase
3082
if (hasWritePermission === null) {
3183
return <span className="text-gray-400">{t("loading")}</span>;
3284
}
3385

34-
// If refunded, show refunded status
86+
// If the purchase has been refunded, show the refunded status
87+
// No further actions are possible for refunded purchases
3588
if (item.refunded) {
3689
return <span className="text-green-500">{t("refunded")}</span>;
3790
}
3891

39-
// If no feedback and user has write permission, show create feedback/return options
92+
// If no feedback exists and user has write permission,
93+
// show the combined button for creating feedback or returning the item
4094
if (!item.hasFeedback && hasWritePermission) {
4195
return (
4296
<div className="flex gap-2">
97+
{/* Custom button component that handles both feedback creation and item return */}
4398
<ButtonAddFeedbackOrReturn
4499
onAction={(key) => {
100+
// Handle the action based on the key returned by the button
45101
if (key === "feedback") {
102+
// Call the callback to create feedback for this purchase
46103
onCreateFeedback(item.purchase, item.amount);
47104
} else if (key === "return") {
105+
// Call the callback to return this purchase
48106
onReturnItem(item.purchase, item.amount);
49107
}
50108
}}

client/src/pages/page-components/PurchaseIdCell.tsx

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,105 @@
1+
/**
2+
* MIT License
3+
*
4+
* Copyright (c) 2025 Ronan LE MEILLAT
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
125
import { CopyButton } from "@/components/copy-button";
226
import { EditIcon } from "@heroui/shared-icons";
327
import { AuthenticationGuardWithPermission } from "@/components/auth0";
428

29+
/**
30+
* Props interface for the PurchaseIdCell component
31+
* Defines the structure of data and callback functions needed
32+
*/
533
interface PurchaseIdCellProps {
34+
/** The unique identifier of the purchase */
635
purchaseId: string;
36+
/** Whether this purchase has been published (affects link generation availability) */
737
hasPublication: boolean;
38+
/** Callback function to edit the purchase */
839
onEditPurchase: (purchaseId: string) => void;
40+
/** Callback function to generate a public link for the purchase */
941
onGenerateLink: (purchaseId: string) => void;
1042
}
1143

1244
/**
13-
* Component for rendering the purchase ID cell with copy button, edit button, and link generation
45+
* PurchaseIdCell Component
46+
*
47+
* This component renders the purchase ID cell in the purchase table.
48+
* It displays the purchase ID with interactive features based on user permissions and purchase status.
49+
*
50+
* Features:
51+
* - Displays the purchase ID as clickable text (if publication exists)
52+
* - Clicking the ID generates a public link (only available for published purchases)
53+
* - Includes a copy button to copy the purchase ID to clipboard
54+
* - Shows an edit icon for admin users to modify the purchase
55+
* - Uses authentication guard to restrict edit functionality to admin users only
56+
*
57+
* The component combines multiple UI elements:
58+
* 1. Clickable purchase ID (when publication exists)
59+
* 2. CopyButton for easy ID copying
60+
* 3. EditIcon with authentication guard for admin editing
61+
*
62+
* @param props - The component props containing purchase data and callback functions
63+
* @returns JSX element representing the purchase ID cell with interactive features
1464
*/
1565
export const PurchaseIdCell = ({
1666
purchaseId,
1767
hasPublication,
1868
onEditPurchase,
1969
onGenerateLink,
2070
}: PurchaseIdCellProps) => {
71+
// Determine if the user can generate a public link
72+
// Link generation is only available for purchases that have been published
2173
const canGenerateLink = hasPublication;
2274

2375
return (
2476
<>
2577
<div className="flex items-center">
78+
{/* Purchase ID display - clickable if publication exists */}
2679
<div
80+
// Apply clickable styling only if link generation is available
2781
className={canGenerateLink ? "cursor-pointer hover:underline text-blue-500" : ""}
2882
onClick={() => {
83+
// Generate public link when clicked (only if publication exists)
2984
if (canGenerateLink) {
3085
onGenerateLink(purchaseId);
3186
}
3287
}}
3388
>
3489
{purchaseId}
3590
</div>
91+
92+
{/* Action buttons container */}
3693
<div className="flex flex-col">
94+
{/* Copy button to copy purchase ID to clipboard */}
3795
<CopyButton value={purchaseId} />
96+
97+
{/* Edit button - only visible to admin users */}
3898
<AuthenticationGuardWithPermission permission={import.meta.env.ADMIN_PERMISSION}>
3999
<EditIcon
100+
// Click handler to open edit modal
40101
onClick={() => onEditPurchase(purchaseId)}
102+
// Styling classes for the edit icon (HeroUI styling)
41103
className="group inline-flex items-center justify-center box-border appearance-none select-none whitespace-nowrap font-normal subpixel-antialiased overflow-hidden tap-highlight-transparent transform-gpu data-[pressed=true]:scale-[0.97] cursor-pointer outline-hidden data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 text-tiny rounded-small px-0 transition-transform-colors-opacity motion-reduce:transition-none bg-transparent data-[hover=true]:bg-default/40 min-w-4 w-4 h-4 relative z-50 text-zinc-300 bottom-0 left-2"
42104
/>
43105
</AuthenticationGuardWithPermission>

client/src/pages/page-components/StatusCell.tsx

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,66 @@
1+
/**
2+
* MIT License
3+
*
4+
* Copyright (c) 2025 Ronan LE MEILLAT
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
125
import { Tooltip } from "@heroui/tooltip";
226
import { CopyButton } from "@/components/copy-button";
327
import { Transparent1x1WebpPixel } from "@/components/icons";
428
import { useTranslation } from "react-i18next";
529

30+
/**
31+
* Props interface for the StatusCell component
32+
* Defines the structure of data needed to display status with optional screenshot
33+
*/
634
interface StatusCellProps {
35+
/** The main text to display in the cell */
736
text: string;
37+
/** Optional screenshot URL for the purchase */
838
screenshot?: string;
39+
/** Optional screenshot summary URL (for additional context) */
940
screenshotSummary?: string;
41+
/** Translation key for the copy button tooltip */
1042
copyTooltipKey: "copy-screenshot" | "copy-screenshots";
43+
/** Callback function when screenshot is clicked */
1144
onScreenshotClick: (screenshot: string | string[]) => void;
1245
}
1346

1447
/**
15-
* Component for rendering table cells that show status text with optional screenshot copy button
16-
* Includes tooltip for screenshot viewing and copy button with tooltip
48+
* StatusCell Component
49+
*
50+
* This component renders table cells that display status text with optional screenshot functionality.
51+
* It provides a user-friendly way to view and copy screenshots associated with purchases.
52+
*
53+
* Features:
54+
* - Displays the main status text (e.g., "Yes", "No", or description)
55+
* - Shows a tooltip when hovering over the text indicating it can be clicked to view screenshot
56+
* - Includes a copy button to copy screenshot URLs to clipboard
57+
* - Handles both single screenshots and screenshot pairs (main + summary)
58+
*
59+
* The component uses HeroUI's Tooltip component to provide helpful user guidance
60+
* and a custom CopyButton component for copying screenshot data.
61+
*
62+
* @param props - The component props containing text, screenshot data, and callbacks
63+
* @returns JSX element representing the status cell with optional screenshot functionality
1764
*/
1865
export const StatusCell = ({
1966
text,
@@ -22,31 +69,40 @@ export const StatusCell = ({
2269
copyTooltipKey,
2370
onScreenshotClick,
2471
}: StatusCellProps) => {
72+
// Hook to access translation functions for internationalization
2573
const { t } = useTranslation();
2674

2775
return (
2876
<div className="flex items-center justify-between">
77+
{/* Main text content with click-to-view functionality */}
2978
<Tooltip content={t("click-to-see-the-screenshot")}>
3079
<span
3180
className="flex-1 cursor-pointer"
3281
onClick={() => {
82+
// Handle click to show screenshot(s)
83+
// If both main screenshot and summary exist, show both
3384
if (screenshotSummary && screenshot) {
3485
onScreenshotClick([screenshot, screenshotSummary]);
3586
} else if (screenshot) {
87+
// Otherwise show just the main screenshot
3688
onScreenshotClick(screenshot);
3789
}
3890
}}
3991
>
4092
{text}
4193
</span>
4294
</Tooltip>
95+
96+
{/* Copy button for screenshot URLs - only shown if screenshot exists */}
4397
{screenshot && (
4498
<Tooltip content={t(copyTooltipKey)}>
4599
<CopyButton
100+
// Prepare the value to copy - either single screenshot or array of screenshots
46101
value={screenshotSummary && screenshot
47102
? [screenshot, screenshotSummary || Transparent1x1WebpPixel]
48103
: screenshot
49104
}
105+
// Indicate that this is image data for proper clipboard handling
50106
isImage={true}
51107
showToast={true}
52108
toastText={t("copied-to-clipboard")}

0 commit comments

Comments
 (0)