Skip to content

Commit

Permalink
✨ Add Category Index and Improve UI
Browse files Browse the repository at this point in the history
  • Loading branch information
saleem-hadad committed Jan 9, 2022
1 parent 348cbd1 commit 564b6c1
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 7 deletions.
13 changes: 13 additions & 0 deletions app/Http/Controllers/CategoryController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Http\Controllers;

use Inertia\Inertia;

class CategoryController extends Controller
{
public function index()
{
return Inertia::render('Category/Index');
}
}
4 changes: 2 additions & 2 deletions graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ type Query {
transactions: [Transaction!]! @paginate(defaultCount: 25) @orderBy(column: id direction: DESC)

allBrands: [Brand!]! @all
brands: [Brand!]! @paginate(defaultCount: 25)
brands: [Brand!]! @paginate(defaultCount: 25) @orderBy(column: id direction: DESC)

allCategories: [Category!]! @all
categories: [Category!]! @paginate(defaultCount: 25)
categories: [Category!]! @paginate(defaultCount: 25) @orderBy(column: id direction: DESC)

totalExpenses: Float! @aggregate(model: Transaction column: amount function: SUM scopes:["expenses"])
totalIncome: Float! @aggregate(model: Transaction column: amount function: SUM scopes: ["income"])
Expand Down
4 changes: 4 additions & 0 deletions public/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -1605,6 +1605,10 @@ select {
}
@media (min-width: 768px) {

.md\:w-1\/2 {
width: 50%;
}

.md\:grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
Expand Down
204 changes: 200 additions & 4 deletions public/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4585,6 +4585,13 @@ var Api = /*#__PURE__*/function () {
query: "query { \n allBrands { \n id \n name \n } \n }"
});
}
}, {
key: "getCategories",
value: function getCategories(page) {
return axios.post('/graphql', {
query: "query {\n categories(page: ".concat(page, ") {\n data {\n id\n name\n type\n }\n paginatorInfo {\n hasMorePages\n }\n }\n }")
});
}
}, {
key: "getBrands",
value: function getBrands(page) {
Expand Down Expand Up @@ -5443,7 +5450,7 @@ function Wrapper(_ref) {
_ref$width = _ref.width,
width = _ref$width === void 0 ? '1/3' : _ref$width;
return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", {
className: "px-3 mb-6 w-1/2 w-full md:w-".concat(width),
className: "px-3 mb-6 w-full md:w-1/2 md:w-".concat(width),
children: children
});
}
Expand Down Expand Up @@ -5618,6 +5625,13 @@ function Authenticated(_ref) {
active: route().current('brands'),
children: "Brands"
})
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", {
className: "hidden space-x-8 sm:-my-px sm:ml-10 sm:flex",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_Components_NavLink__WEBPACK_IMPORTED_MODULE_3__["default"], {
href: route('categories'),
active: route().current('categories'),
children: "Categories"
})
})]
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", {
className: "hidden sm:flex sm:items-center sm:ml-6",
Expand Down Expand Up @@ -5686,13 +5700,25 @@ function Authenticated(_ref) {
})
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", {
className: (showingNavigationDropdown ? 'block' : 'hidden') + ' sm:hidden',
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", {
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", {
className: "pt-2 pb-3 space-y-1",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_Components_ResponsiveNavLink__WEBPACK_IMPORTED_MODULE_4__["default"], {
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_Components_ResponsiveNavLink__WEBPACK_IMPORTED_MODULE_4__["default"], {
href: route('dashboard'),
active: route().current('dashboard'),
children: "Dashboard"
})
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_Components_ResponsiveNavLink__WEBPACK_IMPORTED_MODULE_4__["default"], {
href: route('transactions'),
active: route().current('transactions'),
children: "Transactions"
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_Components_ResponsiveNavLink__WEBPACK_IMPORTED_MODULE_4__["default"], {
href: route('brands'),
active: route().current('brands'),
children: "Brands"
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_Components_ResponsiveNavLink__WEBPACK_IMPORTED_MODULE_4__["default"], {
href: route('categories'),
active: route().current('categories'),
children: "Categories"
})]
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", {
className: "pt-4 pb-1 border-t border-gray-200",
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", {
Expand Down Expand Up @@ -6042,6 +6068,174 @@ function Dashboard(_ref) {

/***/ }),

/***/ "./resources/js/Pages/Category/Index.js":
/*!**********************************************!*\
!*** ./resources/js/Pages/Category/Index.js ***!
\**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (/* binding */ Dashboard)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js");
/* harmony import */ var _heroicons_react_outline__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @heroicons/react/outline */ "./node_modules/@heroicons/react/outline/esm/index.js");
/* harmony import */ var _inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @inertiajs/inertia-react */ "./node_modules/@inertiajs/inertia-react/dist/index.js");
/* harmony import */ var _Layouts_Authenticated__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @/Layouts/Authenticated */ "./resources/js/Layouts/Authenticated.js");
/* harmony import */ var _Components_LoadMore__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/Components/LoadMore */ "./resources/js/Components/LoadMore.js");
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js");
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }

function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }








function Dashboard(_ref) {
var auth = _ref.auth;

var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),
_useState2 = _slicedToArray(_useState, 2),
categories = _useState2[0],
setCategories = _useState2[1];

var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(1),
_useState4 = _slicedToArray(_useState3, 2),
currentPage = _useState4[0],
setCurrentPage = _useState4[1];

var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),
_useState6 = _slicedToArray(_useState5, 2),
hasMorePages = _useState6[0],
setHasMorePages = _useState6[1];

var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),
_useState8 = _slicedToArray(_useState7, 2),
loading = _useState8[0],
setLoading = _useState8[1];

(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {
if (!hasMorePages) return;
setLoading(true);
Api.getCategories(currentPage).then(function (_ref2) {
var data = _ref2.data;
setCategories([].concat(_toConsumableArray(categories), _toConsumableArray(data.data.categories.data)));
setHasMorePages(data.data.categories.paginatorInfo.hasMorePages);
setLoading(false);
})["catch"](console.error);
}, [currentPage]);
return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_Layouts_Authenticated__WEBPACK_IMPORTED_MODULE_3__["default"], {
auth: auth,
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_2__.Head, {
title: "Categories"
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
className: "py-12",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
className: "max-w-7xl mx-auto sm:px-6 lg:px-8",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
className: "flex flex-col",
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
className: "-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
className: "py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
className: "shadow overflow-hidden border-b border-gray-200 sm:rounded-lg",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("table", {
className: "min-w-full divide-y divide-gray-200",
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("thead", {
className: "bg-gray-50",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("tr", {
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("th", {
scope: "col",
className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",
children: "Id"
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("th", {
scope: "col",
className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",
children: "Name"
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("th", {
scope: "col",
className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider",
children: "Type"
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("th", {
scope: "col",
className: "relative py-3",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("span", {
className: "sr-only",
children: "Edit"
})
})]
})
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("tbody", {
className: "bg-white divide-y divide-gray-200",
children: categories.map(function (item) {
return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("tr", {
className: "loaded",
id: 'item-' + item.id,
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("td", {
className: "px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800",
children: item.id
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("td", {
className: "px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800",
children: item.name
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("td", {
className: "px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800",
children: item.type
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("td", {
className: "px-6 py-4 whitespace-nowrap text-right text-sm font-medium",
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("button", {
type: "button",
children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("span", {
className: "sr-only",
children: "Edit"
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_heroicons_react_outline__WEBPACK_IMPORTED_MODULE_1__.PencilAltIcon, {
className: "h-5 w-5 text-gray-500",
"aria-hidden": "true"
})]
})
})]
}, item.id);
})
})]
})
})
})
}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_Components_LoadMore__WEBPACK_IMPORTED_MODULE_4__["default"], {
hasMorePages: hasMorePages,
loading: loading,
onClick: function onClick() {
return setCurrentPage(currentPage + 1);
}
})]
})
})
})]
});
}

/***/ }),

/***/ "./resources/js/Pages/Dashboard.js":
/*!*****************************************!*\
!*** ./resources/js/Pages/Dashboard.js ***!
Expand Down Expand Up @@ -59708,6 +59902,8 @@ var map = {
"./Auth/Login.js": "./resources/js/Pages/Auth/Login.js",
"./Brand/Index": "./resources/js/Pages/Brand/Index.js",
"./Brand/Index.js": "./resources/js/Pages/Brand/Index.js",
"./Category/Index": "./resources/js/Pages/Category/Index.js",
"./Category/Index.js": "./resources/js/Pages/Category/Index.js",
"./Dashboard": "./resources/js/Pages/Dashboard.js",
"./Dashboard.js": "./resources/js/Pages/Dashboard.js",
"./Transaction/Edit": "./resources/js/Pages/Transaction/Edit.js",
Expand Down
15 changes: 15 additions & 0 deletions resources/js/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ export default class Api {
}`});
}

getCategories(page) {
return axios.post('/graphql', {query: `query {
categories(page: ${page}) {
data {
id
name
type
}
paginatorInfo {
hasMorePages
}
}
}`});
}

getBrands(page) {
return axios.post('/graphql', {query: `query {
brands(page: ${page}) {
Expand Down
2 changes: 1 addition & 1 deletion resources/js/Components/Wrapper.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export default function Wrapper({ children, width='1/3' }) {
return (
<div className={`px-3 mb-6 w-1/2 w-full md:w-${width}`}>
<div className={`px-3 mb-6 w-full md:w-1/2 md:w-${width}`}>
{children}
</div>
);
Expand Down
18 changes: 18 additions & 0 deletions resources/js/Layouts/Authenticated.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ export default function Authenticated({ auth, children }) {
Brands
</NavLink>
</div>

<div className="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
<NavLink href={route('categories')} active={route().current('categories')}>
Categories
</NavLink>
</div>
</div>

<div className="hidden sm:flex sm:items-center sm:ml-6">
Expand Down Expand Up @@ -106,6 +112,18 @@ export default function Authenticated({ auth, children }) {
<ResponsiveNavLink href={route('dashboard')} active={route().current('dashboard')}>
Dashboard
</ResponsiveNavLink>

<ResponsiveNavLink href={route('transactions')} active={route().current('transactions')}>
Transactions
</ResponsiveNavLink>

<ResponsiveNavLink href={route('brands')} active={route().current('brands')}>
Brands
</ResponsiveNavLink>

<ResponsiveNavLink href={route('categories')} active={route().current('categories')}>
Categories
</ResponsiveNavLink>
</div>

<div className="pt-4 pb-1 border-t border-gray-200">
Expand Down
Loading

0 comments on commit 564b6c1

Please sign in to comment.