@@ -15,6 +15,7 @@ import {
15
15
Image ,
16
16
Input ,
17
17
Loader ,
18
+ type MantineStyleProp ,
18
19
Menu ,
19
20
Modal ,
20
21
NumberInput ,
@@ -28,6 +29,7 @@ import {
28
29
Text ,
29
30
TextInput ,
30
31
Textarea ,
32
+ ThemeIcon ,
31
33
Title ,
32
34
Tooltip ,
33
35
useComputedColorScheme ,
@@ -50,6 +52,7 @@ import {
50
52
type ReviewItem ,
51
53
type UserMediaReminderPartFragment ,
52
54
UserReviewScale ,
55
+ UserToMediaReason ,
53
56
Visibility ,
54
57
} from "@ryot/generated/graphql/backend/graphql" ;
55
58
import { changeCase , formatDateToNaiveDate , getInitials } from "@ryot/ts-utils" ;
@@ -58,10 +61,12 @@ import {
58
61
IconArrowBigUp ,
59
62
IconArrowsRight ,
60
63
IconBackpack ,
64
+ IconBookmarksFilled ,
61
65
IconCheck ,
62
66
IconCloudDownload ,
63
67
IconEdit ,
64
68
IconPercentage ,
69
+ IconRosetteDiscountCheck ,
65
70
IconStarFilled ,
66
71
IconTrash ,
67
72
IconX ,
@@ -444,6 +449,12 @@ export const ReviewItemDisplay = (props: {
444
449
) ;
445
450
} ;
446
451
452
+ const blackBgStyles = {
453
+ backgroundColor : "rgba(0, 0, 0, 0.75)" ,
454
+ borderRadius : 3 ,
455
+ padding : 2 ,
456
+ } satisfies MantineStyleProp ;
457
+
447
458
export const BaseDisplayItem = ( props : {
448
459
name : string ;
449
460
onClick ?: ( e : React . MouseEvent ) => Promise < void > ;
@@ -457,6 +468,7 @@ export const BaseDisplayItem = (props: {
457
468
highlightRightText ?: string ;
458
469
children ?: ReactNode ;
459
470
nameRight ?: JSX . Element ;
471
+ mediaReason ?: UserToMediaReason [ ] ;
460
472
} ) => {
461
473
const colorScheme = useComputedColorScheme ( "dark" ) ;
462
474
@@ -480,13 +492,18 @@ export const BaseDisplayItem = (props: {
480
492
</ Box >
481
493
) ;
482
494
495
+ const themeIconSurrounder = ( idx : number , icon ?: JSX . Element ) => (
496
+ < ThemeIcon variant = "transparent" size = "sm" color = "lime" key = { idx } >
497
+ { icon }
498
+ </ ThemeIcon >
499
+ ) ;
500
+
483
501
return (
484
502
< Flex
485
503
key = { `${ props . bottomLeft } -${ props . bottomRight } -${ props . name } ` }
486
504
align = "center"
487
505
justify = "center"
488
506
direction = "column"
489
- pos = "relative"
490
507
>
491
508
{ props . topLeft }
492
509
< SurroundingElement style = { { flex : "none" } } pos = "relative" >
@@ -510,7 +527,32 @@ export const BaseDisplayItem = (props: {
510
527
getInitials ( props . name ) ,
511
528
) }
512
529
/>
513
- { props . topRight }
530
+ < Box pos = "absolute" top = { 5 } right = { 5 } >
531
+ { props . topRight }
532
+ </ Box >
533
+ { props . mediaReason ? (
534
+ < Group
535
+ style = { blackBgStyles }
536
+ pos = "absolute"
537
+ bottom = { 5 }
538
+ left = { 5 }
539
+ gap = "xs"
540
+ >
541
+ { props . mediaReason
542
+ . map ( ( r ) =>
543
+ match ( r )
544
+ . with ( UserToMediaReason . Seen , ( ) => (
545
+ < IconRosetteDiscountCheck />
546
+ ) )
547
+ . with ( UserToMediaReason . Watchlist , ( ) => (
548
+ < IconBookmarksFilled />
549
+ ) )
550
+ . otherwise ( ( ) => undefined ) ,
551
+ )
552
+ . filter ( Boolean )
553
+ . map ( ( icon , idx ) => themeIconSurrounder ( idx , icon ) ) }
554
+ </ Group >
555
+ ) : null }
514
556
</ SurroundingElement >
515
557
< Flex w = "100%" direction = "column" px = { { base : 10 , md : 3 } } py = { 4 } >
516
558
< Flex justify = "space-between" direction = "row" w = "100%" >
@@ -563,8 +605,10 @@ export const MediaItemWithoutUpdateModal = (props: {
563
605
noHref ?: boolean ;
564
606
onClick ?: ( e : React . MouseEvent ) => Promise < void > ;
565
607
nameRight ?: JSX . Element ;
608
+ mediaReason ?: UserToMediaReason [ ] ;
566
609
} ) => {
567
610
const navigate = useNavigate ( ) ;
611
+ const id = props . item . identifier ;
568
612
569
613
return (
570
614
< BaseDisplayItem
@@ -575,25 +619,19 @@ export const MediaItemWithoutUpdateModal = (props: {
575
619
? props . href
576
620
: match ( props . entityLot )
577
621
. with ( EntityLot . Media , undefined , null , ( ) =>
578
- $path ( "/media/item/:id" , { id : props . item . identifier } ) ,
622
+ $path ( "/media/item/:id" , { id } ) ,
579
623
)
580
624
. with ( EntityLot . MediaGroup , ( ) =>
581
- $path ( "/media/groups/item/:id" , {
582
- id : props . item . identifier ,
583
- } ) ,
625
+ $path ( "/media/groups/item/:id" , { id } ) ,
584
626
)
585
627
. with ( EntityLot . Person , ( ) =>
586
- $path ( "/media/people/item/:id" , {
587
- id : props . item . identifier ,
588
- } ) ,
628
+ $path ( "/media/people/item/:id" , { id } ) ,
589
629
)
590
630
. with ( EntityLot . Exercise , ( ) =>
591
- $path ( "/fitness/exercises/item/:id" , {
592
- id : props . item . identifier ,
593
- } ) ,
631
+ $path ( "/fitness/exercises/item/:id" , { id } ) ,
594
632
)
595
633
. with ( EntityLot . Collection , ( ) =>
596
- $path ( "/collections/:id" , { id : props . item . identifier } ) ,
634
+ $path ( "/collections/:id" , { id } ) ,
597
635
)
598
636
. exhaustive ( )
599
637
: undefined
@@ -613,18 +651,10 @@ export const MediaItemWithoutUpdateModal = (props: {
613
651
/>
614
652
) : null
615
653
}
654
+ mediaReason = { props . mediaReason }
616
655
topRight = {
617
656
props . averageRating ? (
618
- < Box
619
- p = { 2 }
620
- pos = "absolute"
621
- top = { 5 }
622
- right = { 5 }
623
- style = { {
624
- backgroundColor : "rgba(0, 0, 0, 0.75)" ,
625
- borderRadius : 3 ,
626
- } }
627
- >
657
+ < Box style = { blackBgStyles } >
628
658
< Flex align = "center" gap = { 4 } >
629
659
< IconStarFilled size = { 12 } style = { { color : "#EBE600FF" } } />
630
660
< Text c = "white" size = "xs" fw = "bold" pr = { 4 } >
@@ -656,11 +686,7 @@ export const MediaItemWithoutUpdateModal = (props: {
656
686
onClick = { ( e ) => {
657
687
e . preventDefault ( ) ;
658
688
navigate (
659
- $path (
660
- "/media/item/:id" ,
661
- { id : props . item . identifier } ,
662
- { openReviewModal : true } ,
663
- ) ,
689
+ $path ( "/media/item/:id" , { id } , { openReviewModal : true } ) ,
664
690
) ;
665
691
} }
666
692
>
0 commit comments