]> _ Git - pmi.git/commitdiff
WIP #2751 @8
authorStephen Cameron <stephen@cubedesigners.com>
Wed, 7 Aug 2019 16:43:33 +0000 (18:43 +0200)
committerStephen Cameron <stephen@cubedesigners.com>
Wed, 7 Aug 2019 16:43:33 +0000 (18:43 +0200)
app/Http/Controllers/AjaxController.php
app/Http/Controllers/NewsController.php
app/Models/News.php
app/Templates/News.php
resources/js/mailform.js
resources/styles/components/form.styl
resources/styles/components/news.styl
resources/views/pages/news-detail.blade.php
resources/views/pages/news.blade.php
resources/views/partials/form.blade.php
resources/views/partials/newsletter-form.blade.php [new file with mode: 0644]

index ec7a191151cce1b70721480446f43022dd8438f2..c321dfe0872029320f00119a9b13b599df831f79 100644 (file)
@@ -84,4 +84,27 @@ class AjaxController extends CubistFrontController
             $message->subject($subject . $validatedData['subject']);
         });
     }
+
+    // Subscribe to newsletter via MailChimp API
+    public function newsletter(Request $request)
+    {
+        $validator = Validator::make(
+            $request->all(),
+            [
+                'email' => 'required|email',
+            ],
+            [
+                'email.required' => __('Champ obligatoire'),
+                'email.email' => __('Adresse e-mail invalide'),
+            ]
+        );
+
+        $validator->validate();
+
+        // TODO: implement MailChimp API (https://developer.mailchimp.com/documentation/mailchimp/guides/manage-subscribers-with-the-mailchimp-api/)
+        //$validatedData = $validator->validated();
+        //dd($validatedData);
+
+        return [];
+    }
 }
index e7c73e3ac9e1aabbab16f77bac5630d3d5e5cafc..c0c1c389c3aa25895278fbbf12317ee750f305bc 100644 (file)
@@ -16,8 +16,8 @@ class NewsController extends CubistFrontController
         }
 
         $this->data['title'] = $newsItem->title;
-        $this->data['news'] = $newsItem->getPageData();
-        $this->data['image'] = $this->data['news']->getImageURL('image', 'thumb');
+        $this->data['image'] = $newsItem->getFirstMediaUrl($newsItem->image, 'thumb');
+        $this->data['news'] = $newsItem;
 
         return view('pages.news-detail', $this->data);
     }
index c52af1fedf80f656827e632711e1890d122b7de1..624b9647f5b30c40bf0f83876e8ad8763bd7a3be 100644 (file)
@@ -13,4 +13,27 @@ class News extends \Cubist\Backpack\app\Magic\Models\News
         $this->addMediaConversion('thumb')
              ->crop('crop-center', 348, 232);
     }
+
+    // Display compact date range in localised human readable format
+    // Ref: https://codereview.stackexchange.com/a/78303
+    // Alternative: https://github.com/flack/ranger
+    public function formatDateRange($start, $end) {
+
+        if ($start->format('Y-m-d') === $end->format('Y-m-d')) {
+            # Same day
+            return $start->isoFormat('D MMMM Y');
+
+        } elseif ($start->format('Y-m') === $end->format('Y-m')) {
+            # Same calendar month
+            return $start->isoFormat('D') . $end->isoFormat('–D MMMM YYYY');
+
+        } elseif ($start->format('Y') === $end->format('Y')) {
+            # Same calendar year
+            return $start->isoFormat('D MMMM') . $end->isoFormat(' – D MMMM Y');
+
+        } else {
+            # General case (spans calendar years)
+            return $start->isoFormat('D MMMM Y') . $end->isoFormat(' – D MMMM Y');
+        }
+    }
 }
index 83c2530368d4ef21b057b242113e697c07f62594..53441c02f559d71402a6d2f418821b5b133dd7d7 100644 (file)
@@ -27,6 +27,8 @@ class News extends Base
                 continue;
             }
 
+            // Todo: see if we should handle events differently? Should events have a different ID + URL and maybe a different controller action in case we need a different layout?
+
             $item = new Item();
             $item->setTitle($newsItem->title);
             $item->setHref($newsItem->slug); // Todo: consider having a configurable / translatable prefix for news URLs
index 7a772a237872b521920ef1a3fa6ea8c776034c5b..8ed46de31e4dd8825e84f5918996489cd6f718b0 100644 (file)
@@ -28,7 +28,8 @@ $(function () {
             data: $(this).serialize(),
         }).done(function (response) {
             $(form).find('.error').removeClass('error');
-            $(form).closest('#contact-form').html('<p class="center text-2xl text-center p-8" >' + $(form).data('confirmation') + '</p>');
+            // Todo: make this more customisable from the form
+            $(form).html('<p class="center text-2xl text-center p-8" >' + $(form).data('confirmation') + '</p>');
         }).fail(function (response) {
             button.text(button.data('text')).prop('disabled', false);
             $(form).find('.error').removeClass('error');
index 306db95c5dcbe3bd2a59742e9d12cb428c31d4ac..b592cddfe4ba4bd6492d31968927c7524e870789 100644 (file)
@@ -1,49 +1,48 @@
-#contact-form
-  .form
-
-    .fields
-      grid-column-gap: 30px
-      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
-
-    .errormessage
-      color theme('colors.red')
-      font-weight: 300
-      position: absolute
-      right: 0
-      top: 15px
-      text-align: right
-
-    input, textarea
-      border-radius 3px
-      color: theme('colors.grey.dark')
-      padding 12px 10px
-      border 1px solid #fff
-      display: block
-      width: 100%
-
-      &:focus
-        border-color: theme('colors.grey.250')
-
-      &.error
-        border-color: theme('colors.red')
-
-    label
-      font-family: theme('fontFamily.body')
-      position: relative
-      padding-top: 15px
-      display: block
-
-      &:not(.half)
-        grid-column 1 / -1
-
-    .textarea
-      height 144px
-      display: block
-
-    &-endmessage
-      font-size: 14px
-      margin-bottom: 20px;
-
-    .btn-custom
-      min-width 14rem
-      padding 1.125rem 3.375rem
+.ajax-form
+
+  .fields
+    grid-column-gap: 30px
+    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+
+  .errormessage
+    color theme('colors.red')
+    font-weight: 300
+    position: absolute
+    right: 0
+    top: 15px
+    text-align: right
+
+  input, textarea
+    border-radius 3px
+    color: theme('colors.grey.dark')
+    padding 12px 10px
+    border 1px solid #fff
+    display: block
+    width: 100%
+
+    &:focus
+      border-color: theme('colors.grey.250')
+
+    &.error
+      border-color: theme('colors.red')
+
+  label
+    font-family: theme('fontFamily.body')
+    position: relative
+    padding-top: 15px
+    display: block
+
+    &:not(.half)
+      grid-column 1 / -1
+
+  .textarea
+    height 144px
+    display: block
+
+  &-endmessage
+    font-size: 14px
+    margin-bottom: 20px;
+
+  .btn-custom
+    min-width 14rem
+    padding 1.125rem 3.375rem
index 5bb6a53ba2aa056ca15ceaa615d380e8488eff93..229e144c16333a8c5d44c4d7f76c22876966c961 100644 (file)
@@ -1,5 +1,47 @@
-.news
-  // 3 column layout with image / text / sidebar
+//=== News Index Page
+// 2 column layout with articles / sidebar
+// Internal grid for each article
+.news-index
+  &-layout
+    display: grid
+    constrain(grid-gap, 2.5vw)
+    grid-template: "articles sidebar" auto / 3fr 1fr
+    grid-template-rows: max-content
+    grid-template-columns: auto
+
+    +below(768px)
+      grid-template-areas: "articles" "sidebar"
+
+  &-articles
+    grid-area: articles
+
+  // Internal grid for each article
+  &-article
+    display: grid
+    constrain(grid-gap, 2.5vw)
+    grid-template: "image text" auto / 1fr 2.25fr
+
+    &:not(:last-child)
+      constrain(margin-bottom, 2.5vw)
+
+    +below(1000px)
+      grid-template: "image" "text" auto / 1fr
+      &:not(:last-child)
+        margin-bottom: 5vw
+
+    &-image
+      grid-area: image
+
+    &-text
+      grid-area: text
+
+  &-sidebar
+    grid-area: sidebar
+
+
+//=== Individual News Post
+// 3 column layout with image / text / sidebar
+.news-post
   &-layout
     display: grid
     constrain(grid-gap, 2.5vw)
@@ -23,4 +65,4 @@
 
   &-sidebar
     grid-area: sidebar
-    min-width: 260px
+    min-width: 320px
index af4af2596a2ab3975ef0fa8b2e2377fdb8951c80..68c4254c04e2885b839ca015bdbc9d300c4bb3f9 100644 (file)
@@ -6,19 +6,23 @@
         <content>
             <text-block :title="$news->title" title-tag="h1" />
 
-            <div class="news-layout">
+            <div class="news-post-layout">
                 @if ($image)
                     {{-- Todo: use larger image + srcset here --}}
-                    <img src="{{ $image }}" alt="{{ $title }}" class="news-image">
+                    <img src="{{ $image }}" alt="{{ $title }}" class="news-post-image">
                 @endif
 
-                <div class="news-body">
-                    <p>{{ date('d/m/y', strtotime($news->date['date'])) }}</p>
+                <div class="news-post-body">
+                    <time datetime="{{ $news->date->toDateTimeLocalString() }}" class="block mb-2 text-sm">
+                        {{ $news->date->format('d/m/y') }}
+                    </time>
                     @markdown($news->content)
                 </div>
 
-                <div class="news-sidebar bg-grey-100 p-1v">
-                    (Newsletter Form)
+                <div class="news-post-sidebar">
+                    <div class="bg-grey-100 p-1v">
+                        @include('partials.newsletter-form')
+                    </div>
                 </div>
 
             </div>
index 9f78ea1666ed1124a957dd94726067de71ac5e81..ff7620500275c84948e6544cf50ecec585f52cab 100644 (file)
@@ -6,24 +6,26 @@
         <content>
 
             {{-- Todo: use grid for main (generic?) sidebar layout and utilise minmax for content? --}}
-            <div class="news-index-layout flex">
+            <div class="news-index-layout">
 
-                <div class="news-items">
+                <div class="news-index-articles">
                     @foreach ($news as $newsItem)
                         @php
                             $newsURL = $nav->getHrefByID("news/{$newsItem->id}");
                         @endphp
 
-                        {{-- Todo: use smaller grid for each article: 1fr image, 2fr content with a minmax on image to auto wrap --}}
-                        <article class="flex">
+                        <article class="news-index-article">
 
-                            <a href="{{ $newsURL }}" class="news-item-image">
+                            <a href="{{ $newsURL }}" class="news-index-article-image">
                                 {{--Todo: handle missing images + get correct image size--}}
-                                <img class="mb-1v mr-1v" src="{{ $newsItem->getFirstMediaUrl($newsItem->image, 'thumb') }}" alt="{{ $newsItem->title }}">
+                                <img src="{{ $newsItem->getFirstMediaUrl($newsItem->image, 'thumb') }}" alt="{{ $newsItem->title }}">
                             </a>
 
-                            <div class="news-item-text">
-                                <h4 class="font-display">{{ $newsItem->title }}</h4>
+                            <div class="news-index-article-text">
+                                <time datetime="{{ $newsItem->date->toDateTimeLocalString() }}" class="block mb-2 text-sm">
+                                    {{ $newsItem->date->format('d/m/y') }}
+                                </time>
+                                <h4 class="text-2xl">{{ $newsItem->title }}</h4>
                                 <p>{{ $newsItem['chapo'] }}</p>
 
                                 <p><a href="{{ $newsURL }}">{{ __('En savoir plus') }}</a></p>
                     @endforeach
                 </div>
 
-                <div class="news-sidebar">
+                <div class="news-index-sidebar">
                     <div class="bg-grey-100 p-1v mb-1v">
-                        Events
+                        <h3 class="text-2xl">{{ __('Évènements') }}</h3>
+                        @foreach($events as $event)
+                            @php
+                                $eventURL = $nav->getHrefByID("news/{$event->id}"); // Todo: possibly events will have different IDs
+                            @endphp
+
+                            <div class="event @if(!$loop->last) mb-8 @endif">
+                                <a href="{{ $eventURL }}">
+                                    <img src="{{ $event->getFirstMediaUrl($event->image, 'thumb') }}" alt="{{ $event->title }}" style="max-width:252px" class="mb-3">
+                                </a>
+                                <h4 class="font-medium mb-1">{{ $event->title }}</h4>
+                                <p>{{ $event->formatDateRange($event->event_start, $event->event_end) }}, {{ $event->event_place }}</p>
+                                <p class="-mt-4"><a href="{{ $eventURL }}">{{ __('En savoir plus') }}</a></p>
+                            </div>
+                        @endforeach
                     </div>
 
                     <div class="bg-grey-100 p-1v">
-                        Newsletter subscribe
+                        @include('partials.newsletter-form')
                     </div>
                 </div>
 
index f5ca2db9afa3b88cc7e4bc0673eed97c979d21fb..cb01ad8753f2de4f5056ab107802c8144882c9d9 100644 (file)
@@ -5,7 +5,7 @@
     @endpush
 
 <div id="contact-form">
-    <div class="form flex flex-col">
+    <div class="ajax-form flex flex-col">
         @if($page->get('form_intro'))
             <p class="form-info text-navy">{{$page->get('form_intro')}}</p>
         @endif
diff --git a/resources/views/partials/newsletter-form.blade.php b/resources/views/partials/newsletter-form.blade.php
new file mode 100644 (file)
index 0000000..73ef1fe
--- /dev/null
@@ -0,0 +1,14 @@
+@push('scripts')
+    <script src="{{ mix('/js/mailform.js') }}"></script>
+@endpush
+
+<h3 class="text-2xl">
+    {{ __('Inscription Newsletter') }}
+</h3>
+
+<form action="/ajax/newsletter" method="post" class="ajax-form mailform text-navy" data-confirmation="{{ __('Merci, vous avez été inscrit avec succès') }}" novalidate>
+    <label for="newsletter_email" class="form-input">{{ __('Email') }}
+        <input type="email" name="email" id="newsletter_email" class="py-3 mt-3" required>
+    </label>
+    <button type="submit" class="mt-4 btn w-full sm:w-auto sm:block sm:ml-auto xs:w-full" data-sending="{{ __('Attendez') }}">{{ __("S'inscrire") }}</button>
+</form>