Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
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
5 changes: 0 additions & 5 deletions .env.sample

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { EMGreetingAvatar } from '@/integrations/erxes-messenger/components/EMGr
export const ActiveUsers = () => {
const { members } = useMembersInlineContext();
return (
<div className="flex items-center gap-2">
<div className="flex gap-2 items-center">
{members.map((member) => (
<Avatar key={member._id} size="xl">
<Avatar.Image src={readImage(member.details?.avatar || '', 200)} />
Expand All @@ -27,9 +27,10 @@ export const ActiveUsers = () => {
export const EMPreviewIntro = () => {
const greeting = useAtomValue(erxesMessengerSetupGreetingAtom);
const hours = useAtomValue(erxesMessengerSetupHoursAtom);

return (
<>
<div className="bg-primary text-primary-foreground p-6 pb-16 pt-4">
<div className="p-6 pt-4 pb-16 bg-primary text-primary-foreground">
<Popover.Close asChild>
<Button
size="icon"
Expand All @@ -39,7 +40,7 @@ export const EMPreviewIntro = () => {
<IconX />
</Button>
</Popover.Close>
<div className="flex items-center gap-1 text-accent mb-2">
<div className="flex gap-1 items-center mb-2 text-accent">
{greeting?.links?.map(
(link) =>
!!link && (
Expand All @@ -60,22 +61,22 @@ export const EMPreviewIntro = () => {
<h1 className="text-2xl font-semibold">
{greeting?.title || 'Welcome'}
</h1>
<p className="text-sm text-primary-foreground/80 mt-3 mb-5">
<p className="mt-3 mb-5 text-sm text-primary-foreground/80">
{greeting?.message || 'Welcome to Erxes Messenger'}
</p>
<MembersInline.Provider memberIds={greeting?.supporterIds || []}>
<ActiveUsers />
</MembersInline.Provider>
</div>
<div className="bg-background px-4 py-6 -mt-8 mx-6 rounded-xl shadow-md">
<div className="font-medium text-accent-foreground mb-2 text-sm px-3">
<div className="px-4 py-6 mx-6 -mt-8 rounded-xl shadow-md bg-background">
<div className="px-3 mb-2 text-sm font-medium text-accent-foreground">
Recent conversations
</div>
<Button
className="w-full text-left h-auto justify-start rounded-md px-2 my-2"
className="justify-start px-2 my-2 w-full h-auto text-left rounded-md"
variant="ghost"
>
<div className="flex items-center bg-muted text-muted-foreground p-2 rounded-full">
<div className="flex items-center p-2 rounded-full bg-muted text-muted-foreground">
<IconPlus className="size-5" strokeWidth={1.5} />
</div>
<div className="flex flex-col gap-1">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const EMSetup = ({
loading?: boolean;
}) => {
const step = useAtomValue(erxesMessengerSetupStepAtom);

return (
<Sheet.View
className="gap-0 flex-col flex sm:max-w-none md:w-[calc(100vw-theme(spacing.4))]"
Expand All @@ -29,7 +30,7 @@ export const EMSetup = ({
</Sheet.Header>

{loading ? (
<div className="flex flex-1 items-center justify-center w-full">
<div className="flex flex-1 justify-center items-center w-full">
<Spinner />
</div>
) : (
Expand Down
1 change: 1 addition & 0 deletions frontend/plugins/tourism_ui/module-federation.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const config: ModuleFederationConfig = {
'./pmsSettings': './src/modules/pms/Settings.tsx',
'./tms': './src/modules/tms/Main.tsx',
'./tmsSettings': './src/modules/tms/Settings.tsx',
'./tourism': './src/modules/main/Main.tsx',
},

shared: (libraryName, defaultConfig) => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/plugins/tourism_ui/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"main": "frontend/plugins/tourism_ui/src/main.ts",
"tsConfig": "frontend/plugins/tourism_ui/tsconfig.app.json",
"rspackConfig": "frontend/plugins/tourism_ui/rspack.config.ts",
"assets": []
"assets": ["frontend/plugins/tourism_ui/src/assets"]
},
"configurations": {
"development": {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 16 additions & 9 deletions frontend/plugins/tourism_ui/src/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,25 @@ export const CONFIG: IUIConfig = {
},
modules: [
{
name: 'pms',
icon: IconSandbox,
path: 'pms',
hasSettings: true,
hasRelationWidget: true,
},
{
name: 'tms',
name: 'tourism',
icon: IconBox,
path: 'tms',
path: 'tourism',
hasSettings: true,
hasRelationWidget: true,
},
// {
// name: 'pms',
// icon: IconSandbox,
// path: 'pms',
// hasSettings: true,
// hasRelationWidget: true,
// },
// {
// name: 'tms',
// icon: IconBox,
// path: 'tms',
// hasSettings: true,
// hasRelationWidget: true,
// },
],
};
33 changes: 33 additions & 0 deletions frontend/plugins/tourism_ui/src/modules/main/Main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { lazy, Suspense } from 'react'
import { Navigate, Route, Routes } from 'react-router-dom'

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

const App = () => {
return (
<Suspense fallback={<div />}>
<Routes>
<Route path="/" element={<Navigate to="tms" replace />} />
<Route path="/tms" element={<Tms />} />
<Route path="/tms/PreviewPage" element={<TmsPreview />} />
<Route path="/pms" element={<Pms />} />
</Routes>
</Suspense>
)
}

export default App
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Use named export instead of default export.

The coding guidelines specify favoring named exports for components.

As per coding guidelines.

Apply this diff:

-export default App
+export { App }

You'll also need to update the import in module-federation.config.ts accordingly.

📝 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
export default App
export { App }
🤖 Prompt for AI Agents
In frontend/plugins/tourism_ui/src/modules/main/Main.tsx around line 33, the
file currently uses a default export for the App component; change it to a named
export (export const App = ... or export { App }) and remove the default export
line, then update any imports—specifically update the import in
module-federation.config.ts to import { App } from './modules/main/Main' (or the
correct relative path) instead of the default import, and run a quick build/test
to ensure no other files reference the default export.

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="justify-center text-center">Tms Settings</h1>
</div>
);
};
Expand Down
71 changes: 71 additions & 0 deletions frontend/plugins/tourism_ui/src/modules/tms/atoms/formAtoms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { atom } from 'jotai';
import { atomWithStorage, RESET } from 'jotai/utils';

type TmsFormStorage = TmsForm;

export type TmsForm = {
name: string;
color: string;
logo: string;
favIcon: string;
generalManager: string[];
managers: string[];
payment: string;
token: string;
otherPayments: Array<{
type: string;
title: string;
icon: string;
config?: string;
}>;
};

const DEFAULT_STORAGE_FORM: TmsFormStorage = {
name: '',
color: '#4F46E5',
logo: '',
favIcon: '',
generalManager: [],
managers: [],
payment: '',
token: '',
otherPayments: [],
};

export const DEFAULT_TMS_FORM: TmsForm = {
name: '',
color: '#4F46E5',
logo: '',
favIcon: '',
generalManager: [],
managers: [],
payment: '',
token: '',
otherPayments: [],
};

const tmsFormStorageAtom = atomWithStorage<TmsFormStorage>(
'tms_form_data',
DEFAULT_STORAGE_FORM,
);

export const tmsFormAtom = atom(
(get) => {
const storage = get(tmsFormStorageAtom);
return {
...DEFAULT_TMS_FORM,
...storage,
};
},
(get, set, update: TmsForm) => {
const prev = get(tmsFormStorageAtom);
set(tmsFormStorageAtom, {
...prev,
...update,
});
},
);

export const resetFormAtom = atom(null, (get, set) => {
set(tmsFormStorageAtom, RESET);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import {
IconEdit,
IconCopy,
IconTrash,
IconChevronDown,
} from '@tabler/icons-react';
import { Popover, Spinner } from 'erxes-ui';

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

export const ActionMenu = ({
onEdit,
onDuplicate,
onDelete,
duplicateLoading,
}: ActionMenuProps) => {
const dropdownItems = [
{
label: 'Edit',
icon: <IconEdit size={16} stroke={1.5} />,
onClick: () => onEdit(),
},
{
label: duplicateLoading ? 'Duplicating…' : 'Duplicate',
icon: duplicateLoading ? (
<Spinner className="w-4 h-4" />
) : (
<IconCopy className="size-4" />
),
onClick: () => onDuplicate(),
disabled: duplicateLoading,
},
// {
// label: 'Visit website',
// icon: <IconWorld size={16} stroke={1.5} />,
// onClick: () => window.open(branch.website, '_blank'),
// },
{
label: 'Delete',
icon: <IconTrash size={16} stroke={1.5} />,
onClick: () => onDelete(),
},
];

return (
<Popover>
<Popover.Trigger asChild>
<button
className="flex items-center leading-[100%] text-foreground font-inter gap-1 text-sm font-medium rounded-md p-1 hover:bg-muted focus:outline-none"
aria-label="Open action menu"
aria-haspopup="true"
role="menuitem"
>
Action
<IconChevronDown size={18} stroke={2} />
</button>
</Popover.Trigger>
<Popover.Content
className="p-1 w-48 rounded-lg border shadow-lg bg-background"
side="bottom"
align="end"
>
{dropdownItems.map((item) => (
<div
Copy link

Choose a reason for hiding this comment

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

Each item in the dropdown map should have a unique key prop to avoid React key warnings.

key={item.label}
className={`flex gap-3 items-center px-4 py-2 w-full text-left rounded-md cursor-pointer hover:bg-muted ${
(item as any).disabled ? 'opacity-60 pointer-events-none' : ''
}`}
aria-disabled={(item as any).disabled ? true : undefined}
onClick={(e) => {
if ((item as any).disabled) return;
item.onClick();
}}
>
{item.icon}
<p className="text-sm font-medium leading-[100%] font-inter">
{item.label}
</p>
</div>
))}
</Popover.Content>
</Popover>
);
};
Loading