Compare commits
No commits in common. "00ad62f9163ee126e38706643bc2769876ca4e23" and "96711af5bcaa1e87f9a2fbe7b5753859fef23aa3" have entirely different histories.
00ad62f916
...
96711af5bc
Binary file not shown.
|
Before Width: | Height: | Size: 51 KiB |
@ -390,18 +390,25 @@ module.exports = class EventsDBApi {
|
|||||||
|
|
||||||
if (filter.start_datetimeRange) {
|
if (filter.start_datetimeRange) {
|
||||||
const [start, end] = filter.start_datetimeRange;
|
const [start, end] = filter.start_datetimeRange;
|
||||||
const rangeCondition = {};
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
if (start !== undefined && start !== null && start !== '') {
|
||||||
rangeCondition[Op.gte] = start;
|
where = {
|
||||||
|
...where,
|
||||||
|
start_datetime: {
|
||||||
|
...where.start_datetime,
|
||||||
|
[Op.gte]: start,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
if (end !== undefined && end !== null && end !== '') {
|
||||||
rangeCondition[Op.lte] = end;
|
where = {
|
||||||
}
|
...where,
|
||||||
|
start_datetime: {
|
||||||
if (Object.keys(rangeCondition).length > 0) {
|
...where.start_datetime,
|
||||||
where.start_datetime = { ...where.start_datetime, ...rangeCondition };
|
[Op.lte]: end,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,14 +533,6 @@ module.exports = class EventsDBApi {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
if (currentUser && currentUser.organizationId && (!currentUser.app_role || !currentUser.app_role.globalAccess)) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
organizationId: currentUser.organizationId,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryOptions = {
|
const queryOptions = {
|
||||||
where,
|
where,
|
||||||
include,
|
include,
|
||||||
@ -542,6 +541,7 @@ module.exports = class EventsDBApi {
|
|||||||
? [[filter.field, filter.sort]]
|
? [[filter.field, filter.sort]]
|
||||||
: [['createdAt', 'desc']],
|
: [['createdAt', 'desc']],
|
||||||
transaction: options?.transaction,
|
transaction: options?.transaction,
|
||||||
|
logging: console.log
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
if (!options?.countOnly) {
|
||||||
|
|||||||
@ -15,11 +15,422 @@ const {
|
|||||||
checkCrudPermissions,
|
checkCrudPermissions,
|
||||||
} = require('../middlewares/check-permissions');
|
} = require('../middlewares/check-permissions');
|
||||||
|
|
||||||
router.get('/public', wrapAsync(async (req, res) => {
|
router.use(checkCrudPermissions('events'));
|
||||||
const payload = await EventsDBApi.findAll(req.query);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* components:
|
||||||
|
* schemas:
|
||||||
|
* Events:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
|
||||||
|
* name:
|
||||||
|
* type: string
|
||||||
|
* default: name
|
||||||
|
* description:
|
||||||
|
* type: string
|
||||||
|
* default: description
|
||||||
|
|
||||||
|
|
||||||
|
* budget_total:
|
||||||
|
* type: integer
|
||||||
|
* format: int64
|
||||||
|
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* tags:
|
||||||
|
* name: Events
|
||||||
|
* description: The Events managing API
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/events:
|
||||||
|
* post:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Events]
|
||||||
|
* summary: Add new item
|
||||||
|
* description: Add new item
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* description: Data of the updated item
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully added
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 405:
|
||||||
|
* description: Invalid input data
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
router.post('/', wrapAsync(async (req, res) => {
|
||||||
|
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
||||||
|
const link = new URL(referer);
|
||||||
|
await EventsService.create(req.body.data, req.currentUser, true, link.host);
|
||||||
|
const payload = true;
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/budgets/bulk-import:
|
||||||
|
* post:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Events]
|
||||||
|
* summary: Bulk import items
|
||||||
|
* description: Bulk import items
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* description: Data of the updated items
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The items were successfully imported
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 405:
|
||||||
|
* description: Invalid input data
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
||||||
|
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
||||||
|
const link = new URL(referer);
|
||||||
|
await EventsService.bulkImport(req, res, true, link.host);
|
||||||
|
const payload = true;
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/events/{id}:
|
||||||
|
* put:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Events]
|
||||||
|
* summary: Update the data of the selected item
|
||||||
|
* description: Update the data of the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* description: Item ID to update
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* requestBody:
|
||||||
|
* description: Set new item data
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* id:
|
||||||
|
* description: ID of the updated item
|
||||||
|
* type: string
|
||||||
|
* data:
|
||||||
|
* description: Data of the updated item
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* required:
|
||||||
|
* - id
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item data was successfully updated
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* 400:
|
||||||
|
* description: Invalid ID supplied
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
router.put('/:id', wrapAsync(async (req, res) => {
|
||||||
|
await EventsService.update(req.body.data, req.body.id, req.currentUser);
|
||||||
|
const payload = true;
|
||||||
res.status(200).send(payload);
|
res.status(200).send(payload);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
router.use(checkCrudPermissions('events'));
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/events/{id}:
|
||||||
|
* delete:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Events]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* description: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* description: Item ID to delete
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* 400:
|
||||||
|
* description: Invalid ID supplied
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
router.delete('/:id', wrapAsync(async (req, res) => {
|
||||||
|
await EventsService.remove(req.params.id, req.currentUser);
|
||||||
|
const payload = true;
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/events/deleteByIds:
|
||||||
|
* post:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Events]
|
||||||
|
* summary: Delete the selected item list
|
||||||
|
* description: Delete the selected item list
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* ids:
|
||||||
|
* description: IDs of the updated items
|
||||||
|
* type: array
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The items was successfully deleted
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Items not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
||||||
|
await EventsService.deleteByIds(req.body.data, req.currentUser);
|
||||||
|
const payload = true;
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/events:
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Events]
|
||||||
|
* summary: Get all events
|
||||||
|
* description: Get all events
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Events list successfully received
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Data not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
router.get('/', wrapAsync(async (req, res) => {
|
||||||
|
const filetype = req.query.filetype
|
||||||
|
|
||||||
|
const currentUser = req.currentUser;
|
||||||
|
const payload = await EventsDBApi.findAll(
|
||||||
|
req.query, { currentUser }
|
||||||
|
);
|
||||||
|
if (filetype && filetype === 'csv') {
|
||||||
|
const fields = ['id','name','description',
|
||||||
|
|
||||||
|
'budget_total',
|
||||||
|
'start_datetime','end_datetime',
|
||||||
|
];
|
||||||
|
const opts = { fields };
|
||||||
|
try {
|
||||||
|
const csv = parse(payload.rows, opts);
|
||||||
|
res.status(200).attachment(csv);
|
||||||
|
res.send(csv)
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/events/count:
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Events]
|
||||||
|
* summary: Count all events
|
||||||
|
* description: Count all events
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Events count successfully received
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Data not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
router.get('/count', wrapAsync(async (req, res) => {
|
||||||
|
|
||||||
|
const currentUser = req.currentUser;
|
||||||
|
const payload = await EventsDBApi.findAll(
|
||||||
|
req.query,
|
||||||
|
null,
|
||||||
|
{ countOnly: true, currentUser }
|
||||||
|
);
|
||||||
|
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/events/autocomplete:
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Events]
|
||||||
|
* summary: Find all events that match search criteria
|
||||||
|
* description: Find all events that match search criteria
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Events list successfully received
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Data not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
router.get('/autocomplete', async (req, res) => {
|
||||||
|
|
||||||
|
const payload = await EventsDBApi.findAllAutocomplete(
|
||||||
|
req.query.query,
|
||||||
|
req.query.limit,
|
||||||
|
req.query.offset,
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
res.status(200).send(payload);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/events/{id}:
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Events]
|
||||||
|
* summary: Get selected item
|
||||||
|
* description: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* description: ID of item to get
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/components/schemas/Events"
|
||||||
|
* 400:
|
||||||
|
* description: Invalid ID supplied
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
router.get('/:id', wrapAsync(async (req, res) => {
|
||||||
|
const payload = await EventsDBApi.findBy(
|
||||||
|
{ id: req.params.id },
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.use('/', require('../helpers').commonErrorHandler);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 51 KiB |
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { Event } from '../../interfaces/event';
|
|
||||||
|
|
||||||
const EventCard = ({ event }: { event: Event }) => {
|
|
||||||
const { name, description, start_datetime } = event;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="bg-white rounded-lg shadow-lg overflow-hidden transform hover:scale-105 transition-transform duration-300">
|
|
||||||
<div className="p-6">
|
|
||||||
<h3 className="text-xl font-semibold mb-2">{name}</h3>
|
|
||||||
<p className="text-gray-600 mb-4">{description}</p>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
{new Date(start_datetime).toLocaleDateString('en-US', {
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric',
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EventCard;
|
|
||||||
@ -46,7 +46,7 @@ const InteractiveBackground = () => {
|
|||||||
default: 'bounce',
|
default: 'bounce',
|
||||||
},
|
},
|
||||||
random: false,
|
random: false,
|
||||||
speed: 0.5,
|
speed: 2,
|
||||||
straight: false,
|
straight: false,
|
||||||
},
|
},
|
||||||
number: {
|
number: {
|
||||||
|
|||||||
@ -7,11 +7,6 @@ const menuAside: MenuAsideItem[] = [
|
|||||||
icon: icon.mdiViewDashboardOutline,
|
icon: icon.mdiViewDashboardOutline,
|
||||||
label: 'Dashboard',
|
label: 'Dashboard',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
href: '/public-events',
|
|
||||||
icon: icon.mdiCalendar,
|
|
||||||
label: 'Public Events',
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
href: '/users/users-list',
|
href: '/users/users-list',
|
||||||
|
|||||||
@ -23,7 +23,7 @@ const Dashboard = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(hasPermission(currentUser, 'READ_EVENTS')) {
|
if(hasPermission(currentUser, 'READ_EVENTS')) {
|
||||||
dispatch(fetchEvents({ query: '?sort=start_datetime,ASC&limit=5' }));
|
dispatch(fetchEvents({ query: '?sort=createdAt,DESC&limit=5' }));
|
||||||
}
|
}
|
||||||
if(hasPermission(currentUser, 'READ_GUESTS')) {
|
if(hasPermission(currentUser, 'READ_GUESTS')) {
|
||||||
dispatch(fetchGuests({ query: '' }));
|
dispatch(fetchGuests({ query: '' }));
|
||||||
@ -31,7 +31,7 @@ const Dashboard = () => {
|
|||||||
}, [dispatch, currentUser]);
|
}, [dispatch, currentUser]);
|
||||||
|
|
||||||
const upcomingEvents = events.filter(
|
const upcomingEvents = events.filter(
|
||||||
(event) => new Date(event.start_datetime) > new Date()
|
(event) => new Date(event.date) > new Date()
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -97,18 +97,18 @@ const Dashboard = () => {
|
|||||||
<tr key={event.id}>
|
<tr key={event.id}>
|
||||||
<td className="px-6 py-4 whitespace-nowrap">{event.name}</td>
|
<td className="px-6 py-4 whitespace-nowrap">{event.name}</td>
|
||||||
<td className="px-6 py-4 whitespace-nowrap">
|
<td className="px-6 py-4 whitespace-nowrap">
|
||||||
{new Date(event.start_datetime).toLocaleDateString()}
|
{new Date(event.date).toLocaleDateString()}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4 whitespace-nowrap">{event.location}</td>
|
<td className="px-6 py-4 whitespace-nowrap">{event.location}</td>
|
||||||
<td className="px-6 py-4 whitespace-nowrap">
|
<td className="px-6 py-4 whitespace-nowrap">
|
||||||
<span
|
<span
|
||||||
className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${
|
className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${
|
||||||
new Date(event.start_datetime) < new Date()
|
new Date(event.date) < new Date()
|
||||||
? 'bg-red-100 text-red-800'
|
? 'bg-red-100 text-red-800'
|
||||||
: 'bg-green-100 text-green-800'
|
: 'bg-green-100 text-green-800'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{new Date(event.start_datetime) < new Date() ? 'Past' : 'Upcoming'}
|
{new Date(event.date) < new Date() ? 'Past' : 'Upcoming'}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||||
|
|||||||
@ -1,15 +1,12 @@
|
|||||||
|
|
||||||
import React, { useState, useEffect } from 'react';
|
import React from 'react';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import axios from 'axios';
|
|
||||||
import BaseButton from '../components/BaseButton';
|
import BaseButton from '../components/BaseButton';
|
||||||
import LayoutGuest from '../layouts/Guest';
|
import LayoutGuest from '../layouts/Guest';
|
||||||
import { getPageTitle } from '../config';
|
import { getPageTitle } from '../config';
|
||||||
import SectionTitle from '../components/SectionTitle';
|
import SectionTitle from '../components/SectionTitle';
|
||||||
import EventCard from '../components/Events/EventCard';
|
|
||||||
import { Event } from '../interfaces/event';
|
|
||||||
|
|
||||||
const Feature = ({ icon, title, text }) => (
|
const Feature = ({ icon, title, text }) => (
|
||||||
<div className="p-6 text-center bg-white rounded-lg shadow-lg border border-gray-200">
|
<div className="p-6 text-center bg-white rounded-lg shadow-lg border border-gray-200">
|
||||||
@ -21,24 +18,6 @@ const Feature = ({ icon, title, text }) => (
|
|||||||
|
|
||||||
export default function LandingPage() {
|
export default function LandingPage() {
|
||||||
const title = 'EventCoord Hub'
|
const title = 'EventCoord Hub'
|
||||||
const [events, setEvents] = useState<Event[]>([]);
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [error, setError] = useState(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const fetchEvents = async () => {
|
|
||||||
try {
|
|
||||||
const response = await axios.get(`/api/events/public`);
|
|
||||||
setEvents(response.data.rows);
|
|
||||||
setLoading(false);
|
|
||||||
} catch (err) {
|
|
||||||
setError(err);
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchEvents();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-gray-800">
|
<div className="text-gray-800">
|
||||||
@ -100,34 +79,6 @@ export default function LandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Upcoming Events Section */}
|
|
||||||
<section className="py-20 bg-gray-50">
|
|
||||||
<div className="container mx-auto px-6">
|
|
||||||
<h2 className="text-4xl font-bold text-center mb-12">Upcoming Events</h2>
|
|
||||||
{loading && <p className="text-center">Loading events...</p>}
|
|
||||||
{error && <p className="text-center text-red-500">Error loading events. Please try again later.</p>}
|
|
||||||
{!loading && !error && (
|
|
||||||
<>
|
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8 mt-12">
|
|
||||||
{events.map((event) => (
|
|
||||||
<EventCard key={event.id} event={event} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="text-center mt-12">
|
|
||||||
<BaseButton
|
|
||||||
href="/public-events"
|
|
||||||
label="View All Events"
|
|
||||||
color="info"
|
|
||||||
outline
|
|
||||||
roundedFull
|
|
||||||
className="px-8 py-3 text-lg"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<footer className='text-black'>
|
<footer className='text-black'>
|
||||||
<div className='container mx-auto px-6 py-8 flex flex-col md:flex-row justify-between items-center'>
|
<div className='container mx-auto px-6 py-8 flex flex-col md:flex-row justify-between items-center'>
|
||||||
|
|||||||
@ -1,38 +0,0 @@
|
|||||||
import { useState, useEffect } from 'react'
|
|
||||||
import axios from 'axios'
|
|
||||||
import LayoutGuest from '../layouts/Guest'
|
|
||||||
|
|
||||||
const PublicEventsPage = () => {
|
|
||||||
const [events, setEvents] = useState([])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const fetchEvents = async () => {
|
|
||||||
try {
|
|
||||||
const response = await axios.get('/api/events/public')
|
|
||||||
setEvents(response.data.rows)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching events:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchEvents()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LayoutGuest>
|
|
||||||
<div className="container mx-auto py-8">
|
|
||||||
<h1 className="text-3xl font-bold mb-4">Public Events</h1>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
||||||
{events.map((event: any) => (
|
|
||||||
<div key={event.id} className="border rounded-lg p-4">
|
|
||||||
<h2 className="text-xl font-bold">{event.name}</h2>
|
|
||||||
<p>{event.description}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</LayoutGuest>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PublicEventsPage
|
|
||||||
Loading…
x
Reference in New Issue
Block a user