| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- const { div, h2, p, section, button, form, img, textarea, a, br, h1, span } = require("../server/node_modules/hyperaxe");
- const { template, i18n, userLink} = require('./main_views');
- const moment = require('../server/node_modules/moment');
- const { config } = require('../server/SSB_server.js');
- const userId = config.keys.id;
- const renderCardField = (labelText, value) =>
- div({ class: 'card-field' },
- span({ class: 'card-label' }, labelText),
- span(
- { class: 'card-value' },
- ...(Array.isArray(value) ? value : [value ?? ''])
- )
- );
- function getViewDetailsAction(item) {
- switch (item.type) {
- case 'transfer': return `/transfers/${encodeURIComponent(item.id)}`;
- case 'tribe': return `/tribe/${encodeURIComponent(item.id)}`;
- case 'event': return `/events/${encodeURIComponent(item.id)}`;
- case 'task': return `/tasks/${encodeURIComponent(item.id)}`;
- case 'market': return `/market/${encodeURIComponent(item.id)}`;
- case 'report': return `/reports/${encodeURIComponent(item.id)}`;
- case 'job': return `/jobs/${encodeURIComponent(item.id)}`;
- case 'project': return `/projects/${encodeURIComponent(item.id)}`;
- case 'calendar': return `/calendars/${encodeURIComponent(item.id)}`;
- default: return `/messages/${encodeURIComponent(item.id)}`;
- }
- }
- const renderAgendaItem = (item, userId, filter) => {
- const fmt = d => moment(d).format('YYYY/MM/DD HH:mm:ss');
- const author = item.seller || item.organizer || item.from || item.author || '';
- const commonFields = [
- p({ class: 'card-footer' },
- span({ class: 'date-link' }, `${item.createdAt ? moment(item.createdAt).format('YYYY/MM/DD HH:mm:ss') : ''} ${i18n.performed} `),
- author ? userLink(author) : ''
- )
- ];
- let details = [];
- let actionButton = null;
- if (filter === 'discarded') {
- actionButton = form({ method: 'POST', action: `/agenda/restore/${encodeURIComponent(item.id)}` },
- button({ type: 'submit', class: 'restore-btn' }, i18n.agendaRestoreButton)
- );
- } else {
- actionButton = form({ method: 'POST', action: `/agenda/discard/${encodeURIComponent(item.id)}` },
- button({ type: 'submit', class: 'discard-btn' }, i18n.agendaDiscardButton)
- );
- }
- if (item.type === 'market') {
- details = [
- renderCardField(i18n.marketItemType + ":", String(item.item_type || '').toUpperCase()),
- renderCardField(i18n.marketItemStatus + ":", item.status),
- renderCardField(i18n.marketItemStock + ":", item.stock),
- renderCardField(i18n.marketItemPrice + ":", `${item.price} ECO`),
- renderCardField(i18n.marketItemIncludesShipping + ":", item.includesShipping ? i18n.agendaYes : i18n.agendaNo),
- renderCardField(i18n.deadline + ":", item.deadline ? new Date(item.deadline).toLocaleString() : '')
- ];
- if (String(item.item_type || '').toLowerCase() === 'auction') {
- const bids = Array.isArray(item.auctions_poll) ? item.auctions_poll.map(bid => parseFloat(String(bid).split(':')[1])).filter(n => !isNaN(n)) : [];
- const maxBid = bids.length ? Math.max(...bids) : 0;
- details.push(renderCardField(i18n.marketItemHighestBid + ":", `${maxBid} ECO`));
- }
- const seller = author ? p(userLink(author)) : '';
- details.push(br(), div({ class: 'members-list' }, i18n.marketItemSeller + ': ', seller));
- }
- if (item.type === 'tribe') {
- details = [
- renderCardField(i18n.agendaAnonymousLabel + ":", item.isAnonymous ? i18n.agendaYes : i18n.agendaNo),
- renderCardField(i18n.agendaInviteModeLabel + ":", (item.inviteMode ? String(item.inviteMode).toUpperCase() : i18n.noInviteMode)),
- renderCardField(i18n.agendaLARPLabel + ":", item.isLARP ? i18n.agendaYes : i18n.agendaNo),
- renderCardField(i18n.agendaLocationLabel + ":", item.location || i18n.noLocation),
- renderCardField(i18n.agendaMembersCount + ":", Array.isArray(item.members) ? item.members.length : 0),
- br()
- ];
- const membersList = Array.isArray(item.members) ? item.members.map(member => p(userLink(member))) : [];
- details.push(div({ class: 'members-list' }, `${i18n.agendaMembersLabel}:`, membersList));
- }
- if (item.type === 'report') {
- details = [
- renderCardField(i18n.agendareportStatus + ":", item.status || i18n.noStatus),
- renderCardField(i18n.agendareportCategory + ":", item.category || i18n.noCategory),
- renderCardField(i18n.agendareportSeverity + ":", (item.severity ? String(item.severity).toUpperCase() : i18n.noSeverity))
- ];
- }
- if (item.type === 'event') {
- details = [
- renderCardField(i18n.eventDateLabel + ":", item.date ? fmt(item.date) : ''),
- renderCardField(i18n.eventLocationLabel + ":", item.location || ''),
- renderCardField(i18n.eventPriceLabel + ":", `${item.price} ECO`),
- renderCardField(
- i18n.eventUrlLabel + ":",
- item.url ? p(a({ href: item.url, target: "_blank" }, item.url)) : p(i18n.noUrl)
- )
- ];
- actionButton = actionButton || form({ method: 'POST', action: `/events/attend/${encodeURIComponent(item.id)}` },
- button({ type: 'submit', class: 'assign-btn' }, `${i18n.eventAttendButton}`)
- );
- }
- if (item.type === 'task') {
- details = [
- renderCardField(i18n.taskStatus + ":", item.status),
- renderCardField(i18n.taskPriorityLabel + ":", item.priority),
- renderCardField(i18n.taskStartTimeLabel + ":", item.startTime ? new Date(item.startTime).toLocaleString() : ''),
- renderCardField(i18n.taskEndTimeLabel + ":", item.endTime ? new Date(item.endTime).toLocaleString() : ''),
- renderCardField(i18n.taskLocationLabel + ":", item.location || '')
- ];
- const assigned = Array.isArray(item.assignees) && item.assignees.includes(userId);
- actionButton = actionButton || form({ method: 'POST', action: `/tasks/assign/${encodeURIComponent(item.id)}` },
- button({ type: 'submit', class: 'assign-btn' }, assigned ? i18n.taskUnassignButton : i18n.taskAssignButton)
- );
- }
- if (item.type === 'transfer') {
- details = [
- renderCardField(i18n.agendaTransferConcept + ":", item.concept),
- renderCardField(i18n.agendaTransferAmount + ":", item.amount),
- renderCardField(i18n.agendaTransferDeadline + ":", item.deadline ? fmt(item.deadline) : ''),
- br()
- ];
- const membersList = item.to ? p(userLink(item.to)) : '';
- details.push(div({ class: 'members-list' }, i18n.to + ': ', membersList));
- }
-
- if (item.type === 'project') {
- details = [
- renderCardField(i18n.projectStatus + ":", item.status || i18n.noStatus),
- renderCardField(i18n.projectProgress + ":", `${item.progress || 0}%`),
- renderCardField(i18n.projectGoal + ":", `${item.goal} ECO`),
- renderCardField(i18n.projectPledged + ":", `${item.pledged || 0} ECO`),
- renderCardField(i18n.projectDeadline + ":", item.deadline ? new Date(item.deadline).toLocaleString() : i18n.noDeadline)
- ];
- }
- if (item.type === 'calendar') {
- details = [
- renderCardField((i18n.calendarStatusLabel || 'Status') + ':', item.isClosed ? (i18n.calendarStatusClosed || 'CLOSED') : (i18n.calendarStatusOpen || 'OPEN')),
- renderCardField((i18n.calendarDeadlineLabel || 'Deadline') + ':', item.deadline ? moment(item.deadline).format('YYYY/MM/DD HH:mm') : ''),
- renderCardField((i18n.calendarParticipantsLabel || 'Participants') + ':', Array.isArray(item.participants) ? item.participants.length : 0)
- ];
- }
- if (item.type === 'job') {
- const subs = Array.isArray(item.subscribers)
- ? item.subscribers
- : (typeof item.subscribers === 'string'
- ? item.subscribers.split(',').map(s => s.trim()).filter(Boolean)
- : (item.subscribers && typeof item.subscribers.length === 'number'
- ? Array.from(item.subscribers)
- : []));
- const subsInterleaved = subs
- .map((id, i) => [i > 0 ? ', ' : '', userLink(id)])
- .flat();
- details = [
- renderCardField(i18n.jobStatus + ":", item.status),
- renderCardField(i18n.jobLocation + ":", (item.location || '').toUpperCase()),
- renderCardField(i18n.jobType + ":", (item.job_type || '').toUpperCase()),
- renderCardField(i18n.jobSalary + ":", `${item.salary} ECO`),
- renderCardField(i18n.jobVacants + ":", item.vacants),
- renderCardField(i18n.jobLanguages + ":", (item.languages || '').toUpperCase()),
- br(),
- div(
- { class: 'members-list' },
- i18n.jobSubscribers + ': ',br(),br(),
- ...(subs.length ? subsInterleaved : [i18n.noSubscribers.toUpperCase()])
- ),
- ];
- const subscribed = subs.includes(userId);
- if (!subscribed && String(item.status).toUpperCase() !== 'CLOSED' && item.author !== userId) {
- actionButton = form({ method: 'GET', action: `/jobs/subscribe/${encodeURIComponent(item.id)}` },
- button({ type: 'submit', class: 'subscribe-btn' }, i18n.jobSubscribeButton)
- );
- }
- }
- return div({ class: 'agenda-item card' },
- h2(`[${String(item.type || '').toUpperCase()}] ${item.title || item.name || item.concept || ''}`),
- form({ method: "GET", action: getViewDetailsAction(item) },
- button({ type: "submit", class: "filter-btn" }, i18n.viewDetails)
- ),
- actionButton,
- br(),
- ...details,
- br(),
- ...commonFields
- );
- };
- exports.agendaView = async (data, filter) => {
- const { items = [], counts: _c = {} } = data || {};
- const counts = { all: 0, open: 0, closed: 0, events: 0, tasks: 0, reports: 0, tribes: 0, jobs: 0, market: 0, projects: 0, transfers: 0, calendars: 0, discarded: 0, ..._c };
- return template(
- i18n.agendaTitle,
- section(
- div({ class: 'tags-header' },
- h2(i18n.agendaTitle),
- p(i18n.agendaDescription)
- ),
- div({ class: 'filters' },
- form({ method: 'GET', action: '/agenda' },
- button({ type: 'submit', name: 'filter', value: 'all', class: filter === 'all' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterAll} (${counts.all})`),
- button({ type: 'submit', name: 'filter', value: 'open', class: filter === 'open' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterOpen} (${counts.open})`),
- button({ type: 'submit', name: 'filter', value: 'closed', class: filter === 'closed' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterClosed} (${counts.closed})`),
- button({ type: 'submit', name: 'filter', value: 'events', class: filter === 'events' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterEvents} (${counts.events})`),
- button({ type: 'submit', name: 'filter', value: 'tasks', class: filter === 'tasks' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterTasks} (${counts.tasks})`),
- button({ type: 'submit', name: 'filter', value: 'reports', class: filter === 'reports' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterReports} (${counts.reports})`),
- button({ type: 'submit', name: 'filter', value: 'tribes', class: filter === 'tribes' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterTribes} (${counts.tribes})`),
- button({ type: 'submit', name: 'filter', value: 'jobs', class: filter === 'jobs' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterJobs} (${counts.jobs})`),
- button({ type: 'submit', name: 'filter', value: 'market', class: filter === 'market' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterMarket} (${counts.market})`),
- button({ type: 'submit', name: 'filter', value: 'projects', class: filter === 'projects' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterProjects} (${counts.projects})`),
- button({ type: 'submit', name: 'filter', value: 'calendars', class: filter === 'calendars' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterCalendars || 'CALENDARS'} (${counts.calendars})`),
- button({ type: 'submit', name: 'filter', value: 'transfers', class: filter === 'transfers' ? 'filter-btn active' : 'filter-btn' },
- `${i18n.agendaFilterTransfers} (${counts.transfers})`),
- button({ type: 'submit', name: 'filter', value: 'discarded', class: filter === 'discarded' ? 'filter-btn active' : 'filter-btn' },
- `DISCARDED (${counts.discarded})`)
- )
- ),
- div({ class: 'agenda-list' },
- items.length
- ? items.map(item => renderAgendaItem(item, userId, filter))
- : p(i18n.agendaNoItems)
- )
- )
- );
- };
|