1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-18 07:52:23 +01:00

(wip) React component [EventCard]

This commit is contained in:
vincent 2022-04-15 11:50:53 +02:00 committed by Sylvain
parent fcfa9513e8
commit f30c501948
4 changed files with 61 additions and 120 deletions

View File

@ -13,9 +13,9 @@ interface EventCardProps {
cardType: 'sm' | 'md' | 'lg'
}
export const EventCard: React.FC<EventCardProps> = ({ event, cardType = 'sm' }) => {
export const EventCard: React.FC<EventCardProps> = ({ event, cardType = 'md' }) => {
const { t } = useTranslation('public');
console.log(event);
/**
* Format description to remove HTML tags and set a maximum character count
*/
@ -23,10 +23,10 @@ export const EventCard: React.FC<EventCardProps> = ({ event, cardType = 'sm' })
text = text.replace(/(<\/p>|<\/h4>|<\/h5>|<\/h6>|<\/pre>|<\/blockquote>)/g, '\n');
text = text.replace(/<br\s*\/?>/g, '\n');
text = text.replace(/<\/?\w+[^>]*>/g, '');
text = text.replace(/\n+/g, '<br />');
if (text.length > count) {
return text.slice(0, count) + '...';
text = text.slice(0, count) + '';
}
text = text.replace(/\n+/g, '<br />');
return text;
};
@ -51,28 +51,30 @@ export const EventCard: React.FC<EventCardProps> = ({ event, cardType = 'sm' })
};
/**
* Link to event by id
* TODO: Link to event by id ?
*/
const showEvent = (id: number) => {
// TODO: ???
console.log(id);
console.log(window.location.href + '/' + id);
};
return (
<div className={`event-card event-card--${cardType}`} onClick={() => showEvent(event.id)}>
<div className="event-card-picture">
{event.event_image
? <img src={event.event_image} alt="" />
: <i className="fas fa-image"></i>
}
</div>
{event.event_image
? <div className="event-card-picture">
<img src={event.event_image} alt="" />
</div>
: cardType !== 'sm' &&
<div className="event-card-picture">
<i className="fas fa-image"></i>
</div>
}
<div className="event-card-desc">
<header>
<p className='title'>{event?.title}</p>
<span className={`badge bg-${event.category.slug}`}>{event.category.name}</span>
</header>
{cardType !== 'sm' &&
<p dangerouslySetInnerHTML={{ __html: formatText(event.description, 500) }}></p>
<p dangerouslySetInnerHTML={{ __html: formatText(event.description, cardType === 'md' ? 500 : 400) }}></p>
}
</div>
<div className="event-card-info">

View File

@ -6,8 +6,10 @@
color: var(--gray-hard-darkest);
&:hover {
color: var(--gray-hard-darkest);
border-color: var(--gray-hard);
cursor: pointer;
& .event-card-picture {opacity: 0.7;}
.event-card-picture,
.event-card-info { border-color: var(--gray-hard); }
}
&-picture {
@ -17,7 +19,6 @@
background-color: #fff;
font-size: 8rem;
color: var(--gray-soft-light);
transition: opacity 0.4s ease-out;
img {
width: 100%;
height: 100%;
@ -43,7 +44,7 @@
}
&-info {
margin-top: auto;
padding: 15px 30px;
padding: 15px 20px;
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
@ -55,7 +56,7 @@
i {
width: 16px;
height: 16px;
margin-right: 15px;
margin-right: 10px;
font-size: 16px;
text-align: center;
color: var(--main);
@ -117,7 +118,35 @@
border-top: 1px solid var(--gray-soft-dark);
}
}
&-card--lg {}
&-card--lg {
border: 1px solid var(--gray-hard);
.event-card-info {
padding-top: 0;
& > p {
font-size: 1.8rem;
font-weight: 600;
color: var(--main);
}
}
.event-card-picture {
border-bottom: 1px solid var(--gray-hard);
img { max-height: 300px; }
}
@media (min-width: 992px) {
grid-column: span 2;
display: grid;
grid-template-columns: 3fr 2fr;
.event-card-desc { grid-area: 1/1/2/2; }
.event-card-info { grid-area: 2/1/3/2; }
.event-card-picture {
grid-area: 1/2/3/3;
border-bottom: none;
border-left: 1px solid var(--gray-hard);
img { max-height: none; }
}
}
}
// layout specific
&-home {
@ -142,35 +171,14 @@
&-focus {
display: grid;
margin-bottom: 50px;
.event-card {
border: 1px solid var(--gray-hard);
&-info { padding-top: 0; }
&-picture {
border-bottom: 1px solid var(--gray-hard);
img { max-height: 300px; }
}
}
@media (min-width: 992px) {
grid-template-columns: repeat(auto-fill, minmax(425px, 1fr));
gap: 15px;
.event-card {
grid-column: span 2;
display: grid;
grid-template-columns: 3fr 2fr;
&-desc { grid-area: 1/1/2/2; }
&-info { grid-area: 2/1/3/2; }
&-picture {
grid-area: 1/2/3/3;
border-bottom: none;
border-left: 1px solid var(--gray-hard);
img { max-height: none; }
}
}
}
}
&-month-list {
&-monthList {
display: grid;
grid-template-columns: 1fr;
gap: 15px;

View File

@ -40,43 +40,20 @@
</div>
</div>
<div class="event-focus">
<!-- TODO: get focus event -->
<!-- FIXME: get [card-type] in React component's props -->
<!--<event-card style="display: contents" event="" card-type="lg" />-->
</div>
<div ng-repeat="month in monthOrder">
<h1>{{monthNames[month.split(',')[0] - 1]}}, {{month.split(',')[1]}}</h1>
<div class="month-events-list" ng-repeat="event in (eventsGroupByMonth[month].length/3 | array)">
<a class="Event" ng-repeat="event in eventsGroupByMonth[month].slice(3*$index, 3*$index + 3)" ui-sref="app.public.events_show({id: event.id})">
<div class="Event-desc">
<h5 class="text-xs m-t-n">{{event.category.name}}</h5>
<h4 class="m-n text-sm clear l-n">{{event.title}}</h4>
<h3 class="m-n" ng-show="onSingleDay(event)">{{event.start_date | amDateFormat:'L'}}</h3>
<h3 class="m-n" ng-hide="onSingleDay(event)">{{event.start_date | amDateFormat:'L'}} <span class="text-sm font-thin" translate> {{ 'app.public.events_list.to_date' }} </span> {{event.end_date | amDateFormat:'L'}}</h3>
<h6 class="m-n" ng-if="!event.amount" translate>{{ 'app.public.events_list.free_admission' }}</h6>
<h6 class="m-n" ng-if="event.amount">{{ 'app.public.events_list.full_price_' | translate }} {{event.amount | currency}} <span ng-repeat="price in event.prices">/ {{ price.category.name }} {{price.amount | currency}}</span></h6>
<div>
<span class="text-black-light text-xs m-r-xs" ng-repeat="theme in event.event_themes">
<i class="fa fa-tags" aria-hidden="true"></i> {{theme.name}}
</span>
<span class="text-black-light text-xs" ng-if="event.age_range"><i class="fa fa-users" aria-hidden="true"></i> {{event.age_range.name}}</span>
</div>
<div>
<span class="text-black-light text-xs" ng-if="event.nb_free_places > 0">{{event.nb_free_places}} {{ 'app.public.events_list.still_available' | translate }}</span>
<span class="text-black-light text-xs" ng-if="event.nb_total_places > 0 && event.nb_free_places <= 0" translate>{{ 'app.public.events_list.sold_out' }}</span>
<span class="text-black-light text-xs" ng-if="event.nb_total_places == -1" translate>{{ 'app.public.events_list.cancelled' }}</span>
<span class="text-black-light text-xs" ng-if="!event.nb_total_places" translate>{{ 'app.public.events_list.without_reservation' }}</span>
</div>
</div>
<!-- Event Image -->
<div class="Event-picture" ng-if="event.event_image">
<img ng-src="{{event.event_image_small}}" title="{{event.title}}">
</div>
</a>
<div class="event-monthList" ng-repeat="event in (eventsGroupByMonth[month].length/3 | array)">
<!-- FIXME: get [card-type] in React component's props -->
<event-card style="display: contents" event="event" card-type="sm" ng-repeat="event in eventsGroupByMonth[month].slice(3*$index, 3*$index + 3)" />
</div>
</div>
<div class="row">
@ -88,5 +65,3 @@
</section>
</section>

View File

@ -6,52 +6,8 @@
</a>
</h4>
<div class="home-events-list" ng-repeat="event in (upcomingEvents.length/3 | array)">
<div class="Event" ng-repeat="event in upcomingEvents.slice(3*$index, 3*$index + 3)" ui-sref="app.public.events_show({id: event.id})">
<div class="Event-picture">
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:&#xf03e;/font:'Font Awesome 5 Free'/icon" bs-holder ng-if="!event.event_image" class="img-responsive">
<img ng-if="event.event_image" src="{{event.event_image_medium}}">
</div>
<div class="Event-desc">
<h3>{{event.title}}</h3>
<span class="v-middle badge text-xs" ng-class="'bg-{{event.category.slug}}'">{{event.category.name}}</span>
<p ng-bind-html="event.description | simpleText | humanize : 500 | breakFilter"></p>
</div>
<div class="Event-info">
<div class="Event-info-item">
<i class="fa fa-calendar"></i>
<h6 class="" ng-hide="isOneDayEvent(event)">{{ 'app.public.home.from_date_to_date' | translate:{START:(event.start_date | amDateFormat:'L'), END:(event.end_date | amDateFormat:'L')} }}</h6>
<h6 class="" ng-show="isOneDayEvent(event)">{{ 'app.public.home.on_the_date' | translate:{DATE:(event.start_date | amDateFormat:'L')} }}</h6>
</div>
<div class="Event-info-item">
<i class="fas fa-clock"></i>
<h6 class="">
<span ng-if="event.all_day == 'true'" translate>{{ 'app.public.home.all_day' }}</span>
<span ng-if="event.all_day == 'false'">{{ 'app.public.home.from_time_to_time' | translate:{START:(event.start_date | amDateFormat:'LT'), END:(event.end_date | amDateFormat:'LT')} }}</span>
</h6>
</div>
<div class="Event-info-item">
<i class="fa fa-user"></i>
<h6 class="">
<span ng-if="event.nb_free_places > 0">{{ 'app.public.home.still_available' | translate }} {{event.nb_free_places}}</span>
<span ng-if="!event.nb_total_places" translate>{{ 'app.public.home.without_reservation' }}</span>
<span ng-if="event.nb_total_places > 0 && event.nb_free_places <= 0" translate>{{ 'app.public.home.event_full' }}</span>
</h6>
</div>
<div class="Event-info-item">
<i class="fa fa-bookmark"></i>
<h6 class="">
<span ng-if="event.amount == 0" translate>{{ 'app.public.home.free_admission' }}</span>
<span ng-if="event.amount > 0">{{ 'app.public.home.full_price' | translate }} {{event.amount | currency}}</span>
</h6>
</div>
</div>
</div>
</div>
<div class="event-home-list" ng-repeat="event in (upcomingEvents.length/3 | array)">
<!-- FIXME: get [card-type] in React component's props -->
<event-card style="display: contents" event="event" card-type="md" ng-repeat="event in upcomingEvents.slice(3*$index, 3*$index + 3)" />
</div>
</section>