События и первый конкурс #6

Merged
rndtrash merged 19 commits from feature/events into master 2025-11-26 11:46:26 +03:00
5 changed files with 55 additions and 12 deletions
Showing only changes of commit 828cba41bd - Show all commits

View file

@ -22,7 +22,7 @@
post, post,
size = BlogCardSize.Both, size = BlogCardSize.Both,
fullHeight = false fullHeight = false
}: { post: App.BlogPost; size: BlogCardSize; fullHeight: boolean } = $props(); }: { post: App.BlogPost; size?: BlogCardSize; fullHeight?: boolean } = $props();
const type: App.BlogPostType = post.type ?? 'article'; const type: App.BlogPostType = post.type ?? 'article';
let isPostNew = $state(false); let isPostNew = $state(false);

View file

@ -31,6 +31,7 @@ export function postEventStatus(post: App.BlogPost): EventStatus {
export type PostComparer = (a: App.BlogPost, b: App.BlogPost) => number; export type PostComparer = (a: App.BlogPost, b: App.BlogPost) => number;
export const sortPostsByPostDate: PostComparer = (a, b) => new Date(b.date!).valueOf() - new Date(a.date!).valueOf(); export const sortPostsByPostDate: PostComparer = (a, b) => new Date(b.date!).valueOf() - new Date(a.date!).valueOf();
export const sortPostsByPostAndUpdateDate: PostComparer = (a, b) => laterDate(b.date!, b.dateChanged) - laterDate(a.date!, a.dateChanged);
function laterDate(a: string, ...dates: (string | undefined)[]): number { function laterDate(a: string, ...dates: (string | undefined)[]): number {
const dateA = new Date(a).valueOf(); const dateA = new Date(a).valueOf();
@ -45,8 +46,6 @@ function laterDate(a: string, ...dates: (string | undefined)[]): number {
return max; return max;
} }
export const sortPostsByPostAndUpdateDate: PostComparer = (a, b) => laterDate(b.date!, b.dateChanged) - laterDate(a.date!, a.dateChanged);
export async function fetchPostsSorted(postComparer?: PostComparer) { export async function fetchPostsSorted(postComparer?: PostComparer) {
const allPosts = await fetchPosts(); const allPosts = await fetchPosts();

View file

@ -1,11 +1,24 @@
<script lang="ts"> <script lang="ts">
import SocialButton from '$lib/components/SocialButton.svelte'; import SocialButton from '$lib/components/SocialButton.svelte';
import { PUBLIC_TS_DISCORD, PUBLIC_TS_TELEGRAM } from '$env/static/public'; import { PUBLIC_TS_DISCORD, PUBLIC_TS_TELEGRAM } from '$env/static/public';
import BlogCard, { BlogCardSize } from '$src/lib/components/BlogCard.svelte'; import BlogCard, { BlogCardSize } from '$lib/components/BlogCard.svelte';
import { page } from '$app/state'; import { page } from '$app/state';
import type { PageData } from './$types'; import type { PageData } from './$types';
import { onMount } from 'svelte';
import { postIsEventOfInterest } from '$lib/util/Blogs';
export let data: PageData; let { data }: { data: PageData } = $props();
// postIsEventOfInterest(b) ? b.dateEventTo : undefined
let posts: App.BlogPost[] = $state(page.data.posts);
onMount(() => {
const dateToNum = (d: string) => new Date(d).valueOf();
posts = posts.sort(
(a, b) =>
dateToNum(postIsEventOfInterest(b) ? b.dateEventTo! : b.date!) -
dateToNum(postIsEventOfInterest(a) ? a.dateEventTo! : a.date!)
);
});
</script> </script>
<svelte:head> <svelte:head>
@ -88,9 +101,11 @@
<h1 class="font-disket text-center text-2xl font-bold sm:text-4xl">ПОСЛЕДНИЕ ПОСТЫ</h1> <h1 class="font-disket text-center text-2xl font-bold sm:text-4xl">ПОСЛЕДНИЕ ПОСТЫ</h1>
<div class="flex flex-row items-stretch justify-evenly gap-4 overflow-x-auto p-4"> <div class="flex flex-row items-stretch justify-evenly gap-4 overflow-x-auto p-4">
{#each page.data.posts as post, i} {#each posts as post, i}
<div class="aspect-3/2 w-80 shrink-0"> <div class="aspect-3/2 w-80 shrink-0">
<BlogCard {post} size={BlogCardSize.Short} fullHeight /> {#key post}
<BlogCard {post} size={BlogCardSize.Short} fullHeight />
{/key}
</div> </div>
{/each} {/each}
</div> </div>

View file

@ -1,4 +1,4 @@
import { fetchPostsSorted } from "$src/lib/util/Blogs"; import { fetchPostsSorted } from "$lib/util/Blogs";
export async function load() { export async function load() {
return { title: "Блог", description: "Новости и заметки проектов Tea Sanctuary", posts: await fetchPostsSorted() }; return { title: "Блог", description: "Новости и заметки проектов Tea Sanctuary", posts: await fetchPostsSorted() };

View file

@ -1,8 +1,10 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/state'; import { page } from '$app/state';
import SocialHyperlink from '$src/lib/components/SocialHyperlink.svelte'; import SocialHyperlink from '$lib/components/SocialHyperlink.svelte';
import InfoBlock from '$src/lib/components/InfoBlock.svelte'; import InfoBlock from '$lib/components/InfoBlock.svelte';
import BlogCard from '$src/lib/components/BlogCard.svelte'; import BlogCard, { BlogCardSize } from '$lib/components/BlogCard.svelte';
import { postIsEventOfInterest, type PostComparer } from '$lib/util/Blogs';
import { onMount } from 'svelte';
function groupPostsByMonthYear(posts: App.BlogPost[]) { function groupPostsByMonthYear(posts: App.BlogPost[]) {
const groupedPosts = new Map<string, App.BlogPost[]>(); const groupedPosts = new Map<string, App.BlogPost[]>();
@ -19,7 +21,20 @@
return groupedPosts; return groupedPosts;
} }
function getEventsOfInterest(posts: App.BlogPost[]) {
// Сортировка в обратном порядке - чем ближе к завершению, тем раньше в списке
const sortPostsByEvent: PostComparer = (a, b) =>
new Date(a.dateEventTo!).valueOf() - new Date(b.dateEventTo!).valueOf();
return posts.filter((a) => postIsEventOfInterest(a)).sort(sortPostsByEvent);
}
const groupedPosts = groupPostsByMonthYear(page.data.posts); const groupedPosts = groupPostsByMonthYear(page.data.posts);
let eventPosts: App.BlogPost[] = $state([]);
onMount(() => {
eventPosts = getEventsOfInterest(page.data.posts);
});
</script> </script>
<section class="hero flex shrink-0 flex-col items-center justify-center gap-5 overflow-hidden p-4"> <section class="hero flex shrink-0 flex-col items-center justify-center gap-5 overflow-hidden p-4">
@ -39,6 +54,20 @@
пропускать новые посты! пропускать новые посты!
</InfoBlock> </InfoBlock>
{#if !!eventPosts && eventPosts.length > 0}
<section class="flex flex-col items-stretch bg-amber-50 pt-4">
<h1 class="font-disket text-center text-2xl font-bold sm:text-4xl">АКТУАЛЬНЫЕ СОБЫТИЯ</h1>
<div class="flex flex-row items-stretch justify-evenly gap-4 overflow-x-auto p-4">
{#each eventPosts as post, i}
<div class="aspect-3/2 w-80 shrink-0">
<BlogCard {post} size={BlogCardSize.Short} fullHeight />
</div>
{/each}
</div>
</section>
{/if}
<section class="flex flex-col items-stretch p-2 pb-8 md:p-4"> <section class="flex flex-col items-stretch p-2 pb-8 md:p-4">
{#each groupedPosts.entries() as [monthYear, postsInMonthYear]} {#each groupedPosts.entries() as [monthYear, postsInMonthYear]}
<h1 <h1
@ -52,4 +81,4 @@
{/each} {/each}
</div> </div>
{/each} {/each}
</section> </section>