Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eniig ustgah empty state iig icon ashiglaj shiideh

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions frontend/plugins/tourism_ui/src/config.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ene hediig false bolgoh

Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ export const CONFIG: IUIConfig = {
icon: IconSandbox,
path: 'pms',
hasSettings: true,
hasRelationWidget: true,
hasWidgets: true,
},
{
name: 'tms',
icon: IconBox,
path: 'tms',
hasSettings: true,
hasRelationWidget: true,
hasWidgets: true,
// submenus: [
// {
// name: 'submenu1',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const Appearance = ({ control }: { control: Control<PmsBranchFormType> }) => {
return (
<PmsFormFieldsLayout>
<Heading>Logo and favicon</Heading>
<div className="xl:grid grid-cols-3">
<div className="grid-cols-3 xl:grid">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding the 'grid' class before 'grid-cols-3' to ensure the container is set to display grid.

Suggested change
<div className="grid-cols-3 xl:grid">
<div className="grid grid-cols-3 xl:grid">

<Form.Field
control={control}
name="logo"
Expand All @@ -26,7 +26,7 @@ const Appearance = ({ control }: { control: Control<PmsBranchFormType> }) => {
size="sm"
variant="secondary"
type="button"
className="flex flex-col gap-3 items-center justify-center w-full h-52 border border-dashed text-muted-foreground"
className="flex flex-col items-center justify-center w-full gap-3 border border-dashed h-52 text-muted-foreground"
>
<IconUpload />
<Button variant={'outline'}>Upload Logo</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ const Discount = ({ control }: { control: Control<PmsBranchFormType> }) => {
</Button>

{fields.map((field, index) => (
<div className="flex gap-6 items-end">
<div className="w-full grid grid-cols-3 gap-6">
<div className="flex items-end gap-6">
<div className="grid w-full grid-cols-3 gap-6">
<Form.Field
control={control}
name={`discounts.${index}.type`}
Expand Down Expand Up @@ -62,7 +62,7 @@ const Discount = ({ control }: { control: Control<PmsBranchFormType> }) => {
<Button
variant={'destructive'}
size={'icon'}
className="h-8 w-8"
className="w-8 h-8"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

size-8 gej class baigaa

onClick={() => remove(index)}
>
<IconTrash />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ const Payments = ({ control }: { control: Control<PmsBranchFormType> }) => {
</Button>

{fields.map((field, index) => (
<div className="flex gap-6 items-end">
<div className="w-full grid grid-cols-3 gap-6">
<div className="flex items-end gap-6">
<div className="grid w-full grid-cols-3 gap-6">
<Form.Field
control={control}
name={`otherPayments.${index}.type`}
Expand Down Expand Up @@ -116,7 +116,7 @@ const Payments = ({ control }: { control: Control<PmsBranchFormType> }) => {
<Button
variant={'destructive'}
size={'icon'}
className="h-8 w-8"
className="w-8 h-8"
onClick={() => remove(index)}
>
<IconTrash />
Expand Down
7 changes: 7 additions & 0 deletions frontend/plugins/tourism_ui/src/modules/tms/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ const Tms = lazy(() =>
})),
);

const PreviewPage = lazy(() =>
import('~/pages/tms/PreviewPage').then((module) => ({
default: module.default,
})),
);

const TmsMain = () => {
return (
<Suspense fallback={<div />}>
<Routes>
<Route path="/" element={<Tms />} />
<Route path="/PreviewPage" element={<PreviewPage />} />
</Routes>
</Suspense>
);
Expand Down
2 changes: 1 addition & 1 deletion frontend/plugins/tourism_ui/src/modules/tms/Settings.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const Settings = () => {
return (
<div>
<h1>Tms Settings</h1>
<h1 className="text-center justify-center">Tms Settings</h1>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
IconEdit,
IconCopy,
IconWorld,
IconTrash,
IconChevronDown,
} from '@tabler/icons-react';
import { Popover } from 'erxes-ui';

interface ActionMenuProps {
onEdit: () => void;
onDuplicate: () => void;
onDelete: () => void;
duplicateLoading: boolean;
}

export const ActionMenu = ({
onEdit,
onDuplicate,
onDelete,
duplicateLoading,
}: ActionMenuProps) => {
return (
<Popover>
<Popover.Trigger asChild>
<button className="flex items-center leading-[100%] text-foreground font-inter gap-1 text-sm font-medium rounded-md px-1">
Action
<IconChevronDown size={18} stroke={2} />
</button>
Comment on lines +48 to +51
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance button accessibility.

The action trigger button lacks proper accessibility attributes and focus styling for keyboard navigation.

-        <button className="flex items-center leading-[100%] text-foreground font-inter gap-1 text-sm font-medium rounded-md px-1">
+        <button 
+          className="flex items-center leading-[100%] text-foreground font-inter gap-1 text-sm font-medium rounded-md px-1 hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring"
+          aria-label="Open action menu"
+        >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button className="flex items-center leading-[100%] text-foreground font-inter gap-1 text-sm font-medium rounded-md px-1">
Action
<IconChevronDown size={18} stroke={2} />
</button>
<button
className="flex items-center leading-[100%] text-foreground font-inter gap-1 text-sm font-medium rounded-md px-1 hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring"
aria-label="Open action menu"
>
Action
<IconChevronDown size={18} stroke={2} />
</button>
🤖 Prompt for AI Agents
In frontend/plugins/tourism_ui/src/modules/tms/components/ActionMenu.tsx around
lines 26 to 29, the button element lacks accessibility attributes and focus
styles. Add appropriate ARIA attributes such as aria-haspopup and aria-expanded
to indicate the button's role and state. Also, include focus-visible styling to
ensure keyboard users can see when the button is focused, improving keyboard
navigation accessibility.

</Popover.Trigger>
<Popover.Content
className="p-1 w-48 rounded-lg border shadow-lg bg-background"
side="bottom"
align="end"
>
<div
className="flex gap-3 items-center px-4 py-2 w-full text-left rounded-md cursor-pointer hover:bg-muted"
onClick={onEdit}
>
<IconEdit size={16} stroke={1.5} />
<p className="text-sm font-medium leading-[100%] font-inter">Edit</p>
</div>

<div
className={`flex items-center w-full gap-3 px-4 py-2 text-left cursor-pointer hover:bg-muted rounded-md ${
duplicateLoading ? 'opacity-50 pointer-events-none' : ''
}`}
onClick={() => !duplicateLoading && onDuplicate()}
>
<IconCopy size={16} stroke={1.5} />
<p className="text-sm font-medium leading-[100%] font-inter">
{duplicateLoading ? 'Duplicating...' : 'Duplicate'}
</p>
</div>

<div className="flex gap-3 items-center px-4 py-2 w-full text-left rounded-md cursor-pointer hover:bg-muted">
<IconWorld size={16} stroke={1.5} />
<p className="text-sm font-medium leading-[100%] font-inter">
Visit website
</p>
</div>

<div
className="flex gap-3 items-center px-4 py-2 w-full text-left rounded-md cursor-pointer hover:bg-destructive/10 text-destructive"
onClick={onDelete}
>
<IconTrash size={16} stroke={1.5} />
<p className="text-sm font-medium leading-[100%] font-inter">
Delete
</p>
</div>
</Popover.Content>
</Popover>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { useState } from 'react';
import { Button, Dialog, Input, Label } from 'erxes-ui';
import { IconPlus, IconX } from '@tabler/icons-react';

export const AddPaymentDialog = () => {
const [open, setOpen] = useState(false);

return (
// TODO: Add functionalities
<Dialog open={open} onOpenChange={setOpen}>
<Dialog.Trigger asChild>
<Button
variant="default"
className="flex gap-2 items-center h-8"
type="button"
>
<IconPlus size={18} />
Add Payment
</Button>
</Dialog.Trigger>

<Dialog.Content className="max-w-lg">
<Dialog.Header>
<Dialog.Title>Add New Payment Method</Dialog.Title>
<Dialog.Description>
Add a new payment method to your available options.
</Dialog.Description>
<Dialog.Close asChild>
<Button
variant="secondary"
size="icon"
className="absolute top-3 right-4"
>
<IconX />
</Button>
</Dialog.Close>
</Dialog.Header>

<form className="space-y-4">
<div className="grid gap-4">
<div className="space-y-2">
<Label className="text-sm font-medium">
Payment Name <span className="text-destructive">*</span>
</Label>
<Input
placeholder="e.g., Visa, Mastercard, QPay"
className="h-9"
/>
</div>

<div className="space-y-2">
<Label className="text-sm font-medium">
Payment Value <span className="text-destructive">*</span>
</Label>
<Input
placeholder="e.g., visa, mastercard, qpay"
className="h-9"
/>
</div>
</div>

<Dialog.Footer>
<Button type="button" variant="outline">
Cancel
</Button>
<Button type="button">Add Payment Method</Button>
</Dialog.Footer>
</form>
Comment on lines +39 to +68
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Implement controlled form inputs and submission handling.

The form lacks state management, validation, and submission logic. The inputs are uncontrolled and the buttons have no functionality.

+import { useState } from 'react';
+
+interface PaymentFormData {
+  name: string;
+  value: string;
+}

 export const AddPaymentDialog = () => {
   const [open, setOpen] = useState(false);
+  const [formData, setFormData] = useState<PaymentFormData>({
+    name: '',
+    value: '',
+  });
+
+  const handleInputChange = (field: keyof PaymentFormData, value: string) => {
+    setFormData(prev => ({ ...prev, [field]: value }));
+  };
+
+  const handleSubmit = (e: React.FormEvent) => {
+    e.preventDefault();
+    // TODO: Implement payment creation logic
+    console.log('Payment data:', formData);
+    setOpen(false);
+    setFormData({ name: '', value: '' });
+  };
+
+  const handleCancel = () => {
+    setOpen(false);
+    setFormData({ name: '', value: '' });
+  };

-        <form className="space-y-4">
+        <form className="space-y-4" onSubmit={handleSubmit}>
           <div className="grid gap-4">
             <div className="space-y-2">
               <Label className="text-sm font-medium">
                 Payment Name <span className="text-destructive">*</span>
               </Label>
               <Input
                 placeholder="e.g., Visa, Mastercard, QPay"
                 className="h-9"
+                value={formData.name}
+                onChange={(e) => handleInputChange('name', e.target.value)}
+                required
               />
             </div>

             <div className="space-y-2">
               <Label className="text-sm font-medium">
                 Payment Value <span className="text-destructive">*</span>
               </Label>
               <Input
                 placeholder="e.g., visa, mastercard, qpay"
                 className="h-9"
+                value={formData.value}
+                onChange={(e) => handleInputChange('value', e.target.value)}
+                required
               />
             </div>
           </div>

           <Dialog.Footer>
-            <Button type="button" variant="outline">
+            <Button type="button" variant="outline" onClick={handleCancel}>
               Cancel
             </Button>
-            <Button type="button">Add Payment Method</Button>
+            <Button type="submit">Add Payment Method</Button>
           </Dialog.Footer>
         </form>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<form className="space-y-4">
<div className="grid gap-4">
<div className="space-y-2">
<Label className="text-sm font-medium">
Payment Name <span className="text-destructive">*</span>
</Label>
<Input
placeholder="e.g., Visa, Mastercard, QPay"
className="h-9"
/>
</div>
<div className="space-y-2">
<Label className="text-sm font-medium">
Payment Value <span className="text-destructive">*</span>
</Label>
<Input
placeholder="e.g., visa, mastercard, qpay"
className="h-9"
/>
</div>
</div>
<Dialog.Footer>
<Button type="button" variant="outline">
Cancel
</Button>
<Button type="button">Add Payment Method</Button>
</Dialog.Footer>
</form>
<form className="space-y-4" onSubmit={handleSubmit}>
<div className="grid gap-4">
<div className="space-y-2">
<Label className="text-sm font-medium">
Payment Name <span className="text-destructive">*</span>
</Label>
<Input
placeholder="e.g., Visa, Mastercard, QPay"
className="h-9"
value={formData.name}
onChange={(e) => handleInputChange('name', e.target.value)}
required
/>
</div>
<div className="space-y-2">
<Label className="text-sm font-medium">
Payment Value <span className="text-destructive">*</span>
</Label>
<Input
placeholder="e.g., visa, mastercard, qpay"
className="h-9"
value={formData.value}
onChange={(e) => handleInputChange('value', e.target.value)}
required
/>
</div>
</div>
<Dialog.Footer>
<Button type="button" variant="outline" onClick={handleCancel}>
Cancel
</Button>
<Button type="submit">Add Payment Method</Button>
</Dialog.Footer>
</form>
🤖 Prompt for AI Agents
In frontend/plugins/tourism_ui/src/modules/tms/components/AddPaymentDialog.tsx
around lines 39 to 68, the form inputs are uncontrolled and there is no
submission handling or validation. To fix this, add React state hooks to manage
the values of the Payment Name and Payment Value inputs, making them controlled
components. Implement onChange handlers to update state on user input. Add form
submission logic with validation to ensure required fields are filled before
processing. Also, update the Cancel and Add Payment Method buttons to handle
form reset and submission respectively.

</Dialog.Content>
</Dialog>
);
};

export default AddPaymentDialog;
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { IconCalendarPlus } from '@tabler/icons-react';
import { IBranch } from '@/tms/types/branch';
import { format } from 'date-fns';
import { Avatar } from 'erxes-ui';
import { readImage } from 'erxes-ui/utils/core';
import { ActionMenu } from './ActionMenu';

interface BranchCardProps {
branch: IBranch;
onEdit: (branchId: string) => void;
onDuplicate: (branchId: string) => void;
onDelete: (branchId: string) => void;
duplicateLoading: boolean;
}

export const BranchCard = ({
branch,
onEdit,
onDuplicate,
onDelete,
duplicateLoading,
}: BranchCardProps) => {
return (
<div className="flex flex-col items-start p-2 w-full h-full bg-background shrink-0">
<div className="flex gap-4 items-start self-stretch">

<div className="flex flex-col items-start w-[290px] rounded-sm bg-background shadow-lg">
<div className="flex justify-between items-center self-stretch px-3 h-9">
<div className="flex gap-1 items-center">
<h3 className="text-sm font-semibold leading-[100%] text-foreground font-inter">
{branch.name || 'Unnamed Branch'}
</h3>
</div>

<ActionMenu
onEdit={() => onEdit(branch._id)}
onDuplicate={() => onDuplicate(branch._id)}
onDelete={() => onDelete(branch._id)}
duplicateLoading={duplicateLoading}
/>
</div>

<div className="flex h-[150px] w-full flex-col items-start gap-3 self-stretch">
<div className="flex justify-center items-center w-full h-full bg-background">
<img
src={
branch.uiOptions?.logo
? readImage(branch.uiOptions.logo)
: 'https://placehold.co/150x150'
}
alt={branch.name || 'Branch logo'}
className="object-cover w-full h-full"
/>
</div>
</div>

<div className="flex justify-between items-center self-stretch px-3 h-9">
<div className="flex gap-2 items-center">
<IconCalendarPlus size={12} className="text-foreground" />
<span className="text-[12px] font-semibold leading-[100%] font-inter">
Created:{' '}
{branch.createdAt
? format(new Date(branch.createdAt), 'dd MMM yyyy')
: 'N/A'}
</span>
</div>

<Avatar className="w-6 h-6 rounded-full border shadow-sm">
{branch.user?.details?.avatar ? (
<Avatar.Image
src={branch.user.details.avatar}
alt={branch.user.details.fullName || 'User avatar'}
/>
) : null}
<Avatar.Fallback>
{branch.user?.details?.fullName
?.split(' ')[0]
?.charAt(0)
?.toUpperCase() || 'A'}
</Avatar.Fallback>
</Avatar>
</div>
</div>
</div>
</div>
)
}
Loading