Forced merge: merge ai-dev into master

This commit is contained in:
Flatlogic Bot 2025-06-09 14:51:02 +00:00
commit 8b609978d6
26 changed files with 555 additions and 46 deletions

5
.gitignore vendored
View File

@ -1,3 +1,8 @@
node_modules/ node_modules/
*/node_modules/ */node_modules/
*/build/ */build/
**/node_modules/
**/build/
.DS_Store
.env

File diff suppressed because one or more lines are too long

View File

@ -18,6 +18,9 @@ module.exports = class Booking_requestsDBApi {
start_date: data.start_date || null, start_date: data.start_date || null,
end_date: data.end_date || null, end_date: data.end_date || null,
status: data.status || null, status: data.status || null,
guest_name: data.guest_name || null,
guest_company: data.guest_company || null,
guest_phone: data.guest_phone || null,
importHash: data.importHash || null, importHash: data.importHash || null,
createdById: currentUser.id, createdById: currentUser.id,
updatedById: currentUser.id, updatedById: currentUser.id,
@ -47,6 +50,9 @@ module.exports = class Booking_requestsDBApi {
start_date: item.start_date || null, start_date: item.start_date || null,
end_date: item.end_date || null, end_date: item.end_date || null,
status: item.status || null, status: item.status || null,
guest_name: item.guest_name || null,
guest_company: item.guest_company || null,
guest_phone: item.guest_phone || null,
importHash: item.importHash || null, importHash: item.importHash || null,
createdById: currentUser.id, createdById: currentUser.id,
updatedById: currentUser.id, updatedById: currentUser.id,
@ -83,6 +89,15 @@ module.exports = class Booking_requestsDBApi {
if (data.status !== undefined) updatePayload.status = data.status; if (data.status !== undefined) updatePayload.status = data.status;
if (data.guest_name !== undefined)
updatePayload.guest_name = data.guest_name;
if (data.guest_company !== undefined)
updatePayload.guest_company = data.guest_company;
if (data.guest_phone !== undefined)
updatePayload.guest_phone = data.guest_phone;
updatePayload.updatedById = currentUser.id; updatePayload.updatedById = currentUser.id;
await booking_requests.update(updatePayload, { transaction }); await booking_requests.update(updatePayload, { transaction });
@ -252,6 +267,39 @@ module.exports = class Booking_requestsDBApi {
}; };
} }
if (filter.guest_name) {
where = {
...where,
[Op.and]: Utils.ilike(
'booking_requests',
'guest_name',
filter.guest_name,
),
};
}
if (filter.guest_company) {
where = {
...where,
[Op.and]: Utils.ilike(
'booking_requests',
'guest_company',
filter.guest_company,
),
};
}
if (filter.guest_phone) {
where = {
...where,
[Op.and]: Utils.ilike(
'booking_requests',
'guest_phone',
filter.guest_phone,
),
};
}
if (filter.calendarStart && filter.calendarEnd) { if (filter.calendarStart && filter.calendarEnd) {
where = { where = {
...where, ...where,

View File

@ -0,0 +1,49 @@
module.exports = {
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async up(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.addColumn(
'booking_requests',
'guest_name',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction },
);
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async down(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.removeColumn('booking_requests', 'guest_name', {
transaction,
});
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};

View File

@ -0,0 +1,49 @@
module.exports = {
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async up(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.addColumn(
'booking_requests',
'guest_company',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction },
);
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async down(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.removeColumn('booking_requests', 'guest_company', {
transaction,
});
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};

View File

@ -0,0 +1,49 @@
module.exports = {
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async up(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.addColumn(
'booking_requests',
'guest_phone',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction },
);
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async down(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.removeColumn('booking_requests', 'guest_phone', {
transaction,
});
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};

View File

@ -28,6 +28,18 @@ module.exports = function (sequelize, DataTypes) {
values: ['Pending', 'Confirmed', 'Rejected'], values: ['Pending', 'Confirmed', 'Rejected'],
}, },
guest_name: {
type: DataTypes.TEXT,
},
guest_company: {
type: DataTypes.TEXT,
},
guest_phone: {
type: DataTypes.TEXT,
},
importHash: { importHash: {
type: DataTypes.STRING(255), type: DataTypes.STRING(255),
allowNull: true, allowNull: true,

View File

@ -15,7 +15,13 @@ const BookingRequestsData = [
end_date: new Date('2023-11-05T11:00:00Z'), end_date: new Date('2023-11-05T11:00:00Z'),
status: 'Rejected', status: 'Confirmed',
guest_name: 'Max von Laue',
guest_company: 'Isaac Newton',
guest_phone: 'B. F. Skinner',
}, },
{ {
@ -28,6 +34,12 @@ const BookingRequestsData = [
end_date: new Date('2023-11-15T11:00:00Z'), end_date: new Date('2023-11-15T11:00:00Z'),
status: 'Pending', status: 'Pending',
guest_name: 'Erwin Schrodinger',
guest_company: 'John Bardeen',
guest_phone: 'John Bardeen',
}, },
{ {
@ -40,6 +52,48 @@ const BookingRequestsData = [
end_date: new Date('2023-11-25T11:00:00Z'), end_date: new Date('2023-11-25T11:00:00Z'),
status: 'Confirmed', status: 'Confirmed',
guest_name: 'Linus Pauling',
guest_company: 'Antoine Laurent Lavoisier',
guest_phone: 'Edwin Hubble',
},
{
// type code here for "relation_one" field
// type code here for "relation_one" field
start_date: new Date('2023-12-01T14:00:00Z'),
end_date: new Date('2023-12-05T11:00:00Z'),
status: 'Rejected',
guest_name: 'Charles Darwin',
guest_company: 'Frederick Sanger',
guest_phone: 'Carl Linnaeus',
},
{
// type code here for "relation_one" field
// type code here for "relation_one" field
start_date: new Date('2023-12-10T14:00:00Z'),
end_date: new Date('2023-12-15T11:00:00Z'),
status: 'Pending',
guest_name: 'Max Delbruck',
guest_company: 'Trofim Lysenko',
guest_phone: 'Louis Victor de Broglie',
}, },
]; ];
@ -49,23 +103,39 @@ const RoomsData = [
room_number: 101, room_number: 101,
bed_type: 'Bed-1',
},
{
block: 'Block 1',
room_number: 102,
bed_type: 'Bed-1',
},
{
block: 'Block 1',
room_number: 102,
bed_type: 'Bed-1',
},
{
block: 'Block 2',
room_number: 201,
bed_type: 'SingleBed', bed_type: 'SingleBed',
}, },
{ {
block: 'Block 1', block: 'Block 2',
room_number: 102, room_number: 201,
bed_type: 'Bed-1', bed_type: 'Bed-2',
},
{
block: 'Block 1',
room_number: 102,
bed_type: 'Bed-1',
}, },
]; ];
@ -104,6 +174,28 @@ async function associateBookingRequestWithGuest() {
if (BookingRequest2?.setGuest) { if (BookingRequest2?.setGuest) {
await BookingRequest2.setGuest(relatedGuest2); await BookingRequest2.setGuest(relatedGuest2);
} }
const relatedGuest3 = await Users.findOne({
offset: Math.floor(Math.random() * (await Users.count())),
});
const BookingRequest3 = await BookingRequests.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (BookingRequest3?.setGuest) {
await BookingRequest3.setGuest(relatedGuest3);
}
const relatedGuest4 = await Users.findOne({
offset: Math.floor(Math.random() * (await Users.count())),
});
const BookingRequest4 = await BookingRequests.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (BookingRequest4?.setGuest) {
await BookingRequest4.setGuest(relatedGuest4);
}
} }
async function associateBookingRequestWithRoom() { async function associateBookingRequestWithRoom() {
@ -139,6 +231,28 @@ async function associateBookingRequestWithRoom() {
if (BookingRequest2?.setRoom) { if (BookingRequest2?.setRoom) {
await BookingRequest2.setRoom(relatedRoom2); await BookingRequest2.setRoom(relatedRoom2);
} }
const relatedRoom3 = await Rooms.findOne({
offset: Math.floor(Math.random() * (await Rooms.count())),
});
const BookingRequest3 = await BookingRequests.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (BookingRequest3?.setRoom) {
await BookingRequest3.setRoom(relatedRoom3);
}
const relatedRoom4 = await Rooms.findOne({
offset: Math.floor(Math.random() * (await Rooms.count())),
});
const BookingRequest4 = await BookingRequests.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (BookingRequest4?.setRoom) {
await BookingRequest4.setRoom(relatedRoom4);
}
} }
module.exports = { module.exports = {

View File

@ -20,6 +20,16 @@ router.use(checkCrudPermissions('booking_requests'));
* type: object * type: object
* properties: * properties:
* guest_name:
* type: string
* default: guest_name
* guest_company:
* type: string
* default: guest_company
* guest_phone:
* type: string
* default: guest_phone
* *
*/ */
@ -307,7 +317,15 @@ router.get(
currentUser, currentUser,
}); });
if (filetype && filetype === 'csv') { if (filetype && filetype === 'csv') {
const fields = ['id', 'start_date', 'end_date']; const fields = [
'id',
'guest_name',
'guest_company',
'guest_phone',
'start_date',
'end_date',
];
const opts = { fields }; const opts = { fields };
try { try {
const csv = parse(payload.rows, opts); const csv = parse(payload.rows, opts);

View File

@ -43,6 +43,8 @@ module.exports = class SearchService {
const tableColumns = { const tableColumns = {
users: ['firstName', 'lastName', 'phoneNumber', 'email'], users: ['firstName', 'lastName', 'phoneNumber', 'email'],
booking_requests: ['guest_name', 'guest_company', 'guest_phone'],
rooms: ['block'], rooms: ['block'],
}; };
const columnsInt = { const columnsInt = {

View File

@ -0,0 +1 @@
{}

View File

@ -129,6 +129,39 @@ const CardBooking_requests = ({
</div> </div>
</dd> </dd>
</div> </div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>
Guest name
</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{item.guest_name}
</div>
</dd>
</div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>
Guest company
</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{item.guest_company}
</div>
</dd>
</div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>
Guest phone
</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{item.guest_phone}
</div>
</dd>
</div>
</dl> </dl>
</li> </li>
))} ))}

View File

@ -86,6 +86,23 @@ const ListBooking_requests = ({
<p className={'text-xs text-gray-500 '}>Status</p> <p className={'text-xs text-gray-500 '}>Status</p>
<p className={'line-clamp-2'}>{item.status}</p> <p className={'line-clamp-2'}>{item.status}</p>
</div> </div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Guest name</p>
<p className={'line-clamp-2'}>{item.guest_name}</p>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>
Guest company
</p>
<p className={'line-clamp-2'}>{item.guest_company}</p>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Guest phone</p>
<p className={'line-clamp-2'}>{item.guest_phone}</p>
</div>
</Link> </Link>
<ListActionsPopover <ListActionsPopover
onDelete={onDelete} onDelete={onDelete}

View File

@ -122,6 +122,42 @@ export const loadColumns = async (
editable: hasUpdatePermission, editable: hasUpdatePermission,
}, },
{
field: 'guest_name',
headerName: 'Guest name',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'guest_company',
headerName: 'Guest company',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'guest_phone',
headerName: 'Guest phone',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{ {
field: 'actions', field: 'actions',
type: 'actions', type: 'actions',

View File

@ -17,7 +17,7 @@ export default function WebSiteFooter({ projectName }: WebSiteFooterProps) {
const borders = useAppSelector((state) => state.style.borders); const borders = useAppSelector((state) => state.style.borders);
const websiteHeder = useAppSelector((state) => state.style.websiteHeder); const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
const style = FooterStyle.WITH_PROJECT_NAME; const style = FooterStyle.WITH_PAGES;
const design = FooterDesigns.DEFAULT_DESIGN; const design = FooterDesigns.DEFAULT_DESIGN;

View File

@ -17,7 +17,7 @@ export default function WebSiteHeader({ projectName }: WebSiteHeaderProps) {
const websiteHeder = useAppSelector((state) => state.style.websiteHeder); const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
const borders = useAppSelector((state) => state.style.borders); const borders = useAppSelector((state) => state.style.borders);
const style = HeaderStyle.PAGES_LEFT; const style = HeaderStyle.PAGES_RIGHT;
const design = HeaderDesigns.DESIGN_DIVERSITY; const design = HeaderDesigns.DESIGN_DIVERSITY;
return ( return (

View File

@ -48,6 +48,12 @@ const EditBooking_requests = () => {
end_date: new Date(), end_date: new Date(),
status: '', status: '',
guest_name: '',
guest_company: '',
guest_phone: '',
}; };
const [initialValues, setInitialValues] = useState(initVals); const [initialValues, setInitialValues] = useState(initVals);
@ -174,6 +180,18 @@ const EditBooking_requests = () => {
</Field> </Field>
</FormField> </FormField>
<FormField label='Guest name'>
<Field name='guest_name' placeholder='Guest name' />
</FormField>
<FormField label='Guest company'>
<Field name='guest_company' placeholder='Guest company' />
</FormField>
<FormField label='Guest phone'>
<Field name='guest_phone' placeholder='Guest phone' />
</FormField>
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type='submit' color='info' label='Submit' /> <BaseButton type='submit' color='info' label='Submit' />

View File

@ -48,6 +48,12 @@ const EditBooking_requestsPage = () => {
end_date: new Date(), end_date: new Date(),
status: '', status: '',
guest_name: '',
guest_company: '',
guest_phone: '',
}; };
const [initialValues, setInitialValues] = useState(initVals); const [initialValues, setInitialValues] = useState(initVals);
@ -172,6 +178,18 @@ const EditBooking_requestsPage = () => {
</Field> </Field>
</FormField> </FormField>
<FormField label='Guest name'>
<Field name='guest_name' placeholder='Guest name' />
</FormField>
<FormField label='Guest company'>
<Field name='guest_company' placeholder='Guest company' />
</FormField>
<FormField label='Guest phone'>
<Field name='guest_phone' placeholder='Guest phone' />
</FormField>
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type='submit' color='info' label='Submit' /> <BaseButton type='submit' color='info' label='Submit' />

View File

@ -32,6 +32,10 @@ const Booking_requestsTablesPage = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const [filters] = useState([ const [filters] = useState([
{ label: 'Guest name', title: 'guest_name' },
{ label: 'Guest company', title: 'guest_company' },
{ label: 'Guest phone', title: 'guest_phone' },
{ label: 'StartDate', title: 'start_date', date: 'true' }, { label: 'StartDate', title: 'start_date', date: 'true' },
{ label: 'EndDate', title: 'end_date', date: 'true' }, { label: 'EndDate', title: 'end_date', date: 'true' },

View File

@ -33,14 +33,11 @@ import { useRouter } from 'next/router';
import moment from 'moment'; import moment from 'moment';
const initialValues = { const initialValues = {
guest: '', guest_name: '',
guest_company: '',
room: '', guest_phone: '',
start_date: '', start_date: '',
end_date: '', end_date: '',
status: 'Pending', status: 'Pending',
}; };
@ -86,25 +83,6 @@ const Booking_requestsNew = () => {
<FormField label='Guest' labelFor='guest'> <FormField label='Guest' labelFor='guest'>
<Field <Field
name='guest' name='guest'
id='guest'
component={SelectField}
options={[]}
itemRef={'users'}
></Field>
</FormField>
<FormField label='Room' labelFor='room'>
<Field
name='room'
id='room'
component={SelectField}
options={[]}
itemRef={'rooms'}
></Field>
</FormField>
<FormField label='StartDate'>
<Field
type='datetime-local' type='datetime-local'
name='start_date' name='start_date'
placeholder='StartDate' placeholder='StartDate'
@ -129,6 +107,18 @@ const Booking_requestsNew = () => {
</Field> </Field>
</FormField> </FormField>
<FormField label='Guest name'>
<Field name='guest_name' placeholder='Guest name' />
</FormField>
<FormField label='Guest company'>
<Field name='guest_company' placeholder='Guest company' />
</FormField>
<FormField label='Guest phone'>
<Field name='guest_phone' placeholder='Guest phone' />
</FormField>
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type='submit' color='info' label='Submit' /> <BaseButton type='submit' color='info' label='Submit' />

View File

@ -32,6 +32,10 @@ const Booking_requestsTablesPage = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const [filters] = useState([ const [filters] = useState([
{ label: 'Guest name', title: 'guest_name' },
{ label: 'Guest company', title: 'guest_company' },
{ label: 'Guest phone', title: 'guest_phone' },
{ label: 'StartDate', title: 'start_date', date: 'true' }, { label: 'StartDate', title: 'start_date', date: 'true' },
{ label: 'EndDate', title: 'end_date', date: 'true' }, { label: 'EndDate', title: 'end_date', date: 'true' },

View File

@ -115,6 +115,21 @@ const Booking_requestsView = () => {
<p>{booking_requests?.status ?? 'No data'}</p> <p>{booking_requests?.status ?? 'No data'}</p>
</div> </div>
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>Guest name</p>
<p>{booking_requests?.guest_name}</p>
</div>
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>Guest company</p>
<p>{booking_requests?.guest_company}</p>
</div>
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>Guest phone</p>
<p>{booking_requests?.guest_phone}</p>
</div>
<BaseDivider /> <BaseDivider />
<BaseButton <BaseButton

View File

@ -136,7 +136,7 @@ export default function WebSite() {
<FeaturesSection <FeaturesSection
projectName={'DDF Guest House Booking'} projectName={'DDF Guest House Booking'}
image={['User-friendly booking interface']} image={['User-friendly booking interface']}
withBg={1} withBg={0}
features={features_points} features={features_points}
mainText={`Discover Key Features of ${projectName}`} mainText={`Discover Key Features of ${projectName}`}
subTitle={`Explore the essential features that make ${projectName} the perfect choice for your guest house booking needs.`} subTitle={`Explore the essential features that make ${projectName} the perfect choice for your guest house booking needs.`}

View File

@ -84,6 +84,12 @@ const RoomsView = () => {
<th>EndDate</th> <th>EndDate</th>
<th>Status</th> <th>Status</th>
<th>Guest name</th>
<th>Guest company</th>
<th>Guest phone</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -107,6 +113,14 @@ const RoomsView = () => {
</td> </td>
<td data-label='status'>{item.status}</td> <td data-label='status'>{item.status}</td>
<td data-label='guest_name'>{item.guest_name}</td>
<td data-label='guest_company'>
{item.guest_company}
</td>
<td data-label='guest_phone'>{item.guest_phone}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>

View File

@ -153,6 +153,12 @@ const UsersView = () => {
<th>EndDate</th> <th>EndDate</th>
<th>Status</th> <th>Status</th>
<th>Guest name</th>
<th>Guest company</th>
<th>Guest phone</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -176,6 +182,14 @@ const UsersView = () => {
</td> </td>
<td data-label='status'>{item.status}</td> <td data-label='status'>{item.status}</td>
<td data-label='guest_name'>{item.guest_name}</td>
<td data-label='guest_company'>
{item.guest_company}
</td>
<td data-label='guest_phone'>{item.guest_phone}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>

View File

@ -74,7 +74,7 @@ export default function WebSite() {
<FeaturesSection <FeaturesSection
projectName={'DDF Guest House Booking'} projectName={'DDF Guest House Booking'}
image={['Service features overview image']} image={['Service features overview image']}
withBg={1} withBg={0}
features={features_points} features={features_points}
mainText={`Unveiling ${projectName} Service Features`} mainText={`Unveiling ${projectName} Service Features`}
subTitle={`Explore the key features that make ${projectName} the ideal choice for managing your guest house bookings efficiently and effortlessly.`} subTitle={`Explore the key features that make ${projectName} the ideal choice for managing your guest house bookings efficiently and effortlessly.`}