From 90b973a7f5b8ae3231778594192cda39ce2721cd Mon Sep 17 00:00:00 2001 From: Saleem Hadad Date: Thu, 28 Mar 2024 09:11:32 +0400 Subject: [PATCH] add category search functionality --- app/Models/Category.php | 14 ++++- graphql/schema.graphql | 2 +- public/js/app.js | 2 +- public/mix-manifest.json | 2 +- resources/js/Api/categories.js | 12 ++-- resources/js/Pages/Category/Index.js | 61 +++++++++++++++---- tests/Unit/Models/Categories/CategoryTest.php | 11 ++++ 7 files changed, 82 insertions(+), 22 deletions(-) diff --git a/app/Models/Category.php b/app/Models/Category.php index 96d00b2..c416661 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -2,10 +2,12 @@ namespace App\Models; +use App\Contracts\Searchable; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; -class Category extends Model +class Category extends Model implements Searchable { use HasFactory; @@ -27,4 +29,14 @@ public function brands() { return $this->hasMany(Brand::class); } + + /** + * @param $query + * @return Builder + */ + public static function search($query): Builder + { + return (new static())->newQuery() + ->where('name', 'LIKE', "%$query%"); + } } diff --git a/graphql/schema.graphql b/graphql/schema.graphql index c6d4c9d..1983785 100644 --- a/graphql/schema.graphql +++ b/graphql/schema.graphql @@ -53,7 +53,7 @@ type Query { @orderBy(column: id direction: DESC) allCategories: [Category!]! @all - categories: [Category!]! + categories(search: String @search): [Category!]! @paginate(defaultCount: 50) @orderBy(column: id direction: DESC) diff --git a/public/js/app.js b/public/js/app.js index d2ef144..8d3f74a 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,2 +1,2 @@ /*! For license information please see app.js.LICENSE.txt */ -(()=>{var e,t={2207:(e,t,n)=>{e.exports=n(7452)},8368:(e,t,n)=>{function r(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var i=r(n(8142)),o=n(6540),a=r(o),s=n(8646);function l(){return(l=Object.assign||function(e){for(var t=1;t"}(t);return t.props.children&&(n+=function(t){return"string"==typeof t.props.children?t.props.children:t.props.children.reduce((function(t,n){return t+e(n)}),"")}(t)),t.props.dangerouslySetInnerHTML&&(n+=t.props.dangerouslySetInnerHTML.__html),function(e){return["area","base","br","col","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"].indexOf(e.type)>-1}(t)||(n+=""),n}(function(e){return a.cloneElement(e,{inertia:void 0!==e.props["head-key"]?e.props["head-key"]:""})}(e))}(e)})),i&&!n.find((function(e){return e.startsWith(""+i+""),n)),null}f.displayName="InertiaHeadContext",d.displayName="Inertia";var p=["children","as","data","href","method","preserveScroll","preserveState","replace","only","headers","onClick","onCancelToken","onBefore","onStart","onProgress","onFinish","onCancel","onSuccess","onError"],g=function(){},m=o.forwardRef((function(e,t){var n=e.children,r=e.as,i=void 0===r?"a":r,a=e.data,u=void 0===a?{}:a,c=e.href,f=e.method,d=void 0===f?"get":f,h=e.preserveScroll,m=void 0!==h&&h,y=e.preserveState,v=void 0===y?null:y,b=e.replace,x=void 0!==b&&b,w=e.only,_=void 0===w?[]:w,S=e.headers,k=void 0===S?{}:S,E=e.onClick,A=void 0===E?g:E,O=e.onCancelToken,j=void 0===O?g:O,C=e.onBefore,P=void 0===C?g:C,N=e.onStart,M=void 0===N?g:N,T=e.onProgress,I=void 0===T?g:T,D=e.onFinish,R=void 0===D?g:D,L=e.onCancel,F=void 0===L?g:L,B=e.onSuccess,z=void 0===B?g:B,U=e.onError,V=void 0===U?g:U,W=function(e,t){if(null==e)return{};var n,r,i={},o=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}(e,p),$=o.useCallback((function(e){A(e),s.shouldIntercept(e)&&(e.preventDefault(),s.Inertia.visit(c,{data:u,method:d,preserveScroll:m,preserveState:null!=v?v:"get"!==d,replace:x,only:_,headers:k,onCancelToken:j,onBefore:P,onStart:M,onProgress:I,onFinish:R,onCancel:F,onSuccess:z,onError:V}))}),[u,c,d,m,v,x,_,k,A,j,P,M,I,R,F,z,V]);i=i.toLowerCase(),d=d.toLowerCase();var H=s.mergeDataIntoQueryString(d,c||"",u);return c=H[0],u=H[1],"a"===i&&"get"!==d&&console.warn('Creating POST/PUT/PATCH/DELETE links is discouraged as it causes "Open Link in New Tab/Window" accessibility issues.\n\nPlease specify a more appropriate element using the "as" attribute. For example:\n\n...'),o.createElement(i,l({},W,"a"===i?{href:c}:{},{ref:t,onClick:$}),n)}));t.p3=h,t.N_=m,t.sj=function(e){try{var t,n,r,i,a,s,l;n=void 0===(t=e.id)?"app":t,r=e.resolve,i=e.setup,a=e.title,s=e.page,l=e.render;var u="undefined"==typeof window,c=u?null:document.getElementById(n),f=s||JSON.parse(c.dataset.page),h=function(e){return Promise.resolve(r(e)).then((function(e){return e.default||e}))},p=[];return Promise.resolve(h(f.component).then((function(e){return i({el:c,App:d,props:{initialPage:f,initialComponent:e,resolveComponent:h,titleCallback:a,onHeadUpdate:u?function(e){return p=e}:null}})}))).then((function(e){return function(){if(u)return Promise.resolve(l(o.createElement("div",{id:n,"data-page":JSON.stringify(f)},e))).then((function(e){return{head:p,body:e}}))}()}))}catch(e){return Promise.reject(e)}},t.mN=function(){var e=[].slice.call(arguments),t=o.useRef(null),n="string"==typeof e[0]?e[0]:null,r=("string"==typeof e[0]?e[1]:e[0])||{},a=o.useRef(null),c=o.useRef(null),f=n?u(r,n+":data"):o.useState(r),d=f[0],h=f[1],p=n?u({},n+":errors"):o.useState({}),g=p[0],m=p[1],y=o.useState(!1),v=y[0],b=y[1],x=o.useState(!1),w=x[0],_=x[1],S=o.useState(null),k=S[0],E=S[1],A=o.useState(!1),O=A[0],j=A[1],C=o.useState(!1),P=C[0],N=C[1],M=function(e){return e};o.useEffect((function(){return t.current=!0,function(){t.current=!1}}),[]);var T=o.useCallback((function(e,n,r){void 0===r&&(r={});var i=l({},r,{onCancelToken:function(e){if(a.current=e,r.onCancelToken)return r.onCancelToken(e)},onBefore:function(e){if(j(!1),N(!1),clearTimeout(c.current),r.onBefore)return r.onBefore(e)},onStart:function(e){if(_(!0),r.onStart)return r.onStart(e)},onProgress:function(e){if(E(e),r.onProgress)return r.onProgress(e)},onSuccess:function(e){if(t.current&&(_(!1),E(null),m({}),b(!1),j(!0),N(!0),c.current=setTimeout((function(){t.current&&N(!1)}),2e3)),r.onSuccess)return r.onSuccess(e)},onError:function(e){if(t.current&&(_(!1),E(null),m(e),b(!0)),r.onError)return r.onError(e)},onCancel:function(){if(t.current&&(_(!1),E(null)),r.onCancel)return r.onCancel()},onFinish:function(){if(t.current&&(_(!1),E(null)),a.current=null,r.onFinish)return r.onFinish()}});"delete"===e?s.Inertia.delete(n,l({},i,{data:M(d)})):s.Inertia[e](n,M(d),i)}),[d,m]);return{data:d,setData:function(e,t){var n;h("string"==typeof e?l({},d,((n={})[e]=t,n)):"function"==typeof e?function(t){return e(t)}:e)},isDirty:!i(d,r),errors:g,hasErrors:v,processing:w,progress:k,wasSuccessful:O,recentlySuccessful:P,transform:function(e){M=e},reset:function(){var e=[].slice.call(arguments);h(0===e.length?r:Object.keys(r).filter((function(t){return e.includes(t)})).reduce((function(e,t){return e[t]=r[t],e}),l({},d)))},clearErrors:function(){var e=[].slice.call(arguments);m(Object.keys(g).reduce((function(t,n){var r;return l({},t,e.length>0&&!e.includes(n)?((r={})[n]=g[n],r):{})}),{})),b(Object.keys(g).length>0)},submit:T,get:function(e,t){T("get",e,t)},post:function(e,t){T("post",e,t)},put:function(e,t){T("put",e,t)},patch:function(e,t){T("patch",e,t)},delete:function(e,t){T("delete",e,t)},cancel:function(){a.current&&a.current.cancel()}}}},8646:(e,t,n)=>{function r(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var i=r(n(2505)),o=n(5373),a=r(n(4744));function s(){return(s=Object.assign||function(e){for(var t=1;t0&&"back_forward"===window.performance.getEntriesByType("navigation")[0].type},n.handleBackForwardVisit=function(e){var t=this;window.history.state.version=e.version,this.setPage(window.history.state,{preserveScroll:!0,preserveState:!0}).then((function(){t.restoreScrollPositions(),b(e)}))},n.locationVisit=function(e,t){try{window.sessionStorage.setItem("inertiaLocationVisit",JSON.stringify({preserveScroll:t})),window.location.href=e.href,m(window.location).href===m(e).href&&window.location.reload()}catch(e){return!1}},n.isLocationVisit=function(){try{return null!==window.sessionStorage.getItem("inertiaLocationVisit")}catch(e){return!1}},n.handleLocationVisit=function(e){var t,n,r,i,o=this,a=JSON.parse(window.sessionStorage.getItem("inertiaLocationVisit")||"");window.sessionStorage.removeItem("inertiaLocationVisit"),e.url+=window.location.hash,e.rememberedState=null!=(t=null==(n=window.history.state)?void 0:n.rememberedState)?t:{},e.scrollRegions=null!=(r=null==(i=window.history.state)?void 0:i.scrollRegions)?r:[],this.setPage(e,{preserveScroll:a.preserveScroll,preserveState:!0}).then((function(){a.preserveScroll&&o.restoreScrollPositions(),b(e)}))},n.isLocationVisitResponse=function(e){return e&&409===e.status&&e.headers["x-inertia-location"]},n.isInertiaResponse=function(e){return null==e?void 0:e.headers["x-inertia"]},n.createVisitId=function(){return this.visitId={},this.visitId},n.cancelVisit=function(e,t){var n=t.cancelled,r=void 0!==n&&n,i=t.interrupted,o=void 0!==i&&i;!e||e.completed||e.cancelled||e.interrupted||(e.cancelToken.cancel(),e.onCancel(),e.completed=!1,e.cancelled=r,e.interrupted=o,v(e),e.onFinish(e))},n.finishVisit=function(e){e.cancelled||e.interrupted||(e.completed=!0,e.cancelled=!1,e.interrupted=!1,v(e),e.onFinish(e))},n.resolvePreserveOption=function(e,t){return"function"==typeof e?e(t):"errors"===e?Object.keys(t.props.errors||{}).length>0:e},n.visit=function(e,n){var r=this,o=void 0===n?{}:n,a=o.method,l=void 0===a?t.Method.GET:a,c=o.data,d=void 0===c?{}:c,h=o.replace,v=void 0!==h&&h,b=o.preserveScroll,x=void 0!==b&&b,w=o.preserveState,_=void 0!==w&&w,S=o.only,k=void 0===S?[]:S,E=o.headers,A=void 0===E?{}:E,O=o.errorBag,j=void 0===O?"":O,C=o.forceFormData,P=void 0!==C&&C,N=o.onCancelToken,M=void 0===N?function(){}:N,T=o.onBefore,I=void 0===T?function(){}:T,D=o.onStart,R=void 0===D?function(){}:D,L=o.onProgress,F=void 0===L?function(){}:L,B=o.onFinish,z=void 0===B?function(){}:B,U=o.onCancel,V=void 0===U?function(){}:U,W=o.onSuccess,$=void 0===W?function(){}:W,H=o.onError,q=void 0===H?function(){}:H,Y="string"==typeof e?p(e):e;if(!function e(t){return t instanceof File||t instanceof Blob||t instanceof FileList&&t.length>0||t instanceof FormData&&Array.from(t.values()).some((function(t){return e(t)}))||"object"==typeof t&&null!==t&&Object.values(t).some((function(t){return e(t)}))}(d)&&!P||d instanceof FormData||(d=f(d)),!(d instanceof FormData)){var X=g(l,Y,d),G=X[1];Y=p(X[0]),d=G}var K={url:Y,method:l,data:d,replace:v,preserveScroll:x,preserveState:_,only:k,headers:A,errorBag:j,forceFormData:P,cancelled:!1,completed:!1,interrupted:!1};if(!1!==I(K)&&function(e){return y("before",{cancelable:!0,detail:{visit:e}})}(K)){this.activeVisit&&this.cancelVisit(this.activeVisit,{interrupted:!0}),this.saveScrollPositions();var Q=this.createVisitId();this.activeVisit=s({},K,{onCancelToken:M,onBefore:I,onStart:R,onProgress:F,onFinish:z,onCancel:V,onSuccess:$,onError:q,cancelToken:i.CancelToken.source()}),M({cancel:function(){r.activeVisit&&r.cancelVisit(r.activeVisit,{cancelled:!0})}}),function(e){y("start",{detail:{visit:e}})}(K),R(K),i({method:l,url:m(Y).href,data:l===t.Method.GET?{}:d,params:l===t.Method.GET?d:{},cancelToken:this.activeVisit.cancelToken.token,headers:s({},A,{Accept:"text/html, application/xhtml+xml","X-Requested-With":"XMLHttpRequest","X-Inertia":!0},k.length?{"X-Inertia-Partial-Component":this.page.component,"X-Inertia-Partial-Data":k.join(",")}:{},j&&j.length?{"X-Inertia-Error-Bag":j}:{},this.page.version?{"X-Inertia-Version":this.page.version}:{}),onUploadProgress:function(e){d instanceof FormData&&(e.percentage=Math.round(e.loaded/e.total*100),function(e){y("progress",{detail:{progress:e}})}(e),F(e))}}).then((function(e){var t;if(!r.isInertiaResponse(e))return Promise.reject({response:e});var n=e.data;k.length&&n.component===r.page.component&&(n.props=s({},r.page.props,n.props)),x=r.resolvePreserveOption(x,n),(_=r.resolvePreserveOption(_,n))&&null!=(t=window.history.state)&&t.rememberedState&&n.component===r.page.component&&(n.rememberedState=window.history.state.rememberedState);var i=Y,o=p(n.url);return i.hash&&!o.hash&&m(i).href===o.href&&(o.hash=i.hash,n.url=o.href),r.setPage(n,{visitId:Q,replace:v,preserveScroll:x,preserveState:_})})).then((function(){var e=r.page.props.errors||{};if(Object.keys(e).length>0){var t=j?e[j]?e[j]:{}:e;return function(e){y("error",{detail:{errors:e}})}(t),q(t)}return y("success",{detail:{page:r.page}}),$(r.page)})).catch((function(e){if(r.isInertiaResponse(e.response))return r.setPage(e.response.data,{visitId:Q});if(r.isLocationVisitResponse(e.response)){var t=p(e.response.headers["x-inertia-location"]),n=Y;n.hash&&!t.hash&&m(n).href===t.href&&(t.hash=n.hash),r.locationVisit(t,!0===x)}else{if(!e.response)return Promise.reject(e);y("invalid",{cancelable:!0,detail:{response:e.response}})&&u.show(e.response.data)}})).then((function(){r.activeVisit&&r.finishVisit(r.activeVisit)})).catch((function(e){if(!i.isCancel(e)){var t=y("exception",{cancelable:!0,detail:{exception:e}});if(r.activeVisit&&r.finishVisit(r.activeVisit),t)return Promise.reject(e)}}))}},n.setPage=function(e,t){var n=this,r=void 0===t?{}:t,i=r.visitId,o=void 0===i?this.createVisitId():i,a=r.replace,s=void 0!==a&&a,l=r.preserveScroll,u=void 0!==l&&l,c=r.preserveState,f=void 0!==c&&c;return Promise.resolve(this.resolveComponent(e.component)).then((function(t){o===n.visitId&&(e.scrollRegions=e.scrollRegions||[],e.rememberedState=e.rememberedState||{},(s=s||p(e.url).href===window.location.href)?n.replaceState(e):n.pushState(e),n.swapComponent({component:t,page:e,preserveState:f}).then((function(){u||n.resetScrollPositions(),s||b(e)})))}))},n.pushState=function(e){this.page=e,window.history.pushState(e,"",e.url)},n.replaceState=function(e){this.page=e,window.history.replaceState(e,"",e.url)},n.handlePopstateEvent=function(e){var t=this;if(null!==e.state){var n=e.state,r=this.createVisitId();Promise.resolve(this.resolveComponent(n.component)).then((function(e){r===t.visitId&&(t.page=n,t.swapComponent({component:e,page:n,preserveState:!1}).then((function(){t.restoreScrollPositions(),b(n)})))}))}else{var i=p(this.page.url);i.hash=window.location.hash,this.replaceState(s({},this.page,{url:i.href})),this.resetScrollPositions()}},n.get=function(e,n,r){return void 0===n&&(n={}),void 0===r&&(r={}),this.visit(e,s({},r,{method:t.Method.GET,data:n}))},n.reload=function(e){return void 0===e&&(e={}),this.visit(window.location.href,s({},e,{preserveScroll:!0,preserveState:!0}))},n.replace=function(e,t){var n;return void 0===t&&(t={}),console.warn("Inertia.replace() has been deprecated and will be removed in a future release. Please use Inertia."+(null!=(n=t.method)?n:"get")+"() instead."),this.visit(e,s({preserveState:!0},t,{replace:!0}))},n.post=function(e,n,r){return void 0===n&&(n={}),void 0===r&&(r={}),this.visit(e,s({preserveState:!0},r,{method:t.Method.POST,data:n}))},n.put=function(e,n,r){return void 0===n&&(n={}),void 0===r&&(r={}),this.visit(e,s({preserveState:!0},r,{method:t.Method.PUT,data:n}))},n.patch=function(e,n,r){return void 0===n&&(n={}),void 0===r&&(r={}),this.visit(e,s({preserveState:!0},r,{method:t.Method.PATCH,data:n}))},n.delete=function(e,n){return void 0===n&&(n={}),this.visit(e,s({preserveState:!0},n,{method:t.Method.DELETE}))},n.remember=function(e,t){var n;void 0===t&&(t="default"),this.replaceState(s({},this.page,{rememberedState:s({},this.page.rememberedState,(n={},n[t]=e,n))}))},n.restore=function(e){var t,n;return void 0===e&&(e="default"),null==(t=window.history.state)||null==(n=t.rememberedState)?void 0:n[e]},n.on=function(e,t){var n=function(e){var n=t(e);e.cancelable&&!e.defaultPrevented&&!1===n&&e.preventDefault()};return document.addEventListener("inertia:"+e,n),function(){return document.removeEventListener("inertia:"+e,n)}},e}(),w={buildDOMElement:function(e){var t=document.createElement("template");t.innerHTML=e;var n=t.content.firstChild;if(!e.startsWith("