11import { useEffect , useState } from "react" ;
22import { useHistory , useParams } from "react-router" ;
3- import { Box , CircularProgress , Typography , Button } from "@mui/material" ;
3+ import {
4+ Box ,
5+ CircularProgress ,
6+ Typography ,
7+ Button ,
8+ TextField ,
9+ InputAdornment ,
10+ } from "@mui/material" ;
411import AddRoundedIcon from "@mui/icons-material/AddRounded" ;
12+ import SearchRoundedIcon from "@mui/icons-material/SearchRounded" ;
513import {
614 useGetContentModelItemsQuery ,
715 useGetContentModelsQuery ,
@@ -12,22 +20,22 @@ import { fetchModels } from "../../../shell/store/models";
1220import { useDispatch } from "react-redux" ;
1321import { fetchFields } from "../../../shell/store/fields" ;
1422import { useParams as useSearchParams } from "../../../shell/hooks/useParams" ;
23+ import { ContentItem } from "shell/services/types" ;
24+ import SearchBox from "shell/components/SearchBox" ;
25+ import blockPlaceholder from "../../../../public/images/blockPlaceholder.png" ;
1526
1627export const BlockModel = ( ) => {
1728 const dispatch = useDispatch ( ) ;
29+ const history = useHistory ( ) ;
1830 const { modelZUID } = useParams < {
1931 modelZUID : string ;
2032 } > ( ) ;
21- const history = useHistory ( ) ;
2233 const [ params ] = useSearchParams ( ) ;
23- const [ renderFlag , setRenderFlag ] = useState ( false ) ;
2434 const [ showCreateVariantDialog , setShowCreateVariantDialog ] = useState ( false ) ;
25- const { data, isFetching, error, isUninitialized } =
35+ const [ search , setSearch ] = useState ( "" ) ;
36+ const { data, isLoading, error, isUninitialized } =
2637 useGetContentModelItemsQuery ( {
2738 modelZUID,
28- params : {
29- limit : 1 ,
30- } ,
3139 } ) ;
3240
3341 const { data : models } = useGetContentModelsQuery ( ) ;
@@ -38,46 +46,110 @@ export const BlockModel = () => {
3846 dispatch ( fetchFields ( modelZUID ) ) ;
3947 } , [ ] ) ;
4048
41- useEffect ( ( ) => {
42- if ( data ?. length && ! isFetching && ! error ) {
43- history . push ( `/blocks/${ modelZUID } /${ data ?. [ 0 ] ?. meta ?. ZUID } ` ) ;
44- }
45-
46- if ( ! isFetching && ! isUninitialized && ! data ?. length ) {
47- setRenderFlag ( true ) ;
48- }
49- } , [ data , isFetching , error , history ] ) ;
50-
5149 useEffect ( ( ) => {
5250 setShowCreateVariantDialog ( ! ! params ?. get ( "createVariant" ) ) ;
5351 } , [ params ] ) ;
5452
5553 const model = models ?. find ( ( model ) => model . ZUID === modelZUID ) ;
5654
57- if ( renderFlag ) {
55+ if ( isLoading || isUninitialized ) {
5856 return (
59- < >
57+ < Box
58+ display = "flex"
59+ justifyContent = "center"
60+ alignItems = "center"
61+ height = "100%"
62+ width = "100%"
63+ >
64+ < CircularProgress />
65+ </ Box >
66+ ) ;
67+ }
68+
69+ return (
70+ < >
71+ < Box
72+ width = "100%"
73+ display = "flex"
74+ flexDirection = "column"
75+ sx = { { backgroundColor : "grey.50" } }
76+ >
6077 < Box
61- width = "100%"
6278 display = "flex"
63- flexDirection = "column"
64- sx = { { backgroundColor : "grey.50" } }
79+ justifyContent = "space-between"
80+ alignItems = "center"
81+ px = { 4 }
82+ pt = { 4 }
83+ pb = { 1.75 }
84+ sx = { {
85+ borderBottom : ( theme ) => `2px solid ${ theme . palette . border } ` ,
86+ backgroundColor : "background.paper" ,
87+ } }
6588 >
89+ < Typography variant = "h3" fontWeight = "700" >
90+ { model ?. label }
91+ </ Typography >
92+ < Box display = { "flex" } alignItems = "center" gap = { 2 } >
93+ < SearchBox
94+ data-cy = "search-blocks-input"
95+ value = { search }
96+ onChange = { ( event ) => setSearch ( event . target . value ) }
97+ size = "small"
98+ sx = { {
99+ width : "240px" ,
100+ "& .MuiOutlinedInput-notchedOutline" : {
101+ border : 0 ,
102+ } ,
103+ } }
104+ InputProps = { {
105+ sx : {
106+ backgroundColor : "grey.50" ,
107+ } ,
108+ startAdornment : (
109+ < InputAdornment position = "start" >
110+ < SearchRoundedIcon fontSize = "small" color = "action" />
111+ </ InputAdornment >
112+ ) ,
113+ } }
114+ placeholder = "Search Variants"
115+ />
116+ < Button
117+ variant = "contained"
118+ size = "small"
119+ startIcon = { < AddRoundedIcon /> }
120+ onClick = { ( ) => setShowCreateVariantDialog ( true ) }
121+ data-cy = "create-variant-button-header"
122+ >
123+ Create Variant
124+ </ Button >
125+ </ Box >
126+ </ Box >
127+ { data ?. length ? (
66128 < Box
129+ px = { 4.5 }
130+ py = { 4 }
67131 display = "flex"
68- justifyContent = "space-between"
69- px = { 4 }
70- pt = { 4 }
71- pb = { 1.75 }
132+ gap = { 2 }
133+ flexWrap = { "wrap" }
72134 sx = { {
73- borderBottom : ( theme ) => `2px solid ${ theme . palette . border } ` ,
74- backgroundColor : "background.paper" ,
135+ overflowY : "scroll" ,
75136 } }
76137 >
77- < Typography variant = "h3" fontWeight = "700" >
78- { model ?. label }
79- </ Typography >
138+ { data
139+ ?. filter ?.( ( item ) =>
140+ item . web . metaTitle . toLowerCase ( ) . includes ( search . toLowerCase ( ) )
141+ )
142+ ?. map ( ( item ) => (
143+ < BlockVariantCard
144+ key = { item . meta . ZUID }
145+ item = { item }
146+ onClick = { ( ) => {
147+ history . push ( `/blocks/${ modelZUID } /${ item . meta . ZUID } ` ) ;
148+ } }
149+ />
150+ ) ) }
80151 </ Box >
152+ ) : (
81153 < Box
82154 display = "flex"
83155 height = "100%"
@@ -112,26 +184,72 @@ export const BlockModel = () => {
112184 />
113185 </ Box >
114186 </ Box >
115- </ Box >
116- { showCreateVariantDialog && (
117- < CreateVariantDialog
118- onClose = { ( ) => setShowCreateVariantDialog ( false ) }
119- model = { model }
120- />
121187 ) }
122- </ >
123- ) ;
124- }
188+ </ Box >
189+ { showCreateVariantDialog && (
190+ < CreateVariantDialog
191+ onClose = { ( ) => setShowCreateVariantDialog ( false ) }
192+ model = { model }
193+ />
194+ ) }
195+ </ >
196+ ) ;
197+ } ;
198+
199+ type BlockVariantCardProps = {
200+ item : ContentItem ;
201+ onClick : ( ) => void ;
202+ } ;
125203
204+ const BlockVariantCard = ( { item, onClick } : BlockVariantCardProps ) => {
205+ const [ noImage , setNoImage ] = useState ( false ) ;
126206 return (
127207 < Box
128- display = "flex"
129- justifyContent = "center"
130- alignItems = "center"
131- height = "100%"
132- width = "100%"
208+ key = { item . meta . ZUID }
209+ width = { 265 }
210+ sx = { {
211+ border : ( theme ) => `1px solid ${ theme . palette . border } ` ,
212+ boxSizing : "border-box" ,
213+ cursor : "pointer" ,
214+ } }
215+ onClick = { onClick }
133216 >
134- < CircularProgress />
217+ < Box px = { 1 } pt = { 1 } pb = { 1.75 } >
218+ { ! noImage ? (
219+ < Box
220+ component = "img"
221+ src = { item . data . og_image as string }
222+ minHeight = { 146 }
223+ maxHeight = { 146 }
224+ width = "100%"
225+ sx = { { objectFit : "contain" } }
226+ onError = { ( e : any ) => {
227+ setNoImage ( true ) ;
228+ } }
229+ />
230+ ) : (
231+ < Box
232+ minHeight = { 146 }
233+ maxHeight = { 146 }
234+ width = "100%"
235+ component = "img"
236+ sx = { { objectFit : "contain" } }
237+ src = { blockPlaceholder }
238+ />
239+ ) }
240+ </ Box >
241+ < Box
242+ py = { 2 }
243+ px = { 1 }
244+ sx = { {
245+ backgroundColor : "background.paper" ,
246+ } }
247+ height = { 52 }
248+ >
249+ < Typography noWrap variant = "body2" >
250+ { item . web . metaTitle }
251+ </ Typography >
252+ </ Box >
135253 </ Box >
136254 ) ;
137255} ;
0 commit comments