diff --git a/TODO.md b/TODO.md index 4640904..d2e9de8 100644 --- a/TODO.md +++ b/TODO.md @@ -1 +1,27 @@ # TODO + +## Front + +- [ ] tampilan keranjang jadi lebih seperti tokped dengan metode pembayaran deposit atau hutang jika tersedia +- [ ] tampilan transaksi deposit, hutang (mitra wbb), dan poin jadi satu tampilan +- [ ] mengubah metode pembayaran deposit dengan daftar bank seperti deposit dan tampil logo bank +- [ ] tambah metode topup deposit dengan setor tunai kantor wbb +- [ ] tambah screen untuk daftar setor tunai kantor wbb +- [ ] halaman untuk menampilkan level customer +- [ ] expired time 2jam di deposit manual maupun kantor wbb +- [ ] ubah username dan password di detail transaksi dengan kode voucher saja +- [ ] [BUG] pembelian voucher lebih dari 1 mendapat kode yang sama +- [ ] format nomor transaksi di deposit , transaksi dan poin + +# Back Office + +- [ ] tambah biaya admin di deposit manual transfer +- [ ] info di ubah jadi html +- [ ] tambahan detail customer untuk detail mitra wbb +- [ ] detail customer level untuk tampilan screen level customer di depan +- [ ] rombak fitur affiliasi +- [ ] tambah detail di user admin +- [ ] tambah logo bank +- [ ] tambah setor tunai +- [ ] pengaturan share dapat menggunakan html +- [ ] menu mitrawbb diff --git a/app/Http/Controllers/Customer/CartController.php b/app/Http/Controllers/Customer/CartController.php index 00fac71..ee034df 100644 --- a/app/Http/Controllers/Customer/CartController.php +++ b/app/Http/Controllers/Customer/CartController.php @@ -19,11 +19,12 @@ class CartController extends Controller * has payed button * show payment method -> deposit, poin, paylater */ - public function index() + public function index(Request $request) { - $carts = collect(session('carts') ?? []); + $customer = $request->user('customer'); + $carts = $customer->carts->load(['voucher.locationProfile.location']); $total = $carts->sum(function ($item) { - return $item['quantity'] * $item['voucher']->validate_price; + return $item->quantity * $item->voucher->validate_price; }); $customer = Customer::find(auth()->id()); @@ -42,51 +43,40 @@ class CartController extends Controller */ public function store(Request $request, Voucher $voucher) { - $operator = $request->param ?? 'add'; - $voucher->load(['location']); - - $carts = collect(session('carts') ?? []); - if ($carts->count() > 0) { - $item = $carts->firstWhere('id', $voucher->id); - if ($item == null) { - $carts->add(['id' => $voucher->id, 'quantity' => 1, 'voucher' => $voucher]); - session(['carts' => $carts->toArray()]); - session()->flash('message', ['type' => 'success', 'message' => 'voucher ditambahkan ke keranjang']); - } else { - $carts = $carts->map(function ($item) use ($voucher, $operator) { - if ($item['id'] == $voucher->id) { - if ($operator == 'delete') { - return ['id' => null]; - } - if ($operator == 'add') { - $quantity = $item['quantity'] + 1; - } - if ($operator == 'sub') { - $quantity = $item['quantity'] - 1; - if ($quantity <= 0) { - $quantity = 1; - } - } - - return [ - ...$item, - 'quantity' => $quantity, - ]; - } - - return $item; - }); - $carts = $carts->whereNotNull('id')->toArray(); - session(['carts' => $carts]); + $operator = $request->param ?? 'add'; //delete, sub, add + $customer = $request->user('customer'); + + $item = $customer->carts()->where(['entity_id' => $voucher->id])->first(); + if ($item !== null) { + if ($operator == 'delete') { + $item->delete(); + session()->flash('message', ['type' => 'success', 'message' => 'voucher dihapus dari keranjang', 'cart' => 1]); + } + if ($operator == 'add') { + // bisa tambah filter stock vouchernya + $item->update([ + 'quantity' => $item->quantity + 1 + ]); } + if ($operator == 'sub') { + if ($item->quantity - 1 != 0) { + $item->update([ + 'quantity' => $item->quantity - 1 + ]); + } + } + } else { + $customer->carts()->create([ + 'entity_id' => $voucher->id, + 'quantity' => 1 + ]); - return; + session()->flash('message', ['type' => 'success', 'message' => 'voucher ditambahkan ke keranjang', 'cart' => 1]); } - session(['carts' => [ - ['id' => $voucher->id, 'quantity' => 1, 'voucher' => $voucher], - ]]); - session()->flash('message', ['type' => 'success', 'message' => 'voucher ditambahkan ke keranjang']); + if ($request->direct != '') { + return redirect()->route('cart.index'); + } } /** @@ -166,13 +156,13 @@ class CartController extends Controller if ($bonus != null) { $poin = $customer->poins()->create([ 'debit' => $bonus->bonus_poin, - 'description' => 'Bonus Pembelian #'.$sale->code, + 'description' => 'Bonus Pembelian #' . $sale->code, ]); $poin->update_customer_balance(); } - $description = 'Pembayaran #'.$sale->code; + $description = 'Pembayaran #' . $sale->code; if ($customer->deposit_balance < $total) { if ($customer->deposit_balance > 0) { diff --git a/app/Http/Controllers/Customer/PoinExchangeController.php b/app/Http/Controllers/Customer/PoinExchangeController.php index f65ce8a..a342c99 100644 --- a/app/Http/Controllers/Customer/PoinExchangeController.php +++ b/app/Http/Controllers/Customer/PoinExchangeController.php @@ -15,13 +15,13 @@ class PoinExchangeController extends Controller public function index(Request $request) { $locations = Location::get(); - $vouchers = Voucher::with(['location']) - ->where(function ($q) { + $vouchers = Voucher::with(['locationProfile']) + ->whereHas('locationProfile', function ($q) { $q->where('price_poin', '!=', 0) ->where('price_poin', '!=', null); }) ->where('is_sold', Voucher::UNSOLD) - ->groupBy('batch_id') + ->groupBy('location_profile_id') ->orderBy('updated_at', 'desc'); if ($request->location_id != '') { @@ -52,10 +52,10 @@ class PoinExchangeController extends Controller DB::beginTransaction(); $sale = $customer->sales()->create([ - 'code' => 'Tukar poin '.str()->upper(str()->random(5)), + 'code' => 'Tukar poin ' . str()->upper(str()->random(5)), 'date_time' => now(), 'amount' => 0, - 'payed_with' => Sale::PAYED_WITH_poin, + 'payed_with' => Sale::PAYED_WITH_POIN, ]); $voucher = $voucher->shuffle_unsold(); diff --git a/app/Http/Middleware/HandleInertiaCustomerRequests.php b/app/Http/Middleware/HandleInertiaCustomerRequests.php index 6c54c1c..d8b1012 100644 --- a/app/Http/Middleware/HandleInertiaCustomerRequests.php +++ b/app/Http/Middleware/HandleInertiaCustomerRequests.php @@ -31,17 +31,12 @@ class HandleInertiaCustomerRequests extends Middleware */ public function share(Request $request): array { - $carts = collect(session('carts') ?? []); $cart_count = 0; - if ($carts->count() > 0) { - foreach ($carts as $cart) { - $cart_count += $cart['quantity']; - } - } - $notification_count = 0; + if (auth('customer')->check()) { $notification_count = Notification::where('entity_id', auth()->id())->where('is_read', Notification::UNREAD)->count(); + $cart_count = auth('customer')->user()->carts()->sum('quantity'); } return array_merge(parent::share($request), [ diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 083be54..d0a9bb9 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -209,6 +209,11 @@ class Customer extends Authenticatable return $this->hasMany(CustomerRefferal::class); } + public function carts() + { + return $this->hasMany(CustomerCart::class); + } + public function allowPay($total): array { $allowProcess = false; diff --git a/app/Models/CustomerCart.php b/app/Models/CustomerCart.php index f6d2364..6a2aff6 100644 --- a/app/Models/CustomerCart.php +++ b/app/Models/CustomerCart.php @@ -13,4 +13,9 @@ class CustomerCart extends Model 'quantity', 'additional_info_json', ]; + + public function voucher() + { + return $this->belongsTo(Voucher::class, 'entity_id'); + } } diff --git a/app/Models/DepositHistory.php b/app/Models/DepositHistory.php index 31fd35b..738bdba 100644 --- a/app/Models/DepositHistory.php +++ b/app/Models/DepositHistory.php @@ -76,10 +76,10 @@ class DepositHistory extends Model { return Attribute::make(get: function () { if ($this->credit == 0) { - return 'Rp'.number_format($this->debit, is_float($this->debit) ? 2 : 0, ',', '.'); + return 'Rp ' . number_format($this->debit, is_float($this->debit) ? 2 : 0, ',', '.'); } - return '-Rp'.number_format($this->credit, is_float($this->credit) ? 2 : 0, ',', '.'); + return '-Rp ' . number_format($this->credit, is_float($this->credit) ? 2 : 0, ',', '.'); }); } @@ -115,14 +115,14 @@ class DepositHistory extends Model } Notification::create([ 'entity_type' => User::class, - 'description' => $this->customer->fullname.' melakukan deposit manual sebesar : '.$this->amount.$status, + 'description' => $this->customer->fullname . ' melakukan deposit manual sebesar : ' . $this->amount . $status, ]); } if ($this->payment_channel == Setting::PAYMENT_MIDTRANS) { Notification::create([ 'entity_type' => User::class, - 'description' => $this->customer->fullname.' melakukan deposit via midtrans sebesar : '.$this->amount, + 'description' => $this->customer->fullname . ' melakukan deposit via midtrans sebesar : ' . $this->amount, ]); } } @@ -131,7 +131,7 @@ class DepositHistory extends Model { Notification::create([ 'entity_id' => $this->customer_id, - 'description' => 'Deposit '.$this->description.' sebesar '.$this->amount.' sudah sukses diterima', + 'description' => 'Deposit ' . $this->description . ' sebesar ' . $this->amount . ' sudah sukses diterima', ]); } } diff --git a/package-lock.json b/package-lock.json index fcec9ed..82d52bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "qs": "^6.11.0", "react-chartjs-2": "^5.2.0", "react-datepicker": "^4.8.0", + "react-hot-toast": "^2.4.1", "react-icons": "^4.7.1", "react-number-format": "^5.1.2", "react-toastify": "^9.1.1", @@ -1715,6 +1716,14 @@ "node": ">=4" } }, + "node_modules/goober": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.13.tgz", + "integrity": "sha512-jFj3BQeleOoy7t93E9rZ2de+ScC4lQICLwiAQmKMg9F6roKGaLSHoCDYKkWlSafg138jejvq/mTdvmnwDQgqoQ==", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2426,6 +2435,21 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" }, + "node_modules/react-hot-toast": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz", + "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==", + "dependencies": { + "goober": "^2.1.10" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-icons": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.9.0.tgz", diff --git a/package.json b/package.json index cbb067a..a430516 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "qs": "^6.11.0", "react-chartjs-2": "^5.2.0", "react-datepicker": "^4.8.0", + "react-hot-toast": "^2.4.1", "react-icons": "^4.7.1", "react-number-format": "^5.1.2", "react-toastify": "^9.1.1", diff --git a/resources/css/app.css b/resources/css/app.css index 2395c33..1d4c3ba 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1,6 +1,7 @@ @tailwind base; @tailwind components; @tailwind utilities; + /* Make clicks pass-through */ #nprogress { pointer-events: none; @@ -25,11 +26,11 @@ width: 100px; height: 100%; box-shadow: 0 0 10px #003bf1, 0 0 5px #003bf1; - opacity: 1.0; + opacity: 1; -webkit-transform: rotate(3deg) translate(0px, -4px); - -ms-transform: rotate(3deg) translate(0px, -4px); - transform: rotate(3deg) translate(0px, -4px); + -ms-transform: rotate(3deg) translate(0px, -4px); + transform: rotate(3deg) translate(0px, -4px); } /* Remove these to get rid of the spinner */ @@ -52,7 +53,7 @@ border-radius: 50%; -webkit-animation: nprogress-spinner 400ms linear infinite; - animation: nprogress-spinner 400ms linear infinite; + animation: nprogress-spinner 400ms linear infinite; } .nprogress-custom-parent { @@ -72,37 +73,48 @@ } @-webkit-keyframes nprogress-spinner { - 0% { -webkit-transform: rotate(0deg); } - 100% { -webkit-transform: rotate(360deg); } + 0% { + -webkit-transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(360deg); + } } + @keyframes nprogress-spinner { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } } /* width */ ::-webkit-scrollbar { - width: 5px; - height: 70%; + width: 5px; + height: 70%; } /* Track */ ::-webkit-scrollbar-track { - background: rgb(136 136 136 / 28%); + background: rgb(136 136 136 / 28%); } /* Handle */ ::-webkit-scrollbar-thumb { - background: #888; + background: #888; } /* Handle on hover */ ::-webkit-scrollbar-thumb:hover { - background: rgb(241 241 241 / 12%); + background: rgb(241 241 241 / 12%); } .react-datepicker__input-container input { - @apply block w-full text-base md:text-sm bg-white border dark:bg-gray-700 shadow-sm ; + @apply block w-full text-base md:text-sm bg-white border dark:bg-gray-700 shadow-sm; } .react-datepicker-popper { @@ -141,36 +153,47 @@ .react-datepicker__month-0 { @apply w-1/3; } + .react-datepicker__month-1 { @apply w-1/3; } + .react-datepicker__month-2 { @apply w-1/3; } + .react-datepicker__month-3 { @apply w-1/3; } + .react-datepicker__month-4 { @apply w-1/3; } + .react-datepicker__month-5 { @apply w-1/3; } + .react-datepicker__month-6 { @apply w-1/3; } + .react-datepicker__month-7 { @apply w-1/3; } + .react-datepicker__month-8 { @apply w-1/3; } + .react-datepicker__month-9 { @apply w-1/3; } + .react-datepicker__month-10 { @apply w-1/3; } + .react-datepicker__month-11 { @apply w-1/3; } @@ -246,17 +269,19 @@ .react-datepicker__month-text { @apply mb-1 p-1 flex items-center justify-center text-sm leading-loose transition text-gray-700 dark:text-gray-100 rounded hover:bg-blue-500 hover:text-white dark:hover:text-white; } + .react-datepicker__month--selected { @apply bg-blue-500 text-white; } + .react-datepicker-year-header { @apply ml-2.5 mb-2 text-lg font-semibold text-gray-800 dark:text-gray-100; } .react-datepicker__aria-live { - @apply hidden + @apply hidden; } .min-h-100 { max-height: 45rem; -} \ No newline at end of file +} diff --git a/resources/css/spinner.css b/resources/css/spinner.css index 62280e4..202857e 100644 --- a/resources/css/spinner.css +++ b/resources/css/spinner.css @@ -27,7 +27,7 @@ width: 100px; height: 100%; box-shadow: 0 0 10px #003bf1, 0 0 5px #003bf1; - opacity: 1.0; + opacity: 1; -webkit-transform: rotate(3deg) translate(0px, -4px); -ms-transform: rotate(3deg) translate(0px, -4px); @@ -71,15 +71,14 @@ box-sizing: border-box; border: solid 3px transparent !important; - border-top-color: #F1A410 !important; - border-left-color: #F1A410 !important; + border-top-color: #f1a410 !important; + border-left-color: #f1a410 !important; border-radius: 50px !important; -webkit-animation: nprogress-spinner 400ms linear infinite; animation: nprogress-spinner 400ms linear infinite; } - .nprogress-custom-parent { display: flex; align-items: center; @@ -94,4 +93,4 @@ .nprogress-custom-parent #nprogress .spinner, .nprogress-custom-parent #nprogress .bar { position: absolute; -} \ No newline at end of file +} diff --git a/resources/js/Customer/Cart/VoucherCard.jsx b/resources/js/Customer/Cart/VoucherCard.jsx index a5894a7..0e6d5ce 100644 --- a/resources/js/Customer/Cart/VoucherCard.jsx +++ b/resources/js/Customer/Cart/VoucherCard.jsx @@ -17,12 +17,14 @@ export default function VoucherCard({ item: { voucher, quantity } }) { return (
-
{voucher.location.name}
+
+ {voucher.location_profile.location.name} +
- {voucher.profile} + {voucher.location_profile.display_note}
IDR {formatIDR(voucher.validate_price)} @@ -40,10 +42,10 @@ export default function VoucherCard({ item: { voucher, quantity } }) {
- {voucher.display_quota} + {voucher.location_profile.quota}
- {voucher.display_expired} + {voucher.location_profile.diplay_expired}
@@ -59,14 +61,14 @@ export default function VoucherCard({ item: { voucher, quantity } }) { className="text-red-700 w-6 h-6 rounded-full border mr-4 hover:bg-red-700" onClick={handleDelete} /> -
{quantity}
-
diff --git a/resources/js/Customer/Components/BottomSheet.jsx b/resources/js/Customer/Components/BottomSheet.jsx new file mode 100644 index 0000000..e90f713 --- /dev/null +++ b/resources/js/Customer/Components/BottomSheet.jsx @@ -0,0 +1,23 @@ +export default function BottomSheet({ isOpen, toggle, children }) { + return ( + <> +
+
toggle()} + >
+
+
+ {children} +
+
+
+ + ) +} diff --git a/resources/js/Customer/Deposit/Topup.jsx b/resources/js/Customer/Deposit/Topup.jsx index 9426d04..b56d903 100644 --- a/resources/js/Customer/Deposit/Topup.jsx +++ b/resources/js/Customer/Deposit/Topup.jsx @@ -6,6 +6,7 @@ import CustomerLayout from '@/Layouts/CustomerLayout' import FormInput from '@/Components/FormInput' import Alert from '@/Components/Alert' import { formatIDR } from '@/utils' +import FormInputNumeric from '@/Components/FormInputNumeric' export default function Topup({ payments }) { const { data, setData, post, processing, errors, reset, clearErrors } = @@ -71,7 +72,7 @@ export default function Topup({ payments }) {
- setData('amount', e.target.value)} diff --git a/resources/js/Customer/Index/Index.jsx b/resources/js/Customer/Index/Index.jsx index f60e57d..a6360c3 100644 --- a/resources/js/Customer/Index/Index.jsx +++ b/resources/js/Customer/Index/Index.jsx @@ -1,6 +1,5 @@ import Reactm, { useState, useEffect } from 'react' -import { Head, router, usePage } from '@inertiajs/react' -import { HiOutlineBell } from 'react-icons/hi2' +import { Head, router } from '@inertiajs/react' import Carousel from 'nuka-carousel' import { handleBanner, ALL, FAVORITE } from './utils' @@ -8,30 +7,7 @@ import CustomerLayout from '@/Layouts/CustomerLayout' import UserBanner from './Partials/UserBanner' import AllVoucher from './IndexPartials/AllVoucher' import FavoriteVoucher from './IndexPartials/FavoriteVoucher' - -const GuestBanner = () => { - const { - props: { setting, notification_count }, - } = usePage() - return ( -
- {/* user */} -
-
-
{setting.OPEN_WEBSITE_NAME}
-
-
- -
-
- {notification_count} -
-
-
-
-
- ) -} +import GuestBanner from './Partials/GuestBanner' export default function Index(props) { const { diff --git a/resources/js/Customer/Index/Partials/BalanceBanner.jsx b/resources/js/Customer/Index/Partials/BalanceBanner.jsx index 9f368e4..f8e38e6 100644 --- a/resources/js/Customer/Index/Partials/BalanceBanner.jsx +++ b/resources/js/Customer/Index/Partials/BalanceBanner.jsx @@ -6,7 +6,7 @@ import { HiOutlineCash } from 'react-icons/hi' export default function BalanceBanner({ user }) { return (
router.get(route('customer.deposit.index'))} >
diff --git a/resources/js/Customer/Index/Partials/GuestBanner.jsx b/resources/js/Customer/Index/Partials/GuestBanner.jsx new file mode 100644 index 0000000..5d91a55 --- /dev/null +++ b/resources/js/Customer/Index/Partials/GuestBanner.jsx @@ -0,0 +1,26 @@ +import { usePage } from '@inertiajs/react' +import { HiOutlineBell } from 'react-icons/hi2' + +export default function GuestBanner() { + const { + props: { setting, notification_count }, + } = usePage() + return ( +
+ {/* user */} +
+
+
{setting.OPEN_WEBSITE_NAME}
+
+
+ +
+
+ {notification_count} +
+
+
+
+
+ ) +} diff --git a/resources/js/Customer/Index/Partials/UserBanner.jsx b/resources/js/Customer/Index/Partials/UserBanner.jsx index b42564d..c1ff1dd 100644 --- a/resources/js/Customer/Index/Partials/UserBanner.jsx +++ b/resources/js/Customer/Index/Partials/UserBanner.jsx @@ -11,7 +11,7 @@ export default function UserBanner({ user }) { return (
{/* user */} -
+
{user.name}
diff --git a/resources/js/Customer/Index/Partials/VoucherCard.jsx b/resources/js/Customer/Index/Partials/VoucherCard.jsx index 325cfb0..f391658 100644 --- a/resources/js/Customer/Index/Partials/VoucherCard.jsx +++ b/resources/js/Customer/Index/Partials/VoucherCard.jsx @@ -1,14 +1,14 @@ +import Alert from '@/Components/Alert' +import BottomSheet from '@/Customer/Components/BottomSheet' +import { useModalState } from '@/hooks' import { formatIDR } from '@/utils' import { router } from '@inertiajs/react' -export default function VoucherCard({ voucher }) { - const addCart = () => { - router.post(route('cart.store', voucher)) - } +const Voucher = ({ voucher, onClick }) => { return (
@@ -23,7 +23,7 @@ export default function VoucherCard({ voucher }) { {voucher.location_profile.display_note}
- IDR {formatIDR(voucher.validate_price)} + Rp {formatIDR(voucher.validate_price)}
{+voucher.discount !== 0 && (
@@ -48,3 +48,62 @@ export default function VoucherCard({ voucher }) {
) } + +const ModalChoose = (props) => { + const { state, voucher } = props + + const onDirectBuy = () => { + router.post(route('cart.store', voucher), { direct: 1 }) + state.toggle() + } + + const addToCarts = () => { + router.post(route('cart.store', voucher)) + state.toggle() + } + + return ( + state.toggle()}> + + {voucher.location_profile.display_note !== null && ( +
+ {voucher.location_profile.display_note} +
+ )} +
+
+ Beli Langsung +
+
+ + Keranjang +
+
+
+ ) +} + +export default function VoucherCard({ voucher }) { + const chooseModalState = useModalState() + + const onVoucherChoose = () => { + chooseModalState.toggle() + } + + return ( + <> +
onVoucherChoose()}> + +
+ + + ) +} diff --git a/resources/js/Customer/Poin/VoucherCard.jsx b/resources/js/Customer/Poin/VoucherCard.jsx index 5112b4a..d09d0a8 100644 --- a/resources/js/Customer/Poin/VoucherCard.jsx +++ b/resources/js/Customer/Poin/VoucherCard.jsx @@ -1,64 +1,57 @@ import { formatIDR } from '@/utils' import { router } from '@inertiajs/react' import { useState } from 'react' +import BottomSheet from '../Components/BottomSheet' const ExchangeModal = ({ show, voucher, setShow }) => { return ( -
-
setShow(false)} - > -
-
-
- {voucher.location.name} + setShow(false)}> +
+
+
+ {voucher.location_profile.name} +
+
+
+
+
+ {voucher.location_profile.display_note} +
+
+ {formatIDR(voucher.location_profile.price_poin)}{' '} + poin{' '} +
-
-
-
-
- {voucher.profile} -
-
- {formatIDR(voucher.price_poin)} poin -
+
+
+ {voucher.location_profile.quota}
-
-
- {voucher.display_quota} -
-
- {voucher.display_expired} -
+
+ {voucher.location_profile.display_expired}
-
-
- router.get( - route( - 'customer.poin.exchange.process', - voucher - ) - ) - } - > - Tukarkan -
-
- Batal -
+
+
+
+ router.get( + route('customer.poin.exchange.process', voucher) + ) + } + > + Tukarkan +
+
setShow(false)} + > + Batal
-
+ ) } @@ -71,24 +64,25 @@ export default function VoucherCard({ voucher }) { onClick={() => setShow(true)} >
- {voucher.location.name} + {voucher.location_profile.name}
- {voucher.profile} + {voucher.location_profile.display_note}
- {formatIDR(voucher.price_poin)} poin + {formatIDR(voucher.location_profile.price_poin)}{' '} + poin
- {voucher.display_quota} + {voucher.location_profile.quota}
- {voucher.display_expired} + {voucher.location_profile.display_expired}
diff --git a/resources/js/Customer/Profile/Index.jsx b/resources/js/Customer/Profile/Index.jsx index 5bfffef..15290be 100644 --- a/resources/js/Customer/Profile/Index.jsx +++ b/resources/js/Customer/Profile/Index.jsx @@ -35,7 +35,7 @@ export default function Index({ auth: { user }, notification_count }) {
{/* user */} -
+
{user.image_url !== null ? ( {notifications.map((notif) => (
handleNotification(notif) } key={notif.id} > -
{notif.description}
-
{notif.created_at}
+
+ {notif.description} +
+
+ {notif.format_created_at} +
))} {notifications.length > 0 && ( diff --git a/resources/js/Layouts/CustomerLayout.jsx b/resources/js/Layouts/CustomerLayout.jsx index 4ba4600..121c3f5 100644 --- a/resources/js/Layouts/CustomerLayout.jsx +++ b/resources/js/Layouts/CustomerLayout.jsx @@ -1,5 +1,5 @@ -import React, { useEffect } from 'react' -import { ToastContainer, toast } from 'react-toastify' +import React, { useEffect, useState } from 'react' +import toast, { Toaster } from 'react-hot-toast' import { router, usePage } from '@inertiajs/react' import { HiOutlineHome } from 'react-icons/hi' @@ -19,22 +19,40 @@ export default function CustomerLayout({ children }) { }, } = usePage() + const [bounce, setBouce] = useState(false) + const handleOnClick = (r) => { router.get(route(r, { direct: 1 })) } const isActive = (r) => { if (route().current(r)) { - return 'text-blue-700 font-bold' + return 'text-primary-900 font-bold' } return 'text-gray-600 font-light' } + const clearAnimate = () => { + setBouce(false) + } + useEffect(() => { - if (flash.message !== null) { - toast(flash.message.message, { type: flash.message.type }) + let se + if (flash.message !== null && flash.message.type !== null) { + toast.success((t) => { + return ( +
toast.dismiss(t.id)}> + {flash.message.message} +
+ ) + }) + if (+flash.message.cart === 1) { + setBouce(true) + se = setTimeout(clearAnimate, 3000) + } } + return () => clearTimeout(se) }, [flash]) return ( @@ -58,7 +76,11 @@ export default function CustomerLayout({ children }) { )}`} onClick={() => handleOnClick('cart.index')} > -
+
@@ -104,7 +126,17 @@ export default function CustomerLayout({ children }) {
Menu
- +
) } diff --git a/resources/js/app.jsx b/resources/js/app.jsx index cb908ba..ff7528b 100644 --- a/resources/js/app.jsx +++ b/resources/js/app.jsx @@ -2,7 +2,6 @@ import './bootstrap' import '../css/app.css' import '../css/spinner.css' import 'flowbite' -import 'react-toastify/dist/ReactToastify.css' import React from 'react' import NProgress from 'nprogress' diff --git a/rsync.sh b/rsync.sh index 2ebc0b4..e3e2177 100755 --- a/rsync.sh +++ b/rsync.sh @@ -1,4 +1,6 @@ #!/bin/bash +npm run build + rsync -arP -e 'ssh -p 225' --exclude=node_modules --exclude=database/database.sqlite --exclude=.git --exclude=.env --exclude=public/hot . arm@ajikamaludin.id:/home/arm/projects/www/voucher -ssh -p 225 arm@ajikamaludin.id -C docker exec php82 php /var/www/voucher/artisan migrate:refresh --seed \ No newline at end of file +ssh -p 225 arm@ajikamaludin.id -C docker exec php82 php /var/www/voucher/artisan migrate:refresh --seed diff --git a/tailwind.config.js b/tailwind.config.js index 4cc684c..c5c1fbc 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -17,6 +17,34 @@ module.exports = { sans: ['Nunito', ...defaultTheme.fontFamily.sans], }, }, + colors: { + primary: { + 50: '#edf7ff', + 100: '#d6ebff', + 200: '#b6deff', + 300: '#84cbff', + 400: '#4aaeff', + 500: '#2089ff', + 600: '#0867ff', + 700: '#024ff3', + 800: '#0940c4', + 900: '#0e3995', + 950: '#0e255d', + }, + secondary: { + 50: '#fffceb', + 100: '#fdf4c8', + 200: '#fbe88c', + 300: '#f9d650', + 400: '#f7c328', + 500: '#f1a410', + 600: '#d57d0a', + 700: '#b1580c', + 800: '#904510', + 900: '#763911', + 950: '#441c04', + }, + }, }, plugins: [require('@tailwindcss/forms'), require('flowbite/plugin')],