Auto commit: 2025-05-24T06:18:04.409Z

This commit is contained in:
Flatlogic Bot 2025-05-24 06:18:04 +00:00
parent e93f945df3
commit 4f42c9d4ed
24 changed files with 675 additions and 173 deletions

File diff suppressed because one or more lines are too long

View File

@ -34,25 +34,6 @@ const config = {
clientId: process.env.MS_CLIENT_ID || '',
clientSecret: process.env.MS_CLIENT_SECRET || '',
},
amadeus: {
clientId: process.env.AMADEUS_CLIENT_ID || 'YnlNGEWG0bMODXXFh59aWczdKy2Abr3l',
clientSecret: process.env.AMADEUS_CLIENT_SECRET || 'YaSiX7mGOu3dhDz6',
baseURL: 'https://test.api.amadeus.com',
},
tap: {
secretKey: process.env.TAP_SECRET_KEY || 'sk_test_XKokBfNWv6FIYuTMg5LPjhJ',
publishableKey: process.env.TAP_PUBLISHABLE_KEY || 'pk_test_EtHFV4BuPQokJT6jiROls87Y',
merchantId: process.env.TAP_MERCHANT_ID || '26374580',
baseURL: 'https://api.tap.company',
successUrl: process.env.TAP_SUCCESS_URL || 'https://flyaru.com/payment-success',
failureUrl: process.env.TAP_FAILURE_URL || 'https://flyaru.com/payment-failed',
webhookUrl: process.env.TAP_WEBHOOK_URL || 'https://flyaru.com/api/webhook',
force3DSecure: true,
capture: 'capture',
refundWindowDays: 30,
},
uploadDir: os.tmpdir(),
email: {
from: 'FlyAru-Powered by Arwa Travel Group <app@flatlogic.app>',

View File

@ -20,6 +20,7 @@ module.exports = class ToursDBApi {
price: data.price || null,
start_date: data.start_date || null,
end_date: data.end_date || null,
image_url: data.image_url || null,
importHash: data.importHash || null,
createdById: currentUser.id,
updatedById: currentUser.id,
@ -51,6 +52,7 @@ module.exports = class ToursDBApi {
price: item.price || null,
start_date: item.start_date || null,
end_date: item.end_date || null,
image_url: item.image_url || null,
importHash: item.importHash || null,
createdById: currentUser.id,
updatedById: currentUser.id,
@ -86,6 +88,8 @@ module.exports = class ToursDBApi {
if (data.end_date !== undefined) updatePayload.end_date = data.end_date;
if (data.image_url !== undefined) updatePayload.image_url = data.image_url;
updatePayload.updatedById = currentUser.id;
await tours.update(updatePayload, { transaction });
@ -171,6 +175,10 @@ module.exports = class ToursDBApi {
transaction,
});
output.cartitem_tour = await tours.getCartitem_tour({
transaction,
});
output.agency = await tours.getAgency({
transaction,
});
@ -237,6 +245,13 @@ module.exports = class ToursDBApi {
};
}
if (filter.image_url) {
where = {
...where,
[Op.and]: Utils.ilike('tours', 'image_url', filter.image_url),
};
}
if (filter.calendarStart && filter.calendarEnd) {
where = {
...where,

View File

@ -0,0 +1,47 @@
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(
'tours',
'image_url',
{
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('tours', 'image_url', { transaction });
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};

View File

@ -0,0 +1,36 @@
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 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 transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};

View File

@ -34,6 +34,10 @@ module.exports = function (sequelize, DataTypes) {
type: DataTypes.DATE,
},
image_url: {
type: DataTypes.TEXT,
},
importHash: {
type: DataTypes.STRING(255),
allowNull: true,
@ -58,6 +62,14 @@ module.exports = function (sequelize, DataTypes) {
constraints: false,
});
db.tours.hasMany(db.cartitem, {
as: 'cartitem_tour',
foreignKey: {
name: 'tourId',
},
constraints: false,
});
//end loop
db.tours.belongsTo(db.agencies, {

View File

@ -11,6 +11,8 @@ const Agencies = db.agencies;
const Cart = db.cart;
const Cartitem = db.cartitem;
const AgentsData = [
{
name: 'Alice Green',
@ -41,16 +43,6 @@ const AgentsData = [
// type code here for "relation_one" field
},
{
name: 'Diana Blue',
commission_rate: 0.08,
// type code here for "relation_one" field
// type code here for "relation_one" field
},
];
const BookingsData = [
@ -73,7 +65,7 @@ const BookingsData = [
booking_date: new Date('2023-12-05T11:00:00Z'),
status: 'confirmed',
status: 'pending',
// type code here for "relation_one" field
},
@ -85,19 +77,7 @@ const BookingsData = [
booking_date: new Date('2023-12-10T12:00:00Z'),
status: 'pending',
// type code here for "relation_one" field
},
{
// type code here for "relation_one" field
// type code here for "relation_one" field
booking_date: new Date('2023-12-15T13:00:00Z'),
status: 'pending',
status: 'confirmed',
// type code here for "relation_one" field
},
@ -118,6 +98,8 @@ const ToursData = [
// type code here for "relation_one" field
// type code here for "relation_one" field
image_url: 'Alfred Wegener',
},
{
@ -134,6 +116,8 @@ const ToursData = [
// type code here for "relation_one" field
// type code here for "relation_one" field
image_url: 'Konrad Lorenz',
},
{
@ -150,22 +134,8 @@ const ToursData = [
// type code here for "relation_one" field
// type code here for "relation_one" field
},
{
title: 'Red Sea Diving Experience',
description: 'Dive into the vibrant underwater world of the Red Sea.',
price: 1000,
start_date: new Date('2024-04-01T09:00:00Z'),
end_date: new Date('2024-04-07T18:00:00Z'),
// type code here for "relation_one" field
// type code here for "relation_one" field
image_url: 'Alfred Kinsey',
},
];
@ -181,31 +151,63 @@ const AgenciesData = [
{
name: 'Adventure Seekers',
},
{
name: 'Cultural Journeys',
},
];
const CartData = [
{
// type code here for "relation_one" field
// type code here for "relation_one" field
// type code here for "relation_one" field
},
{
// type code here for "relation_one" field
// type code here for "relation_one" field
// type code here for "relation_one" field
},
{
// type code here for "relation_one" field
// type code here for "relation_one" field
// type code here for "relation_one" field
},
];
const CartitemData = [
{
// type code here for "relation_one" field
// type code here for "relation_one" field
// type code here for "relation_one" field
quantity: 7,
unitprice: 13.85,
},
{
// type code here for "relation_one" field
// type code here for "relation_one" field
// type code here for "relation_one" field
quantity: 7,
unitprice: 88.36,
},
{
// type code here for "relation_one" field
// type code here for "relation_one" field
// type code here for "relation_one" field
quantity: 4,
unitprice: 36.29,
},
];
@ -244,17 +246,6 @@ async function associateUserWithAgency() {
if (User2?.setAgency) {
await User2.setAgency(relatedAgency2);
}
const relatedAgency3 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const User3 = await Users.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (User3?.setAgency) {
await User3.setAgency(relatedAgency3);
}
}
async function associateAgentWithAgency() {
@ -290,17 +281,6 @@ async function associateAgentWithAgency() {
if (Agent2?.setAgency) {
await Agent2.setAgency(relatedAgency2);
}
const relatedAgency3 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Agent3 = await Agents.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Agent3?.setAgency) {
await Agent3.setAgency(relatedAgency3);
}
}
async function associateAgentWithAgency() {
@ -336,17 +316,6 @@ async function associateAgentWithAgency() {
if (Agent2?.setAgency) {
await Agent2.setAgency(relatedAgency2);
}
const relatedAgency3 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Agent3 = await Agents.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Agent3?.setAgency) {
await Agent3.setAgency(relatedAgency3);
}
}
async function associateBookingWithTour() {
@ -382,17 +351,6 @@ async function associateBookingWithTour() {
if (Booking2?.setTour) {
await Booking2.setTour(relatedTour2);
}
const relatedTour3 = await Tours.findOne({
offset: Math.floor(Math.random() * (await Tours.count())),
});
const Booking3 = await Bookings.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Booking3?.setTour) {
await Booking3.setTour(relatedTour3);
}
}
async function associateBookingWithCustomer() {
@ -428,17 +386,6 @@ async function associateBookingWithCustomer() {
if (Booking2?.setCustomer) {
await Booking2.setCustomer(relatedCustomer2);
}
const relatedCustomer3 = await Users.findOne({
offset: Math.floor(Math.random() * (await Users.count())),
});
const Booking3 = await Bookings.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Booking3?.setCustomer) {
await Booking3.setCustomer(relatedCustomer3);
}
}
async function associateBookingWithAgency() {
@ -474,17 +421,6 @@ async function associateBookingWithAgency() {
if (Booking2?.setAgency) {
await Booking2.setAgency(relatedAgency2);
}
const relatedAgency3 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Booking3 = await Bookings.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Booking3?.setAgency) {
await Booking3.setAgency(relatedAgency3);
}
}
async function associateTourWithAgency() {
@ -520,17 +456,6 @@ async function associateTourWithAgency() {
if (Tour2?.setAgency) {
await Tour2.setAgency(relatedAgency2);
}
const relatedAgency3 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Tour3 = await Tours.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Tour3?.setAgency) {
await Tour3.setAgency(relatedAgency3);
}
}
async function associateTourWithAgency() {
@ -566,17 +491,6 @@ async function associateTourWithAgency() {
if (Tour2?.setAgency) {
await Tour2.setAgency(relatedAgency2);
}
const relatedAgency3 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Tour3 = await Tours.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Tour3?.setAgency) {
await Tour3.setAgency(relatedAgency3);
}
}
async function associateCartWithAgency() {
@ -612,17 +526,6 @@ async function associateCartWithAgency() {
if (Cart2?.setAgency) {
await Cart2.setAgency(relatedAgency2);
}
const relatedAgency3 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Cart3 = await Cart.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Cart3?.setAgency) {
await Cart3.setAgency(relatedAgency3);
}
}
async function associateCartWithUser() {
@ -658,16 +561,145 @@ async function associateCartWithUser() {
if (Cart2?.setUser) {
await Cart2.setUser(relatedUser2);
}
}
const relatedUser3 = await Users.findOne({
offset: Math.floor(Math.random() * (await Users.count())),
async function associateCartWithAgency() {
const relatedAgency0 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Cart3 = await Cart.findOne({
const Cart0 = await Cart.findOne({
order: [['id', 'ASC']],
offset: 3,
offset: 0,
});
if (Cart3?.setUser) {
await Cart3.setUser(relatedUser3);
if (Cart0?.setAgency) {
await Cart0.setAgency(relatedAgency0);
}
const relatedAgency1 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Cart1 = await Cart.findOne({
order: [['id', 'ASC']],
offset: 1,
});
if (Cart1?.setAgency) {
await Cart1.setAgency(relatedAgency1);
}
const relatedAgency2 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Cart2 = await Cart.findOne({
order: [['id', 'ASC']],
offset: 2,
});
if (Cart2?.setAgency) {
await Cart2.setAgency(relatedAgency2);
}
}
async function associateCartitemWithAgency() {
const relatedAgency0 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Cartitem0 = await Cartitem.findOne({
order: [['id', 'ASC']],
offset: 0,
});
if (Cartitem0?.setAgency) {
await Cartitem0.setAgency(relatedAgency0);
}
const relatedAgency1 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Cartitem1 = await Cartitem.findOne({
order: [['id', 'ASC']],
offset: 1,
});
if (Cartitem1?.setAgency) {
await Cartitem1.setAgency(relatedAgency1);
}
const relatedAgency2 = await Agencies.findOne({
offset: Math.floor(Math.random() * (await Agencies.count())),
});
const Cartitem2 = await Cartitem.findOne({
order: [['id', 'ASC']],
offset: 2,
});
if (Cartitem2?.setAgency) {
await Cartitem2.setAgency(relatedAgency2);
}
}
async function associateCartitemWithCart() {
const relatedCart0 = await Cart.findOne({
offset: Math.floor(Math.random() * (await Cart.count())),
});
const Cartitem0 = await Cartitem.findOne({
order: [['id', 'ASC']],
offset: 0,
});
if (Cartitem0?.setCart) {
await Cartitem0.setCart(relatedCart0);
}
const relatedCart1 = await Cart.findOne({
offset: Math.floor(Math.random() * (await Cart.count())),
});
const Cartitem1 = await Cartitem.findOne({
order: [['id', 'ASC']],
offset: 1,
});
if (Cartitem1?.setCart) {
await Cartitem1.setCart(relatedCart1);
}
const relatedCart2 = await Cart.findOne({
offset: Math.floor(Math.random() * (await Cart.count())),
});
const Cartitem2 = await Cartitem.findOne({
order: [['id', 'ASC']],
offset: 2,
});
if (Cartitem2?.setCart) {
await Cartitem2.setCart(relatedCart2);
}
}
async function associateCartitemWithTour() {
const relatedTour0 = await Tours.findOne({
offset: Math.floor(Math.random() * (await Tours.count())),
});
const Cartitem0 = await Cartitem.findOne({
order: [['id', 'ASC']],
offset: 0,
});
if (Cartitem0?.setTour) {
await Cartitem0.setTour(relatedTour0);
}
const relatedTour1 = await Tours.findOne({
offset: Math.floor(Math.random() * (await Tours.count())),
});
const Cartitem1 = await Cartitem.findOne({
order: [['id', 'ASC']],
offset: 1,
});
if (Cartitem1?.setTour) {
await Cartitem1.setTour(relatedTour1);
}
const relatedTour2 = await Tours.findOne({
offset: Math.floor(Math.random() * (await Tours.count())),
});
const Cartitem2 = await Cartitem.findOne({
order: [['id', 'ASC']],
offset: 2,
});
if (Cartitem2?.setTour) {
await Cartitem2.setTour(relatedTour2);
}
}
@ -683,6 +715,8 @@ module.exports = {
await Cart.bulkCreate(CartData);
await Cartitem.bulkCreate(CartitemData);
await Promise.all([
// Similar logic for "relation_many"
@ -705,6 +739,14 @@ module.exports = {
await associateCartWithAgency(),
await associateCartWithUser(),
await associateCartWithAgency(),
await associateCartitemWithAgency(),
await associateCartitemWithCart(),
await associateCartitemWithTour(),
]);
},
@ -718,5 +760,7 @@ module.exports = {
await queryInterface.bulkDelete('agencies', null, {});
await queryInterface.bulkDelete('cart', null, {});
await queryInterface.bulkDelete('cartitem', null, {});
},
};

View File

@ -0,0 +1,75 @@
'use strict';
const { v4: uuidv4 } = require('uuid');
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.bulkInsert('tours', [
{
id: uuidv4(),
title: 'Discover the Mysteries of Thailand',
description: '2 nights in Krabi; 3 nights in Phuket; half-day tour of the Emerald Temple & waterfall; 7-Islands long-tail boat cruise with sunset dinner; half-day Phuket city tour with Big Buddha; Phi Phi Islands Maya Bay & Khai speedboat tour with lunch; all transfers via private boat.',
price: 1881,
start_date: null,
end_date: null,
image_url: 'https://www.arwatravelksa.com/images/pac2.jpeg',
createdAt: new Date(),
updatedAt: new Date(),
},
{
id: uuidv4(),
title: 'Family Adventures in Thailand',
description: 'Discover hidden gems, pristine beaches and vibrant cities while experiencing rich culture and hospitality in the Land of Smiles—designed for 2 adults + 1 child.',
price: 2600,
start_date: null,
end_date: null,
image_url: 'https://www.arwatravelksa.com/images/486033692_960427122968372_1468632099997282977_n.jpg',
createdAt: new Date(),
updatedAt: new Date(),
},
{
id: uuidv4(),
title: 'Turkey Highlights: Trabzon & Istanbul',
description: 'Cruise dinner in Istanbul; Princess Island tour; full-day Uzungöl & tea-factory visit; explore the heart of Trabzon.',
price: 2850,
start_date: null,
end_date: null,
image_url: 'https://www.arwatravelksa.com/images/pac5.jpeg',
createdAt: new Date(),
updatedAt: new Date(),
},
{
id: uuidv4(),
title: 'Turkey Trabzon & Istanbul (English Version)',
description: 'Cruise dinner in Istanbul; Princess Island; full-day Uzungöl tour with tea factory; Heart of Trabzon.',
price: null,
start_date: null,
end_date: null,
image_url: 'https://www.arwatravelksa.com/images/pac3.jpeg',
createdAt: new Date(),
updatedAt: new Date(),
},
{
id: uuidv4(),
title: 'Azerbaijan Explorer',
description: 'Join us for an exciting trip to Qafqaz and Gabala; includes 4-star hotel, daily breakfast, one guided tour and all transport.',
price: null,
start_date: null,
end_date: null,
image_url: 'https://www.arwatravelksa.com/images/pac4.jpeg',
createdAt: new Date(),
updatedAt: new Date(),
}
], {});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.bulkDelete('tours', {
title: [
'Discover the Mysteries of Thailand',
'Family Adventures in Thailand',
'Turkey Highlights: Trabzon & Istanbul',
'Turkey Trabzon & Istanbul (English Version)',
'Azerbaijan Explorer'
]
}, {});
}
};

View File

@ -28,6 +28,9 @@ router.use(checkCrudPermissions('tours'));
* description:
* type: string
* default: description
* image_url:
* type: string
* default: image_url
* price:
* type: integer
@ -316,6 +319,7 @@ router.get(
'id',
'title',
'description',
'image_url',
'price',
'start_date',

View File

@ -45,7 +45,7 @@ module.exports = class SearchService {
agents: ['name'],
tours: ['title', 'description'],
tours: ['title', 'description', 'image_url'],
agencies: ['name'],
};
@ -53,6 +53,8 @@ module.exports = class SearchService {
agents: ['commission_rate'],
tours: ['price'],
cartitem: ['quantity', 'unitprice'],
};
let allFoundRecords = [];

View File

@ -135,6 +135,17 @@ const CardTours = ({
</div>
</dd>
</div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>
Image url
</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{item.image_url}
</div>
</dd>
</div>
</dl>
</li>
))}

View File

@ -88,6 +88,11 @@ const ListTours = ({
{dataFormatter.agenciesOneListFormatter(item.agency)}
</p>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Image url</p>
<p className={'line-clamp-2'}>{item.image_url}</p>
</div>
</Link>
<ListActionsPopover
onDelete={onDelete}

View File

@ -128,6 +128,18 @@ export const loadColumns = async (
params?.value?.id ?? params?.value,
},
{
field: 'image_url',
headerName: 'Image url',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{
field: 'actions',
type: 'actions',

View File

@ -19,7 +19,7 @@ export default function WebSiteFooter({ projectName }: WebSiteFooterProps) {
const style = FooterStyle.WITH_PAGES;
const design = FooterDesigns.DEFAULT_DESIGN;
const design = FooterDesigns.DESIGN_DIVERSITY;
return (
<div

View File

@ -17,9 +17,9 @@ export default function WebSiteHeader({ projectName }: WebSiteHeaderProps) {
const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
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.DEFAULT_DESIGN;
return (
<header id='websiteHeader' className='overflow-hidden'>
<div

View File

@ -0,0 +1,112 @@
import * as icon from '@mdi/js';
import { MenuAsideItem } from './interfaces';
const menuAside: MenuAsideItem[] = [
{
href: '/dashboard',
icon: icon.mdiViewDashboardOutline,
label: 'Dashboard',
},
{
href: '/users/users-list',
label: 'Users',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiAccountGroup ?? icon.mdiTable,
permissions: 'READ_USERS',
},
{
href: '/agents/agents-list',
label: 'Agents',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon:
'mdiAccountTie' in icon
? icon['mdiAccountTie' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_AGENTS',
},
{
href: '/bookings/bookings-list',
label: 'Bookings',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon:
'mdiCalendarCheck' in icon
? icon['mdiCalendarCheck' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_BOOKINGS',
},
{
href: '/tours/tours-list',
label: 'Tours',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon:
'mdiMapMarker' in icon
? icon['mdiMapMarker' as keyof typeof icon]
: icon.mdiTable ?? icon.mdiTable,
{
href: '/flights-search',
label: 'Flights',
icon: icon.mdiAirplane,
},
permissions: 'READ_TOURS',
},
{
href: '/roles/roles-list',
label: 'Roles',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiShieldAccountVariantOutline ?? icon.mdiTable,
permissions: 'READ_ROLES',
},
{
href: '/permissions/permissions-list',
label: 'Permissions',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiShieldAccountOutline ?? icon.mdiTable,
permissions: 'READ_PERMISSIONS',
},
{
href: '/agencies/agencies-list',
label: 'Agencies',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_AGENCIES',
},
{
href: '/cart/cart-list',
label: 'Cart',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_CART',
},
{
href: '/profile',
label: 'Profile',
icon: icon.mdiAccountCircle,
},
{
href: '/home',
label: 'Home page',
icon: icon.mdiHome,
withDevider: true,
},
{
href: '/api-docs',
target: '_blank',
label: 'Swagger API',
icon: icon.mdiFileCode,
permissions: 'READ_API_DOCS',
},
];
export default menuAside;

View File

@ -258,6 +258,8 @@ const AgenciesView = () => {
<th>StartDate</th>
<th>EndDate</th>
<th>Image url</th>
</tr>
</thead>
<tbody>
@ -281,6 +283,8 @@ const AgenciesView = () => {
<td data-label='end_date'>
{dataFormatter.dateTimeFormatter(item.end_date)}
</td>
<td data-label='image_url'>{item.image_url}</td>
</tr>
))}
</tbody>
@ -309,6 +313,8 @@ const AgenciesView = () => {
<th>StartDate</th>
<th>EndDate</th>
<th>Image url</th>
</tr>
</thead>
<tbody>
@ -332,6 +338,8 @@ const AgenciesView = () => {
<td data-label='end_date'>
{dataFormatter.dateTimeFormatter(item.end_date)}
</td>
<td data-label='image_url'>{item.image_url}</td>
</tr>
))}
</tbody>
@ -374,6 +382,78 @@ const AgenciesView = () => {
</CardBox>
</>
<>
<p className={'block font-bold mb-2'}>Cart Agency</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
>
<div className='overflow-x-auto'>
<table>
<thead>
<tr></tr>
</thead>
<tbody>
{agencies.cart_agency &&
Array.isArray(agencies.cart_agency) &&
agencies.cart_agency.map((item: any) => (
<tr
key={item.id}
onClick={() =>
router.push(`/cart/cart-view/?id=${item.id}`)
}
></tr>
))}
</tbody>
</table>
</div>
{!agencies?.cart_agency?.length && (
<div className={'text-center py-4'}>No data</div>
)}
</CardBox>
</>
<>
<p className={'block font-bold mb-2'}>Cartitem agencies</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
>
<div className='overflow-x-auto'>
<table>
<thead>
<tr>
<th>Quantity</th>
<th>Unitprice</th>
</tr>
</thead>
<tbody>
{agencies.cartitem_agencies &&
Array.isArray(agencies.cartitem_agencies) &&
agencies.cartitem_agencies.map((item: any) => (
<tr
key={item.id}
onClick={() =>
router.push(
`/cartitem/cartitem-view/?id=${item.id}`,
)
}
>
<td data-label='quantity'>{item.quantity}</td>
<td data-label='unitprice'>{item.unitprice}</td>
</tr>
))}
</tbody>
</table>
</div>
{!agencies?.cartitem_agencies?.length && (
<div className={'text-center py-4'}>No data</div>
)}
</CardBox>
</>
<BaseDivider />
<BaseButton

View File

@ -51,6 +51,8 @@ const EditTours = () => {
agency: null,
agencies: null,
image_url: '',
};
const [initialValues, setInitialValues] = useState(initVals);
@ -181,6 +183,10 @@ const EditTours = () => {
></Field>
</FormField>
<FormField label='Image url'>
<Field name='image_url' placeholder='Image url' />
</FormField>
<BaseDivider />
<BaseButtons>
<BaseButton type='submit' color='info' label='Submit' />

View File

@ -51,6 +51,8 @@ const EditToursPage = () => {
agency: null,
agencies: null,
image_url: '',
};
const [initialValues, setInitialValues] = useState(initVals);
@ -179,6 +181,10 @@ const EditToursPage = () => {
></Field>
</FormField>
<FormField label='Image url'>
<Field name='image_url' placeholder='Image url' />
</FormField>
<BaseDivider />
<BaseButtons>
<BaseButton type='submit' color='info' label='Submit' />

View File

@ -31,6 +31,7 @@ const ToursTablesPage = () => {
const [filters] = useState([
{ label: 'TourTitle', title: 'title' },
{ label: 'Description', title: 'description' },
{ label: 'Image url', title: 'image_url' },
{ label: 'Price', title: 'price', number: 'true' },
{ label: 'StartDate', title: 'start_date', date: 'true' },

View File

@ -46,6 +46,8 @@ const initialValues = {
agency: '',
agencies: '',
image_url: '',
};
const ToursNew = () => {
@ -139,6 +141,10 @@ const ToursNew = () => {
></Field>
</FormField>
<FormField label='Image url'>
<Field name='image_url' placeholder='Image url' />
</FormField>
<BaseDivider />
<BaseButtons>
<BaseButton type='submit' color='info' label='Submit' />

View File

@ -31,6 +31,7 @@ const ToursTablesPage = () => {
const [filters] = useState([
{ label: 'TourTitle', title: 'title' },
{ label: 'Description', title: 'description' },
{ label: 'Image url', title: 'image_url' },
{ label: 'Price', title: 'price', number: 'true' },
{ label: 'StartDate', title: 'start_date', date: 'true' },

View File

@ -125,6 +125,11 @@ const ToursView = () => {
<p>{tours?.agencies?.name ?? 'No data'}</p>
</div>
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>Image url</p>
<p>{tours?.image_url}</p>
</div>
<>
<p className={'block font-bold mb-2'}>Bookings Tour</p>
<CardBox
@ -168,6 +173,47 @@ const ToursView = () => {
</CardBox>
</>
<>
<p className={'block font-bold mb-2'}>Cartitem Tour</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
>
<div className='overflow-x-auto'>
<table>
<thead>
<tr>
<th>Quantity</th>
<th>Unitprice</th>
</tr>
</thead>
<tbody>
{tours.cartitem_tour &&
Array.isArray(tours.cartitem_tour) &&
tours.cartitem_tour.map((item: any) => (
<tr
key={item.id}
onClick={() =>
router.push(
`/cartitem/cartitem-view/?id=${item.id}`,
)
}
>
<td data-label='quantity'>{item.quantity}</td>
<td data-label='unitprice'>{item.unitprice}</td>
</tr>
))}
</tbody>
</table>
</div>
{!tours?.cartitem_tour?.length && (
<div className={'text-center py-4'}>No data</div>
)}
</CardBox>
</>
<BaseDivider />
<BaseButton

View File

@ -142,7 +142,7 @@ export default function WebSite() {
<FeaturesSection
projectName={'FlyAru-Powered by Arwa Travel Group'}
image={['Iconic travel destinations collage']}
withBg={1}
withBg={0}
features={features_points}
mainText={`Explore ${projectName} Features`}
subTitle={`Discover the unique features of ${projectName} that make your travel planning seamless and enjoyable.`}