From 2d4e5aea055a1d31201c6730bc054e6def3e6811 Mon Sep 17 00:00:00 2001 From: Mads Hermansen <119772939+madshermansen@users.noreply.github.com> Date: Wed, 20 Mar 2024 18:18:36 +0100 Subject: [PATCH] 126 branch2 blog overview (#166) * refactor(frontend): :ambulance: Move changes from other branch 126 into new branch * feat(frontend): :art: Moved Card displaying to new component to make main page less have less clustering * style(frontend): :sparkles: Styling for responsiveness * feat(frontend): :sparkles: add max-height to image * feat(frontend): :art: prettier write --- .../article/content-types/article/schema.json | 18 +- backend/types/generated/contentTypes.d.ts | 2 + frontend/src/__generated__/gql.ts | 4 +- frontend/src/__generated__/graphql.ts | 13 +- frontend/src/app/blog/page.tsx | 159 +++++++++--------- frontend/src/components/BlogpageButtons.tsx | 30 ++++ frontend/src/components/fullBlogCard.tsx | 82 +++++++++ frontend/src/components/ui/blogCard.tsx | 86 ++++++++++ 8 files changed, 302 insertions(+), 92 deletions(-) create mode 100644 frontend/src/components/BlogpageButtons.tsx create mode 100644 frontend/src/components/fullBlogCard.tsx create mode 100644 frontend/src/components/ui/blogCard.tsx diff --git a/backend/src/api/article/content-types/article/schema.json b/backend/src/api/article/content-types/article/schema.json index c257024..fc89d44 100644 --- a/backend/src/api/article/content-types/article/schema.json +++ b/backend/src/api/article/content-types/article/schema.json @@ -4,7 +4,8 @@ "info": { "singularName": "article", "pluralName": "articles", - "displayName": "Article" + "displayName": "Article", + "description": "" }, "options": { "draftAndPublish": true @@ -29,11 +30,12 @@ "required": true }, "coverImage": { + "type": "media", + "multiple": false, + "required": false, "allowedTypes": [ "images" - ], - "type": "media", - "multiple": false + ] }, "body": { "type": "blocks", @@ -44,6 +46,14 @@ "relation": "manyToOne", "target": "api::author.author", "inversedBy": "articles" + }, + "Tag": { + "type": "enumeration", + "enum": [ + "Featured", + "News", + "Updates" + ] } } } diff --git a/backend/types/generated/contentTypes.d.ts b/backend/types/generated/contentTypes.d.ts index e491035..f907bdb 100644 --- a/backend/types/generated/contentTypes.d.ts +++ b/backend/types/generated/contentTypes.d.ts @@ -794,6 +794,7 @@ export interface ApiArticleArticle extends Schema.CollectionType { singularName: 'article'; pluralName: 'articles'; displayName: 'Article'; + description: ''; }; options: { draftAndPublish: true; @@ -810,6 +811,7 @@ export interface ApiArticleArticle extends Schema.CollectionType { 'manyToOne', 'api::author.author' >; + Tag: Attribute.Enumeration<['Featured', 'News', 'Updates']>; createdAt: Attribute.DateTime; updatedAt: Attribute.DateTime; publishedAt: Attribute.DateTime; diff --git a/frontend/src/__generated__/gql.ts b/frontend/src/__generated__/gql.ts index fac870c..aa31062 100644 --- a/frontend/src/__generated__/gql.ts +++ b/frontend/src/__generated__/gql.ts @@ -14,7 +14,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ */ const documents = { "query ArticleWithSlug($articlesFilters: ArticleFiltersInput) {\n articles(filters: $articlesFilters) {\n data {\n attributes {\n author {\n data {\n attributes {\n name\n avatar {\n data {\n attributes {\n url\n }\n }\n }\n }\n }\n }\n body\n coverImage {\n data {\n attributes {\n url\n }\n }\n }\n datePublished\n subtitle\n title\n }\n }\n }\n }\n \n ": types.ArticleWithSlugDocument, - "\nquery GET_ARTICLES {\n articles(sort: [\"datePublished:desc\"]) {\n data {\n id\n attributes {\n author {\n data {\n attributes {\n name\n avatar {\n data {\n attributes {\n url\n }\n }\n }\n }\n }\n }\n title\n datePublished\n body\n coverImage {\n data {\n attributes {\n url\n }\n }\n }\n createdAt\n publishedAt\n slug\n subtitle\n }\n }\n }\n}\n": types.Get_ArticlesDocument, + "\nquery GET_ARTICLES {\n articles(sort: [\"datePublished:desc\"]) {\n data {\n id\n attributes {\n author {\n data {\n attributes {\n name\n avatar {\n data {\n attributes {\n url\n }\n }\n }\n }\n }\n }\n title\n datePublished\n body\n coverImage {\n data {\n attributes {\n url\n }\n }\n }\n createdAt\n publishedAt\n slug\n subtitle\n Tag\n }\n }\n }\n}\n": types.Get_ArticlesDocument, "\nquery MostRecentImages {\n mostRecentImages(sort: [\"publishedAt:desc\"]) {\n data {\n attributes {\n mostRecentImage {\n data {\n attributes {\n url\n }\n }\n }\n satellite {\n data {\n attributes {\n catalogNumberNORAD\n }\n }\n }\n createdAt\n updatedAt\n publishedAt\n }\n }\n }\n}\n\n": types.MostRecentImagesDocument, "\nquery Projects($projectFilters: ProjectFiltersInput) {\n projects(filters: $projectFilters) {\n data {\n attributes {\n title\n description\n article\n satellites {\n data {\n id\n attributes {\n name\n previewImage {\n data {\n attributes {\n url\n }\n }\n }\n }\n }\n }\n slug\n coverImage {\n data {\n id\n attributes {\n url\n }\n }\n }\n }\n }\n }\n}": types.ProjectsDocument, "\n query GET_PROJECTS {\n projects(sort: [\"publishedAt:desc\"]) {\n data {\n id\n attributes {\n title\n article\n satellites {\n data {\n attributes {\n catalogNumberNORAD\n }\n }\n }\n slug\n coverImage {\n data {\n attributes {\n url\n }\n }\n }\n updatedAt\n publishedAt\n createdAt\n description\n }\n }\n }\n }": types.Get_ProjectsDocument, @@ -44,7 +44,7 @@ export function gql(source: "query ArticleWithSlug($articlesFilters: ArticleFilt /** * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function gql(source: "\nquery GET_ARTICLES {\n articles(sort: [\"datePublished:desc\"]) {\n data {\n id\n attributes {\n author {\n data {\n attributes {\n name\n avatar {\n data {\n attributes {\n url\n }\n }\n }\n }\n }\n }\n title\n datePublished\n body\n coverImage {\n data {\n attributes {\n url\n }\n }\n }\n createdAt\n publishedAt\n slug\n subtitle\n }\n }\n }\n}\n"): (typeof documents)["\nquery GET_ARTICLES {\n articles(sort: [\"datePublished:desc\"]) {\n data {\n id\n attributes {\n author {\n data {\n attributes {\n name\n avatar {\n data {\n attributes {\n url\n }\n }\n }\n }\n }\n }\n title\n datePublished\n body\n coverImage {\n data {\n attributes {\n url\n }\n }\n }\n createdAt\n publishedAt\n slug\n subtitle\n }\n }\n }\n}\n"]; +export function gql(source: "\nquery GET_ARTICLES {\n articles(sort: [\"datePublished:desc\"]) {\n data {\n id\n attributes {\n author {\n data {\n attributes {\n name\n avatar {\n data {\n attributes {\n url\n }\n }\n }\n }\n }\n }\n title\n datePublished\n body\n coverImage {\n data {\n attributes {\n url\n }\n }\n }\n createdAt\n publishedAt\n slug\n subtitle\n Tag\n }\n }\n }\n}\n"): (typeof documents)["\nquery GET_ARTICLES {\n articles(sort: [\"datePublished:desc\"]) {\n data {\n id\n attributes {\n author {\n data {\n attributes {\n name\n avatar {\n data {\n attributes {\n url\n }\n }\n }\n }\n }\n }\n title\n datePublished\n body\n coverImage {\n data {\n attributes {\n url\n }\n }\n }\n createdAt\n publishedAt\n slug\n subtitle\n Tag\n }\n }\n }\n}\n"]; /** * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/frontend/src/__generated__/graphql.ts b/frontend/src/__generated__/graphql.ts index caef617..7ae870b 100644 --- a/frontend/src/__generated__/graphql.ts +++ b/frontend/src/__generated__/graphql.ts @@ -26,6 +26,7 @@ export type Scalars = { export type Article = { __typename?: 'Article'; + Tag?: Maybe; author?: Maybe; body: Scalars['JSON']['output']; coverImage?: Maybe; @@ -56,6 +57,7 @@ export type ArticleEntityResponseCollection = { }; export type ArticleFiltersInput = { + Tag?: InputMaybe; and?: InputMaybe>>; author?: InputMaybe; body?: InputMaybe; @@ -72,6 +74,7 @@ export type ArticleFiltersInput = { }; export type ArticleInput = { + Tag?: InputMaybe; author?: InputMaybe; body?: InputMaybe; coverImage?: InputMaybe; @@ -216,6 +219,12 @@ export type DateTimeFilterInput = { startsWith?: InputMaybe; }; +export enum Enum_Article_Tag { + Featured = 'Featured', + News = 'News', + Updates = 'Updates' +} + export type FileInfoInput = { alternativeText?: InputMaybe; caption?: InputMaybe; @@ -1396,7 +1405,7 @@ export type ArticleWithSlugQuery = { __typename?: 'Query', articles?: { __typena export type Get_ArticlesQueryVariables = Exact<{ [key: string]: never; }>; -export type Get_ArticlesQuery = { __typename?: 'Query', articles?: { __typename?: 'ArticleEntityResponseCollection', data: Array<{ __typename?: 'ArticleEntity', id?: string | null, attributes?: { __typename?: 'Article', title: string, datePublished: any, body: any, createdAt?: any | null, publishedAt?: any | null, slug: string, subtitle?: string | null, author?: { __typename?: 'AuthorEntityResponse', data?: { __typename?: 'AuthorEntity', attributes?: { __typename?: 'Author', name: string, avatar?: { __typename?: 'UploadFileEntityResponse', data?: { __typename?: 'UploadFileEntity', attributes?: { __typename?: 'UploadFile', url: string } | null } | null } | null } | null } | null } | null, coverImage?: { __typename?: 'UploadFileEntityResponse', data?: { __typename?: 'UploadFileEntity', attributes?: { __typename?: 'UploadFile', url: string } | null } | null } | null } | null }> } | null }; +export type Get_ArticlesQuery = { __typename?: 'Query', articles?: { __typename?: 'ArticleEntityResponseCollection', data: Array<{ __typename?: 'ArticleEntity', id?: string | null, attributes?: { __typename?: 'Article', title: string, datePublished: any, body: any, createdAt?: any | null, publishedAt?: any | null, slug: string, subtitle?: string | null, Tag?: Enum_Article_Tag | null, author?: { __typename?: 'AuthorEntityResponse', data?: { __typename?: 'AuthorEntity', attributes?: { __typename?: 'Author', name: string, avatar?: { __typename?: 'UploadFileEntityResponse', data?: { __typename?: 'UploadFileEntity', attributes?: { __typename?: 'UploadFile', url: string } | null } | null } | null } | null } | null } | null, coverImage?: { __typename?: 'UploadFileEntityResponse', data?: { __typename?: 'UploadFileEntity', attributes?: { __typename?: 'UploadFile', url: string } | null } | null } | null } | null }> } | null }; export type MostRecentImagesQueryVariables = Exact<{ [key: string]: never; }>; @@ -1436,7 +1445,7 @@ export type SatellitesQuery = { __typename?: 'Query', satellites?: { __typename? export const ArticleWithSlugDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ArticleWithSlug"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"articlesFilters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ArticleFiltersInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"articles"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"articlesFilters"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"body"}},{"kind":"Field","name":{"kind":"Name","value":"coverImage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"datePublished"}},{"kind":"Field","name":{"kind":"Name","value":"subtitle"}},{"kind":"Field","name":{"kind":"Name","value":"title"}}]}}]}}]}}]}}]} as unknown as DocumentNode; -export const Get_ArticlesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GET_ARTICLES"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"articles"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"ListValue","values":[{"kind":"StringValue","value":"datePublished:desc","block":false}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"datePublished"}},{"kind":"Field","name":{"kind":"Name","value":"body"}},{"kind":"Field","name":{"kind":"Name","value":"coverImage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"publishedAt"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"subtitle"}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const Get_ArticlesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GET_ARTICLES"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"articles"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"ListValue","values":[{"kind":"StringValue","value":"datePublished:desc","block":false}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"datePublished"}},{"kind":"Field","name":{"kind":"Name","value":"body"}},{"kind":"Field","name":{"kind":"Name","value":"coverImage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"publishedAt"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"subtitle"}},{"kind":"Field","name":{"kind":"Name","value":"Tag"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const MostRecentImagesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"MostRecentImages"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"mostRecentImages"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"ListValue","values":[{"kind":"StringValue","value":"publishedAt:desc","block":false}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"mostRecentImage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"satellite"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"catalogNumberNORAD"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"publishedAt"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const ProjectsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Projects"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectFilters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectFiltersInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectFilters"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"article"}},{"kind":"Field","name":{"kind":"Name","value":"satellites"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"previewImage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"coverImage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const Get_ProjectsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GET_PROJECTS"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"ListValue","values":[{"kind":"StringValue","value":"publishedAt:desc","block":false}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"article"}},{"kind":"Field","name":{"kind":"Name","value":"satellites"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"catalogNumberNORAD"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"coverImage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attributes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"url"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"publishedAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}}]}}]}}]}}]} as unknown as DocumentNode; diff --git a/frontend/src/app/blog/page.tsx b/frontend/src/app/blog/page.tsx index 82156c8..06275cc 100644 --- a/frontend/src/app/blog/page.tsx +++ b/frontend/src/app/blog/page.tsx @@ -1,18 +1,11 @@ export const runtime = "edge"; -import { - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, -} from "@/components/ui/card"; -import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; -import Link from "next/link"; import { BlocksContent } from "@strapi/blocks-react-renderer"; -import BlockRendererClient from "@/components/BlockRendererClient"; import { getClient } from "@/lib/ApolloClient"; import { gql } from "@/__generated__/gql"; -import Image from "next/image"; +import FullBlogCard from "@/components/fullBlogCard"; +import BlogpageButtons from "@/components/BlogpageButtons"; +import { JSX } from "react"; + const HOST_URL = process.env.HOST_URL; const GET_ARTICLES = gql(` @@ -49,6 +42,7 @@ query GET_ARTICLES { publishedAt slug subtitle + Tag } } } @@ -69,87 +63,84 @@ export default async function BlogPage() { return
There are no articles to show.
; } + let firstArticle = true; + let articleList: JSX.Element[] = []; + return (
-

Blog

-

- News and other short stories about our activities are shown - here. -

-
- {graphqlData.data.articles.data.map((article) => { - let avatarURL = - article?.attributes?.author?.data?.attributes?.avatar - ?.data?.attributes?.url; + {graphqlData.data.articles.data.map((article) => { + let avatarURL = + article?.attributes?.author?.data?.attributes?.avatar?.data + ?.attributes?.url; - if (HOST_URL && avatarURL != undefined) { - avatarURL = HOST_URL + avatarURL; - } + if (HOST_URL && avatarURL != undefined) { + avatarURL = HOST_URL + avatarURL; + } - const authorName = - article?.attributes?.author?.data?.attributes?.name; - const datePublished = article?.attributes?.datePublished; - let coverImage = - article?.attributes?.coverImage?.data?.attributes?.url; - if (HOST_URL && coverImage != undefined) { - coverImage = HOST_URL + coverImage; - } - let content: BlocksContent = - article?.attributes?.body ?? []; + const authorName = + article?.attributes?.author?.data?.attributes?.name; + const tag = article?.attributes?.Tag; + const datePublished = article?.attributes?.datePublished; + let coverImage = + article?.attributes?.coverImage?.data?.attributes?.url; + if (HOST_URL && coverImage != undefined) { + coverImage = HOST_URL + coverImage; + } + let content: BlocksContent = article?.attributes?.body ?? []; - for (const block of content) { - if (block.type === "paragraph") { - content = [block]; - break; - } + const title = article?.attributes?.title; + + for (const block of content) { + if (block.type === "paragraph") { + content = [block]; + break; } + } + + if (firstArticle) { + firstArticle = false; return ( - - - - - {article?.attributes?.title} - - - - - {coverImage && ( - {coverImage} - )} - - - -
- {avatarURL && ( - - - - {// Get initials from author name - authorName - ?.split(" ") - .map((name) => name[0]) - .join("")} - - - )} -
-

{authorName}

-

{datePublished}

-
-
-
-
+
+ + {} +
+ ); + } else { + articleList.push( + , ); + } + })} +
+ {articleList.map((article) => { + return article; })}
diff --git a/frontend/src/components/BlogpageButtons.tsx b/frontend/src/components/BlogpageButtons.tsx new file mode 100644 index 0000000..8b7cd40 --- /dev/null +++ b/frontend/src/components/BlogpageButtons.tsx @@ -0,0 +1,30 @@ +"use client"; +import { useState } from "react"; +import { Button } from "./ui/button"; + +export default function BlogpageButtons() { + const [activeButton, setActiveButton] = useState("All Posts"); + + return ( +
+ + + +
+ ); +} diff --git a/frontend/src/components/fullBlogCard.tsx b/frontend/src/components/fullBlogCard.tsx new file mode 100644 index 0000000..f614833 --- /dev/null +++ b/frontend/src/components/fullBlogCard.tsx @@ -0,0 +1,82 @@ +import { + BlogCard, + BlogCardContent, + BlogCardHeader, + BlogCardTitle, +} from "@/components/ui/blogCard"; + +import BlockRendererClient from "./BlockRendererClient"; +import { Enum_Article_Tag } from "@/__generated__/graphql"; +import { BlocksContent } from "@strapi/blocks-react-renderer"; +import Link from "next/link"; + +interface BlogPost { + key: string | null | undefined; + firstArticle?: boolean | null | undefined; + title: string | undefined; + content: BlocksContent; // Or a more appropriate type if your content is structured + coverImage?: string; // Optional cover image + datePublished: any; + tag?: Enum_Article_Tag | null | undefined; // Optional tag + HOST_URL?: string; // It's common to keep the host URL separate from post data + authorName?: string; + avatarURL?: string; // Optional avatar URL + slug: string | undefined; +} + +export default function FullBlogCard(article: BlogPost) { + function formatDate(dateString: string) { + const date = new Date(dateString); + const options: Intl.DateTimeFormatOptions = { + month: "long", + day: "numeric", + year: "numeric", + }; + return date.toLocaleDateString("en-US", options); + } + + return ( + + + + {article.coverImage && ( + {article.coverImage} + )} +
+
+

+ {article.tag ? article.tag : "General"} +

+

+ {formatDate(article.datePublished)} +

+
+ + + {article.title} + + + +
+
+
+ + Read more → + +
+ ); +} diff --git a/frontend/src/components/ui/blogCard.tsx b/frontend/src/components/ui/blogCard.tsx new file mode 100644 index 0000000..c2531bf --- /dev/null +++ b/frontend/src/components/ui/blogCard.tsx @@ -0,0 +1,86 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const BlogCard = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +BlogCard.displayName = "BlogCard"; + +const BlogCardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +BlogCardHeader.displayName = "BlogCardHeader"; + +const BlogCardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +BlogCardTitle.displayName = "BlogCardTitle"; + +const BlogCardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +BlogCardDescription.displayName = "BlogCardDescription"; + +const BlogCardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +BlogCardContent.displayName = "BlogCardContent"; + +const BlogCardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +BlogCardFooter.displayName = "BlogCardFooter"; + +export { + BlogCard, + BlogCardHeader, + BlogCardFooter, + BlogCardTitle, + BlogCardDescription, + BlogCardContent, +};