Fused all the preview cards to one all-encompassing component
This commit is contained in:
		
							parent
							
								
									51f050819e
								
							
						
					
					
						commit
						add0522095
					
				| @ -20,7 +20,7 @@ interface Props { | ||||
|   langui: AppStaticProps["langui"]; | ||||
| } | ||||
| 
 | ||||
| export default function ContentTOCLine(props: Props): JSX.Element { | ||||
| export default function ContentLine(props: Props): JSX.Element { | ||||
|   const { content, langui, parentSlug } = props; | ||||
| 
 | ||||
|   const [opened, setOpened] = useState(false); | ||||
| @ -1,61 +0,0 @@ | ||||
| import Chip from "components/Chip"; | ||||
| import Img, { ImageQuality } from "components/Img"; | ||||
| import { GetContentsQuery } from "graphql/generated"; | ||||
| import Link from "next/link"; | ||||
| import { prettySlug } from "queries/helpers"; | ||||
| 
 | ||||
| interface Props { | ||||
|   item: Exclude< | ||||
|     GetContentsQuery["contents"], | ||||
|     null | undefined | ||||
|   >["data"][number]["attributes"]; | ||||
| } | ||||
| 
 | ||||
| export default function LibraryContentPreview(props: Props): JSX.Element { | ||||
|   const { item } = props; | ||||
| 
 | ||||
|   return ( | ||||
|     <Link href={`/contents/${item?.slug}`} passHref> | ||||
|       <div className="drop-shadow-shade-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform"> | ||||
|         {item?.thumbnail?.data?.attributes ? ( | ||||
|           <Img | ||||
|             className="rounded-md coarse:rounded-b-none" | ||||
|             image={item.thumbnail.data.attributes} | ||||
|             quality={ImageQuality.Medium} | ||||
|           /> | ||||
|         ) : ( | ||||
|           <div className="w-full aspect-[3/2] bg-light rounded-lg"></div> | ||||
|         )} | ||||
|         <div className="linearbg-obi fine:drop-shadow-shade-lg fine:absolute coarse:rounded-b-md bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-2"> | ||||
|           <div className="grid grid-flow-col gap-1 overflow-hidden place-content-start"> | ||||
|             {item?.type?.data?.attributes && ( | ||||
|               <Chip> | ||||
|                 {item.type.data.attributes.titles?.[0] | ||||
|                   ? item.type.data.attributes.titles[0]?.title | ||||
|                   : prettySlug(item.type.data.attributes.slug)} | ||||
|               </Chip> | ||||
|             )} | ||||
|           </div> | ||||
|           <div> | ||||
|             {item?.titles?.[0] ? ( | ||||
|               <> | ||||
|                 <p>{item.titles[0].pre_title}</p> | ||||
|                 <h1 className="text-lg">{item.titles[0].title}</h1> | ||||
|                 <h2>{item.titles[0].subtitle}</h2> | ||||
|               </> | ||||
|             ) : ( | ||||
|               <h1 className="text-lg">{prettySlug(item?.slug)}</h1> | ||||
|             )} | ||||
|           </div> | ||||
|           <div className="grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start"> | ||||
|             {item?.categories?.data.map((category) => ( | ||||
|               <Chip key={category.id} className="text-sm"> | ||||
|                 {category.attributes?.short} | ||||
|               </Chip> | ||||
|             ))} | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </Link> | ||||
|   ); | ||||
| } | ||||
| @ -1,98 +0,0 @@ | ||||
| import Chip from "components/Chip"; | ||||
| import Img, { ImageQuality } from "components/Img"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { | ||||
|   GetLibraryItemQuery, | ||||
|   GetLibraryItemsPreviewQuery, | ||||
| } from "graphql/generated"; | ||||
| import Link from "next/link"; | ||||
| import { AppStaticProps } from "queries/getAppStaticProps"; | ||||
| import { prettyDate, prettyItemSubType, prettyPrice } from "queries/helpers"; | ||||
| 
 | ||||
| interface Props { | ||||
|   className?: string; | ||||
|   item: | ||||
|     | Exclude< | ||||
|         Exclude< | ||||
|           Exclude< | ||||
|             GetLibraryItemQuery["libraryItems"], | ||||
|             null | undefined | ||||
|           >["data"][number]["attributes"], | ||||
|           null | undefined | ||||
|         >["subitems"], | ||||
|         null | undefined | ||||
|       >["data"][number]["attributes"] | ||||
|     | Exclude< | ||||
|         GetLibraryItemsPreviewQuery["libraryItems"], | ||||
|         null | undefined | ||||
|       >["data"][number]["attributes"]; | ||||
|   currencies: AppStaticProps["currencies"]; | ||||
| } | ||||
| 
 | ||||
| export default function LibraryItemsPreview(props: Props): JSX.Element { | ||||
|   const { item } = props; | ||||
|   const appLayout = useAppLayout(); | ||||
| 
 | ||||
|   return ( | ||||
|     <Link href={`/library/${item?.slug}`} passHref> | ||||
|       <div | ||||
|         className={`drop-shadow-shade-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`} | ||||
|       > | ||||
|         {item?.thumbnail?.data?.attributes ? ( | ||||
|           <Img | ||||
|             image={item.thumbnail.data.attributes} | ||||
|             quality={ImageQuality.Small} | ||||
|           /> | ||||
|         ) : ( | ||||
|           <div className="w-full aspect-[21/29.7] bg-light rounded-lg"></div> | ||||
|         )} | ||||
| 
 | ||||
|         <div className="linearbg-obi fine:drop-shadow-shade-lg fine:absolute place-items-start bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-2"> | ||||
|           {item?.metadata && item.metadata.length > 0 && item.metadata[0] && ( | ||||
|             <div className="flex flex-row gap-1"> | ||||
|               <Chip>{prettyItemSubType(item.metadata[0])}</Chip> | ||||
|             </div> | ||||
|           )} | ||||
| 
 | ||||
|           <div> | ||||
|             <h2 className="mobile:text-sm text-lg leading-5">{item?.title}</h2> | ||||
|             <h3 className="mobile:text-xs leading-3">{item?.subtitle}</h3> | ||||
|           </div> | ||||
| 
 | ||||
|           <div className="w-full grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:h-0 [scrollbar-width:none] place-content-start"> | ||||
|             {item?.categories?.data.map((category) => ( | ||||
|               <Chip key={category.id} className="text-sm"> | ||||
|                 {category.attributes?.short} | ||||
|               </Chip> | ||||
|             ))} | ||||
|           </div> | ||||
| 
 | ||||
|           {(item?.release_date || item?.price) && ( | ||||
|             <div className="grid grid-flow-col w-full"> | ||||
|               {item.release_date && ( | ||||
|                 <p className="mobile:text-xs text-sm"> | ||||
|                   <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|                     event | ||||
|                   </span> | ||||
|                   {prettyDate(item.release_date)} | ||||
|                 </p> | ||||
|               )} | ||||
|               {item.price && ( | ||||
|                 <p className="mobile:text-xs text-sm justify-self-end"> | ||||
|                   <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|                     shopping_cart | ||||
|                   </span> | ||||
|                   {prettyPrice( | ||||
|                     item.price, | ||||
|                     props.currencies, | ||||
|                     appLayout.currency | ||||
|                   )} | ||||
|                 </p> | ||||
|               )} | ||||
|             </div> | ||||
|           )} | ||||
|         </div> | ||||
|       </div> | ||||
|     </Link> | ||||
|   ); | ||||
| } | ||||
| @ -1,62 +0,0 @@ | ||||
| import Chip from "components/Chip"; | ||||
| import Img, { ImageQuality } from "components/Img"; | ||||
| import { GetPostsPreviewQuery } from "graphql/generated"; | ||||
| import Link from "next/link"; | ||||
| import { prettyDate, prettySlug } from "queries/helpers"; | ||||
| 
 | ||||
| interface Props { | ||||
|   post: Exclude< | ||||
|     GetPostsPreviewQuery["posts"], | ||||
|     null | undefined | ||||
|   >["data"][number]["attributes"]; | ||||
| } | ||||
| 
 | ||||
| export default function PostPreview(props: Props): JSX.Element { | ||||
|   const { post } = props; | ||||
| 
 | ||||
|   return ( | ||||
|     <Link href={`/news/${post?.slug}`} passHref> | ||||
|       <div className="drop-shadow-shade-xl cursor-pointer grid items-end hover:scale-[1.02] transition-transform"> | ||||
|         {post?.thumbnail?.data?.attributes ? ( | ||||
|           <Img | ||||
|             className="rounded-md rounded-b-none" | ||||
|             image={post.thumbnail.data.attributes} | ||||
|             quality={ImageQuality.Medium} | ||||
|           /> | ||||
|         ) : ( | ||||
|           <div className="w-full aspect-[3/2] bg-light rounded-lg"></div> | ||||
|         )} | ||||
|         <div className="linearbg-obi fine:drop-shadow-shade-lg rounded-b-md top-full transition-opacity z-20 grid p-4 gap-2"> | ||||
|           {post?.date && ( | ||||
|             <div className="grid grid-flow-col w-full"> | ||||
|               <p className="mobile:text-xs text-sm"> | ||||
|                 <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|                   event | ||||
|                 </span> | ||||
|                 {prettyDate(post.date)} | ||||
|               </p> | ||||
|             </div> | ||||
|           )} | ||||
| 
 | ||||
|           <div> | ||||
|             {post?.translations?.[0] ? ( | ||||
|               <> | ||||
|                 <h1 className="text-xl">{post.translations[0].title}</h1> | ||||
|                 <p>{post.translations[0].excerpt}</p> | ||||
|               </> | ||||
|             ) : ( | ||||
|               <h1 className="text-lg">{prettySlug(post?.slug)}</h1> | ||||
|             )} | ||||
|           </div> | ||||
|           <div className="grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start"> | ||||
|             {post?.categories?.data.map((category) => ( | ||||
|               <Chip key={category.id} className="text-sm"> | ||||
|                 {category.attributes?.short} | ||||
|               </Chip> | ||||
|             ))} | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </Link> | ||||
|   ); | ||||
| } | ||||
							
								
								
									
										193
									
								
								src/components/ThumbnailPreview.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								src/components/ThumbnailPreview.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,193 @@ | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| import { | ||||
|   DatePickerFragment, | ||||
|   PricePickerFragment, | ||||
|   UploadImageFragment, | ||||
| } from "graphql/generated"; | ||||
| import Link from "next/link"; | ||||
| import { AppStaticProps } from "queries/getAppStaticProps"; | ||||
| import { | ||||
|   prettyDate, | ||||
|   prettyDuration, | ||||
|   prettyPrice, | ||||
|   prettyShortenNumber, | ||||
| } from "queries/helpers"; | ||||
| import Chip from "./Chip"; | ||||
| import Img, { ImageQuality } from "./Img"; | ||||
| 
 | ||||
| interface Props { | ||||
|   thumbnail?: UploadImageFragment | string | null | undefined; | ||||
|   thumbnailAspectRatio?: string; | ||||
|   href: string; | ||||
|   pre_title?: string | null | undefined; | ||||
|   title: string | null | undefined; | ||||
|   subtitle?: string | null | undefined; | ||||
|   description?: string | null | undefined; | ||||
|   topChips?: string[]; | ||||
|   bottomChips?: string[]; | ||||
|   keepInfoVisible?: boolean; | ||||
|   metadata?: { | ||||
|     currencies?: AppStaticProps["currencies"]; | ||||
|     release_date?: DatePickerFragment | null; | ||||
|     price?: PricePickerFragment | null; | ||||
|     views?: number; | ||||
|     author?: string; | ||||
|     position: "Bottom" | "Top"; | ||||
|   }; | ||||
|   hoverlay?: { | ||||
|     __typename: "Video"; | ||||
|     duration: number; | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| export default function ThumbnailPreview(props: Props): JSX.Element { | ||||
|   const { | ||||
|     href, | ||||
|     thumbnail, | ||||
|     pre_title, | ||||
|     title, | ||||
|     subtitle, | ||||
|     description, | ||||
|     topChips, | ||||
|     bottomChips, | ||||
|     keepInfoVisible, | ||||
|     thumbnailAspectRatio, | ||||
|     metadata, | ||||
|     hoverlay, | ||||
|   } = props; | ||||
| 
 | ||||
|   const appLayout = useAppLayout(); | ||||
| 
 | ||||
|   const metadataJSX = | ||||
|     metadata && (metadata.release_date || metadata.price) ? ( | ||||
|       <div className="flex flex-row flex-wrap gap-x-3 w-full"> | ||||
|         {metadata.release_date && ( | ||||
|           <p className="mobile:text-xs text-sm"> | ||||
|             <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|               event | ||||
|             </span> | ||||
|             {prettyDate(metadata.release_date)} | ||||
|           </p> | ||||
|         )} | ||||
|         {metadata.price && metadata.currencies && ( | ||||
|           <p className="mobile:text-xs text-sm justify-self-end"> | ||||
|             <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|               shopping_cart | ||||
|             </span> | ||||
|             {prettyPrice( | ||||
|               metadata.price, | ||||
|               metadata.currencies, | ||||
|               appLayout.currency | ||||
|             )} | ||||
|           </p> | ||||
|         )} | ||||
|         {metadata.views && ( | ||||
|           <p className="mobile:text-xs text-sm"> | ||||
|             <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|               visibility | ||||
|             </span> | ||||
|             {prettyShortenNumber(metadata.views)} | ||||
|           </p> | ||||
|         )} | ||||
|         {metadata.author && ( | ||||
|           <p className="mobile:text-xs text-sm"> | ||||
|             <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|               person | ||||
|             </span> | ||||
|             {metadata.author} | ||||
|           </p> | ||||
|         )} | ||||
|       </div> | ||||
|     ) : ( | ||||
|       <></> | ||||
|     ); | ||||
| 
 | ||||
|   return ( | ||||
|     <Link href={href} passHref> | ||||
|       <div | ||||
|         className="drop-shadow-shade-xl cursor-pointer grid items-end | ||||
|         fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] | ||||
|         [--bg-opacity:0] hover:[--bg-opacity:0.5] [--play-opacity:0] | ||||
|         hover:[--play-opacity:100] transition-transform" | ||||
|       > | ||||
|         {thumbnail ? ( | ||||
|           <div className="relative"> | ||||
|             <Img | ||||
|               className={ | ||||
|                 keepInfoVisible | ||||
|                   ? "rounded-t-md" | ||||
|                   : "rounded-md coarse:rounded-b-none" | ||||
|               } | ||||
|               image={thumbnail} | ||||
|               quality={ImageQuality.Medium} | ||||
|             /> | ||||
|             {hoverlay && hoverlay.__typename === "Video" && ( | ||||
|               <> | ||||
|                 <div | ||||
|                   className="absolute inset-0 text-light grid | ||||
|                   place-content-center drop-shadow-shade-lg bg-shade | ||||
|                   bg-opacity-[var(--bg-opacity)] transition-colors" | ||||
|                 > | ||||
|                   <span | ||||
|                     className="material-icons text-6xl | ||||
|                     opacity-[var(--play-opacity)] transition-opacity" | ||||
|                   > | ||||
|                     play_circle_outline | ||||
|                   </span> | ||||
|                 </div> | ||||
|                 <div | ||||
|                   className="absolute right-2 bottom-2 text-light bg-black | ||||
|                   bg-opacity-60 px-2 rounded-full" | ||||
|                 > | ||||
|                   {prettyDuration(hoverlay.duration)} | ||||
|                 </div> | ||||
|               </> | ||||
|             )} | ||||
|           </div> | ||||
|         ) : ( | ||||
|           <div | ||||
|             className={`w-full aspect-[${thumbnailAspectRatio}] bg-light ${ | ||||
|               keepInfoVisible | ||||
|                 ? "rounded-t-md" | ||||
|                 : "rounded-md coarse:rounded-b-none" | ||||
|             }`}
 | ||||
|           ></div> | ||||
|         )} | ||||
|         <div | ||||
|           className={`linearbg-obi ${ | ||||
|             keepInfoVisible | ||||
|               ? "-mt-[0.3333em]" | ||||
|               : `fine:drop-shadow-shade-lg fine:absolute coarse:rounded-b-md
 | ||||
|               bottom-2 -inset-x-0.5 opacity-[var(--cover-opacity)]` | ||||
|           } transition-opacity z-20 grid p-4 gap-2`}
 | ||||
|         > | ||||
|           {metadata?.position === "Top" && metadataJSX} | ||||
|           {topChips && topChips.length > 0 && ( | ||||
|             <div className="grid grid-flow-col gap-1 overflow-hidden place-content-start"> | ||||
|               {topChips.map((text, index) => ( | ||||
|                 <Chip key={index}>{text}</Chip> | ||||
|               ))} | ||||
|             </div> | ||||
|           )} | ||||
|           <div> | ||||
|             {pre_title && <p>{pre_title}</p>} | ||||
|             {title && <h1 className="text-lg">{title}</h1>} | ||||
|             {subtitle && <h2>{subtitle}</h2>} | ||||
|           </div> | ||||
|           {description && <p>{description}</p>} | ||||
|           {bottomChips && bottomChips.length > 0 && ( | ||||
|             <div className="grid grid-flow-col gap-1 overflow-hidden place-content-start"> | ||||
|               {bottomChips.map((text, index) => ( | ||||
|                 <Chip key={index} className="text-sm"> | ||||
|                   {text} | ||||
|                 </Chip> | ||||
|               ))} | ||||
|             </div> | ||||
|           )} | ||||
| 
 | ||||
|           {metadata?.position === "Bottom" && metadataJSX} | ||||
|         </div> | ||||
|       </div> | ||||
|     </Link> | ||||
|   ); | ||||
| } | ||||
| @ -1,80 +0,0 @@ | ||||
| import Chip from "components/Chip"; | ||||
| import { GetVideosPreviewQuery } from "graphql/generated"; | ||||
| import Link from "next/link"; | ||||
| import { | ||||
|   getVideoThumbnailURL, | ||||
|   prettyDate, | ||||
|   prettyDuration, | ||||
|   prettyShortenNumber, | ||||
| } from "queries/helpers"; | ||||
| 
 | ||||
| interface Props { | ||||
|   video: Exclude< | ||||
|     Exclude< | ||||
|       GetVideosPreviewQuery["videos"], | ||||
|       null | undefined | ||||
|     >["data"][number]["attributes"], | ||||
|     null | undefined | ||||
|   >; | ||||
| } | ||||
| 
 | ||||
| export default function PostPreview(props: Props): JSX.Element { | ||||
|   const { video } = props; | ||||
| 
 | ||||
|   return ( | ||||
|     <Link href={`/archives/videos/v/${video.uid}`} passHref> | ||||
|       <div className="drop-shadow-shade-xl cursor-pointer grid items-end hover:scale-[1.02] [--bg-opacity:0] hover:[--bg-opacity:0.5] [--play-opacity:0] hover:[--play-opacity:100] transition-transform"> | ||||
|         <div className="relative"> | ||||
|           <img | ||||
|             className="aspect-video rounded-t-lg" | ||||
|             src={getVideoThumbnailURL(video.uid)} | ||||
|             alt={video.title} | ||||
|           /> | ||||
|           <div className="absolute inset-0 text-light grid place-content-center drop-shadow-shade-lg bg-shade bg-opacity-[var(--bg-opacity)] transition-colors"> | ||||
|             <span className="material-icons text-6xl opacity-[var(--play-opacity)] transition-opacity"> | ||||
|               play_circle_outline | ||||
|             </span> | ||||
|           </div> | ||||
|           <div className="absolute right-2 bottom-2 text-light bg-black bg-opacity-60 px-2 rounded-full"> | ||||
|             {prettyDuration(video.duration)} | ||||
|           </div> | ||||
|         </div> | ||||
|         <div className="linearbg-obi fine:drop-shadow-shade-lg rounded-b-md top-full transition-opacity z-20 grid p-4 gap-2"> | ||||
|           <div className="flex flex-row flex-wrap gap-x-3 w-full"> | ||||
|             <p className="mobile:text-xs text-sm"> | ||||
|               <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|                 event | ||||
|               </span> | ||||
|               {prettyDate(video.published_date)} | ||||
|             </p> | ||||
|             <p className="mobile:text-xs text-sm"> | ||||
|               <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|                 visibility | ||||
|               </span> | ||||
|               {prettyShortenNumber(video.views)} | ||||
|             </p> | ||||
|             {video.channel?.data?.attributes && ( | ||||
|               <p className="mobile:text-xs text-sm"> | ||||
|                 <span className="material-icons !text-base translate-y-[.15em] mr-1"> | ||||
|                   person | ||||
|                 </span> | ||||
|                 {video.channel.data.attributes.title} | ||||
|               </p> | ||||
|             )} | ||||
|           </div> | ||||
| 
 | ||||
|           <div> | ||||
|             <h1 className="text-xl">{video.title}</h1> | ||||
|           </div> | ||||
|           <div className="grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start"> | ||||
|             {video.categories?.data.map((category) => ( | ||||
|               <Chip key={category.id} className="text-sm"> | ||||
|                 {category.attributes?.short} | ||||
|               </Chip> | ||||
|             ))} | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </Link> | ||||
|   ); | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| import ChronologyItemComponent from "components/Chronology/ChronologyItemComponent"; | ||||
| import ChronologyItemComponent from "components/Wiki/Chronology/ChronologyItemComponent"; | ||||
| import { GetChronologyItemsQuery } from "graphql/generated"; | ||||
| import { AppStaticProps } from "queries/getAppStaticProps"; | ||||
| 
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint