location profile done
parent
935be0886f
commit
5a3bfa0be1
@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\CustomerLevel;
|
||||
use App\Models\LocationProfile;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class LocationProfileController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = LocationProfile::with(['location'])->orderBy('updated_at', 'desc');
|
||||
|
||||
if ($request->location_id != '') {
|
||||
$query->where('location_id', $request->location_id);
|
||||
}
|
||||
|
||||
if ($request->q != '') {
|
||||
$query->where('name', 'like', "%$request->q%")
|
||||
->orWhere('display_note', 'like', "%$request->q%");
|
||||
}
|
||||
|
||||
return inertia('LocationProfile/Index', [
|
||||
'query' => $query->paginate(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
return inertia('LocationProfile/Form', [
|
||||
'expireds' => LocationProfile::EXPIRED_UNIT,
|
||||
'levels' => CustomerLevel::all(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'location_id' => 'required|exists:locations,id',
|
||||
'name' => 'required|string',
|
||||
'quota' => 'required|string',
|
||||
'display_note' => 'nullable|string',
|
||||
'expired' => 'required|numeric',
|
||||
'expired_unit' => 'required|string',
|
||||
'description' => 'nullable|string',
|
||||
'min_stock' => 'required|numeric',
|
||||
'display_price' => 'required|numeric',
|
||||
'discount' => 'required|numeric|min:0|max:100',
|
||||
'price_poin' => 'required|numeric',
|
||||
'bonus_poin' => 'required|numeric',
|
||||
'prices' => 'nullable|array',
|
||||
'prices.*.customer_level_id' => 'required|exists:customer_levels,id',
|
||||
'prices.*.display_price' => 'required|numeric',
|
||||
'prices.*.discount' => 'required|numeric|min:0|max:100',
|
||||
'prices.*.price_poin' => 'required|numeric',
|
||||
'prices.*.bonus_poin' => 'required|numeric',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
$profile = LocationProfile::create([
|
||||
'location_id' => $request->location_id,
|
||||
'name' => $request->name,
|
||||
'quota' => $request->quota,
|
||||
'display_note' => $request->display_note,
|
||||
'expired' => $request->expired,
|
||||
'expired_unit' => $request->expired_unit,
|
||||
'description' => $request->description,
|
||||
'min_stock' => $request->min_stock,
|
||||
'display_price' => $request->display_price,
|
||||
'discount' => $request->discount,
|
||||
'price_poin' => $request->price_poin,
|
||||
'bonus_poin' => $request->bonus_poin,
|
||||
]);
|
||||
|
||||
$prices = collect($request->prices);
|
||||
if ($prices->count() > 0) {
|
||||
foreach ($prices as $price) {
|
||||
$profile->prices()->create([
|
||||
'customer_level_id' => $price['customer_level_id'],
|
||||
'display_price' => $price['display_price'],
|
||||
'discount' => $price['discount'],
|
||||
'price_poin' => $price['price_poin'],
|
||||
'bonus_poin' => $price['bonus_poin'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
DB::commit();
|
||||
|
||||
return redirect()->route('location-profile.index')
|
||||
->with('message', ['type' => 'success', 'message' => 'Item has beed saved']);
|
||||
}
|
||||
|
||||
public function edit(LocationProfile $profile)
|
||||
{
|
||||
return inertia('LocationProfile/Form', [
|
||||
'expireds' => LocationProfile::EXPIRED_UNIT,
|
||||
'levels' => CustomerLevel::all(),
|
||||
'profile' => $profile->load(['location', 'prices.level'])
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, LocationProfile $profile)
|
||||
{
|
||||
$request->validate([
|
||||
'location_id' => 'required|exists:locations,id',
|
||||
'name' => 'required|string',
|
||||
'quota' => 'required|string',
|
||||
'display_note' => 'nullable|string',
|
||||
'expired' => 'required|numeric',
|
||||
'expired_unit' => 'required|string',
|
||||
'description' => 'nullable|string',
|
||||
'min_stock' => 'required|numeric',
|
||||
'display_price' => 'required|numeric',
|
||||
'discount' => 'required|numeric|min:0|max:100',
|
||||
'price_poin' => 'required|numeric',
|
||||
'bonus_poin' => 'required|numeric',
|
||||
'prices' => 'nullable|array',
|
||||
'prices.*.customer_level_id' => 'required|exists:customer_levels,id',
|
||||
'prices.*.display_price' => 'required|numeric',
|
||||
'prices.*.discount' => 'required|numeric|min:0|max:100',
|
||||
'prices.*.price_poin' => 'required|numeric',
|
||||
'prices.*.bonus_poin' => 'required|numeric',
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
$profile->update([
|
||||
'location_id' => $request->location_id,
|
||||
'name' => $request->name,
|
||||
'quota' => $request->quota,
|
||||
'display_note' => $request->display_note,
|
||||
'expired' => $request->expired,
|
||||
'expired_unit' => $request->expired_unit,
|
||||
'description' => $request->description,
|
||||
'min_stock' => $request->min_stock,
|
||||
'display_price' => $request->display_price,
|
||||
'discount' => $request->discount,
|
||||
'price_poin' => $request->price_poin,
|
||||
'bonus_poin' => $request->bonus_poin,
|
||||
]);
|
||||
|
||||
$profile->prices()->delete();
|
||||
$prices = collect($request->prices);
|
||||
if ($prices->count() > 0) {
|
||||
foreach ($prices as $price) {
|
||||
$profile->prices()->create([
|
||||
'customer_level_id' => $price['customer_level_id'],
|
||||
'display_price' => $price['display_price'],
|
||||
'discount' => $price['discount'],
|
||||
'price_poin' => $price['price_poin'],
|
||||
'bonus_poin' => $price['bonus_poin'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
DB::commit();
|
||||
|
||||
return redirect()->route('location-profile.index')
|
||||
->with('message', ['type' => 'success', 'message' => 'Item has beed updated']);
|
||||
}
|
||||
|
||||
public function destroy(LocationProfile $profile)
|
||||
{
|
||||
$profile->delete();
|
||||
|
||||
return redirect()->route('location-profile.index')
|
||||
->with('message', ['type' => 'success', 'message' => 'Item has beed deleted']);
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class poinHistory extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'debit',
|
||||
'credit',
|
||||
'description',
|
||||
'customer_id',
|
||||
'related_type',
|
||||
'related_id',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'amount',
|
||||
'format_human_created_at',
|
||||
'format_created_at',
|
||||
];
|
||||
|
||||
public function formatHumanCreatedAt(): Attribute
|
||||
{
|
||||
return Attribute::make(get: function () {
|
||||
return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y');
|
||||
});
|
||||
}
|
||||
|
||||
public function formatCreatedAt(): Attribute
|
||||
{
|
||||
return Attribute::make(get: function () {
|
||||
return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y H:i:s');
|
||||
});
|
||||
}
|
||||
|
||||
public function amount(): Attribute
|
||||
{
|
||||
return Attribute::make(get: function () {
|
||||
if ($this->credit == 0) {
|
||||
return number_format($this->debit, is_float($this->debit) ? 2 : 0, ',', '.');
|
||||
}
|
||||
|
||||
return number_format($this->credit, is_float($this->credit) ? 2 : 0, ',', '.');
|
||||
});
|
||||
}
|
||||
|
||||
public function customer()
|
||||
{
|
||||
return $this->belongsTo(Customer::class);
|
||||
}
|
||||
|
||||
public function update_customer_balance()
|
||||
{
|
||||
$customer = Customer::find($this->customer_id);
|
||||
$customer->update(['poin_balance' => $customer->poin_balance + $this->debit - $this->credit]);
|
||||
}
|
||||
}
|
@ -0,0 +1,353 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { isEmpty } from 'lodash'
|
||||
|
||||
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
|
||||
import FormInput from '@/Components/FormInput'
|
||||
import Button from '@/Components/Button'
|
||||
import { Head, useForm } from '@inertiajs/react'
|
||||
import FormInputWith from '@/Components/FormInputWith'
|
||||
import LocationSelectionInput from '../Location/SelectionInput'
|
||||
import Checkbox from '@/Components/Checkbox'
|
||||
import { DEFAULT_EXPIRED_UNIT } from '@/constant'
|
||||
import { toFixed } from '@/utils'
|
||||
import FormInputNumeric from '@/Components/FormInputNumeric'
|
||||
|
||||
export default function Form(props) {
|
||||
const { profile, levels, expireds } = props
|
||||
|
||||
const [use_level, setUseLevel] = useState(false)
|
||||
const { data, setData, post, processing, errors } = useForm({
|
||||
location_id: null,
|
||||
name: '',
|
||||
quota: '',
|
||||
display_note: '',
|
||||
expired: '',
|
||||
expired_unit: DEFAULT_EXPIRED_UNIT,
|
||||
description: '',
|
||||
min_stock: 0,
|
||||
display_price: 0,
|
||||
discount: 0,
|
||||
price_poin: 0,
|
||||
bonus_poin: 0,
|
||||
prices: null,
|
||||
})
|
||||
|
||||
const handleOnChange = (event) => {
|
||||
setData(
|
||||
event.target.name,
|
||||
event.target.type === 'checkbox'
|
||||
? event.target.checked
|
||||
? 1
|
||||
: 0
|
||||
: event.target.value
|
||||
)
|
||||
}
|
||||
|
||||
const handleUseLevel = () => {
|
||||
setUseLevel(!use_level)
|
||||
if (!use_level === true) {
|
||||
const prices = levels.map((level) => {
|
||||
return {
|
||||
level: level,
|
||||
customer_level_id: level.id,
|
||||
display_price: 0,
|
||||
discount: 0,
|
||||
price_poin: 0,
|
||||
bonus_poin: 0,
|
||||
}
|
||||
})
|
||||
setData('prices', prices)
|
||||
return
|
||||
}
|
||||
setData('prices', null)
|
||||
}
|
||||
|
||||
const handleSetLevelPrice = (id, event) => {
|
||||
setData(
|
||||
'prices',
|
||||
data.prices.map((price) => {
|
||||
if (price.customer_level_id === id) {
|
||||
price[event.target.name] = event.target.value
|
||||
}
|
||||
return price
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (isEmpty(profile) === false) {
|
||||
post(route('location-profile.update', profile))
|
||||
return
|
||||
}
|
||||
post(route('location-profile.store'))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isEmpty(profile) === false) {
|
||||
if (profile.prices.length > 0) {
|
||||
setUseLevel(true)
|
||||
}
|
||||
setData({
|
||||
name: profile.name,
|
||||
quota: profile.quota,
|
||||
display_note: profile.display_note,
|
||||
description: profile.description,
|
||||
min_stock: profile.min_stock,
|
||||
display_price: profile.display_price,
|
||||
discount: profile.discount,
|
||||
price_poin: profile.price_poin,
|
||||
bonus_poin: profile.bonus_poin,
|
||||
expired: profile.expired,
|
||||
expired_unit: profile.expired_unit,
|
||||
location_id: profile.location_id,
|
||||
prices: profile.prices.map((price) => {
|
||||
return {
|
||||
...price,
|
||||
display_price: price.display_price,
|
||||
discount: price.discount,
|
||||
price_poin: price.price_poin,
|
||||
bonus_poin: price.bonus_poin,
|
||||
}
|
||||
}),
|
||||
})
|
||||
}
|
||||
}, [profile])
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout
|
||||
auth={props.auth}
|
||||
errors={props.errors}
|
||||
flash={props.flash}
|
||||
page={'Profile Lokasi'}
|
||||
action={'Form'}
|
||||
>
|
||||
<Head title="Profile Lokasi" />
|
||||
|
||||
<div>
|
||||
<div className="mx-auto sm:px-6 lg:px-8">
|
||||
<div className="overflow-hidden p-4 shadow-sm sm:rounded-lg bg-white dark:bg-gray-800 flex flex-col ">
|
||||
<div className="text-xl font-bold mb-4">
|
||||
Profile Lokasi
|
||||
</div>
|
||||
<LocationSelectionInput
|
||||
label="Lokasi"
|
||||
itemSelected={data.location_id}
|
||||
onItemSelected={(id) => setData('location_id', id)}
|
||||
error={errors.location_id}
|
||||
/>
|
||||
<div className="mt-2" />
|
||||
<FormInput
|
||||
name="name"
|
||||
value={data.name}
|
||||
onChange={handleOnChange}
|
||||
label="Nama"
|
||||
error={errors.name}
|
||||
/>
|
||||
<FormInput
|
||||
name="display_note"
|
||||
value={data.display_note}
|
||||
onChange={handleOnChange}
|
||||
label="Catatan"
|
||||
error={errors.display_note}
|
||||
/>
|
||||
<FormInputNumeric
|
||||
name="display_price"
|
||||
value={data.display_price}
|
||||
onChange={handleOnChange}
|
||||
label="Harga"
|
||||
error={errors.display_price}
|
||||
fixed={false}
|
||||
/>
|
||||
<FormInputWith
|
||||
type="number"
|
||||
rightItem={<div className="text-sm">%</div>}
|
||||
name="discount"
|
||||
value={data.discount}
|
||||
onChange={handleOnChange}
|
||||
error={errors.discount}
|
||||
formClassName={'pr-10'}
|
||||
label="Discount"
|
||||
/>
|
||||
<FormInputNumeric
|
||||
name="price_poin"
|
||||
value={data.price_poin}
|
||||
onChange={handleOnChange}
|
||||
label="Harga poin (untuk penukaran)"
|
||||
error={errors.price_poin}
|
||||
/>
|
||||
<FormInputNumeric
|
||||
name="bonus_poin"
|
||||
value={data.bonus_poin}
|
||||
onChange={handleOnChange}
|
||||
label="Bonus poin"
|
||||
error={errors.bonus_poin}
|
||||
/>
|
||||
<FormInput
|
||||
name="quota"
|
||||
value={data.quota}
|
||||
onChange={handleOnChange}
|
||||
label="Kuota"
|
||||
error={errors.quota}
|
||||
/>
|
||||
<FormInputNumeric
|
||||
name="min_stock"
|
||||
value={data.min_stock}
|
||||
onChange={handleOnChange}
|
||||
label="Minimal Stok"
|
||||
error={errors.min_stock}
|
||||
/>
|
||||
<div className="mb-2">
|
||||
<label className="block text-sm font-medium text-gray-900 dark:text-white">
|
||||
Masa Aktif
|
||||
</label>
|
||||
<div className="w-full flex flex-row space-x-2 items-center">
|
||||
<FormInput
|
||||
type="number"
|
||||
name="expired"
|
||||
value={data.expired}
|
||||
onChange={handleOnChange}
|
||||
error={errors.expired}
|
||||
className="flex-1"
|
||||
/>
|
||||
<div>
|
||||
<select
|
||||
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
onChange={handleOnChange}
|
||||
value={data.expired_unit}
|
||||
name="expired_unit"
|
||||
>
|
||||
{expireds.map((unit) => (
|
||||
<option value={unit} key={unit}>
|
||||
{unit}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
label="Level Harga"
|
||||
value={use_level}
|
||||
onChange={(e) => handleUseLevel(e.target.value)}
|
||||
/>
|
||||
<div
|
||||
className={`p-2 mt-2 border rounded ${
|
||||
!use_level && 'hidden'
|
||||
}`}
|
||||
>
|
||||
{errors.prices && (
|
||||
<p className="mb-2 text-sm text-red-600 dark:text-red-500">
|
||||
{errors.prices}
|
||||
</p>
|
||||
)}
|
||||
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 mb-4">
|
||||
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||
<tr>
|
||||
<th scope="col" className="py-3 px-6">
|
||||
Level
|
||||
</th>
|
||||
<th scope="col" className="py-3 px-6">
|
||||
Harga
|
||||
</th>
|
||||
<th scope="col" className="py-3 px-6">
|
||||
Diskon
|
||||
</th>
|
||||
<th scope="col" className="py-3 px-6">
|
||||
Harga Poin
|
||||
</th>
|
||||
<th scope="col" className="py-3 px-6">
|
||||
Bonus Poin
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.prices?.map((price) => (
|
||||
<tr
|
||||
className="bg-white border-b dark:bg-gray-800 dark:border-gray-700"
|
||||
key={price.level.id}
|
||||
>
|
||||
<td
|
||||
scope="row"
|
||||
className="py-4 px-6 font-medium text-gray-900 whitespace-nowrap dark:text-white"
|
||||
>
|
||||
{price.level.name}
|
||||
</td>
|
||||
<td
|
||||
scope="row"
|
||||
className="py-2 px-2"
|
||||
>
|
||||
<FormInputNumeric
|
||||
value={price.display_price}
|
||||
name="display_price"
|
||||
onChange={(e) =>
|
||||
handleSetLevelPrice(
|
||||
price.customer_level_id,
|
||||
e
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
<td
|
||||
scope="row"
|
||||
className="py-2 px-2"
|
||||
>
|
||||
<FormInputNumeric
|
||||
value={price.discount}
|
||||
name="discount"
|
||||
onChange={(e) =>
|
||||
handleSetLevelPrice(
|
||||
price.customer_level_id,
|
||||
e
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
<td
|
||||
scope="row"
|
||||
className="py-2 px-2"
|
||||
>
|
||||
<FormInputNumeric
|
||||
value={price.price_poin}
|
||||
name="price_poin"
|
||||
onChange={(e) =>
|
||||
handleSetLevelPrice(
|
||||
price.customer_level_id,
|
||||
e
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
<td
|
||||
scope="row"
|
||||
className="py-2 px-2"
|
||||
>
|
||||
<FormInputNumeric
|
||||
value={price.bonus_poin}
|
||||
name="bonus_poin"
|
||||
onChange={(e) =>
|
||||
handleSetLevelPrice(
|
||||
price.customer_level_id,
|
||||
e
|
||||
)
|
||||
}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="mt-8">
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
processing={processing}
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AuthenticatedLayout>
|
||||
)
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Link, router } from '@inertiajs/react'
|
||||
import { usePrevious } from 'react-use'
|
||||
import { Head } from '@inertiajs/react'
|
||||
import { Button, Dropdown } from 'flowbite-react'
|
||||
import { HiPencil, HiTrash } from 'react-icons/hi'
|
||||
import { useModalState } from '@/hooks'
|
||||
|
||||
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
|
||||
import Pagination from '@/Components/Pagination'
|
||||
import ModalConfirm from '@/Components/ModalConfirm'
|
||||
import SearchInput from '@/Components/SearchInput'
|
||||
import LocationSelectionInput from '../Location/SelectionInput'
|
||||
import { hasPermission } from '@/utils'
|
||||
|
||||
export default function Index(props) {
|
||||
const {
|
||||
query: { links, data },
|
||||
auth,
|
||||
} = props
|
||||
|
||||
const [location, setLocation] = useState(null)
|
||||
const [search, setSearch] = useState('')
|
||||
const preValue = usePrevious(`${search}${location}`)
|
||||
|
||||
const confirmModal = useModalState()
|
||||
|
||||
const handleDeleteClick = (profile) => {
|
||||
confirmModal.setData(profile)
|
||||
confirmModal.toggle()
|
||||
}
|
||||
|
||||
const onDelete = () => {
|
||||
if (confirmModal.data !== null) {
|
||||
router.delete(
|
||||
route('location-profile.destroy', confirmModal.data.id)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const params = { q: search, location_id: location }
|
||||
useEffect(() => {
|
||||
if (preValue) {
|
||||
router.get(
|
||||
route(route().current()),
|
||||
{ q: search, location_id: location },
|
||||
{
|
||||
replace: true,
|
||||
preserveState: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
}, [search, location])
|
||||
|
||||
const canCreate = hasPermission(auth, 'create-location-profile')
|
||||
const canUpdate = hasPermission(auth, 'update-location-profile')
|
||||
const canDelete = hasPermission(auth, 'delete-location-profile')
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout
|
||||
auth={props.auth}
|
||||
errors={props.errors}
|
||||
flash={props.flash}
|
||||
page={'Profile Lokasi'}
|
||||
action={''}
|
||||
>
|
||||
<Head title="Profile Lokasi" />
|
||||
|
||||
<div>
|
||||
<div className="mx-auto sm:px-6 lg:px-8 ">
|
||||
<div className="p-6 overflow-hidden shadow-sm sm:rounded-lg bg-gray-200 dark:bg-gray-800 space-y-4">
|
||||
<div className="flex justify-between">
|
||||
{canCreate && (
|
||||
<div className="flex flex-row space-x-2">
|
||||
<Link
|
||||
href={route('location-profile.create')}
|
||||
>
|
||||
<Button size="sm">Tambah</Button>
|
||||
</Link>
|
||||
{/* <Link
|
||||
href={route('location-profile.import')}
|
||||
>
|
||||
<Button size="sm" outline>
|
||||
Import
|
||||
</Button>
|
||||
</Link> */}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-row space-x-2 items-center">
|
||||
<LocationSelectionInput
|
||||
itemSelected={location}
|
||||
onItemSelected={(id) => setLocation(id)}
|
||||
placeholder={'filter lokasi'}
|
||||
/>
|
||||
<SearchInput
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
value={search}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="overflow-auto">
|
||||
<div>
|
||||
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 mb-4">
|
||||
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||
<tr>
|
||||
<th
|
||||
scope="col"
|
||||
className="py-3 px-6"
|
||||
>
|
||||
Nama
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="py-3 px-6"
|
||||
>
|
||||
Lokasi
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="py-3 px-6"
|
||||
>
|
||||
Kuota
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="py-3 px-6"
|
||||
>
|
||||
Masa Aktif
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
className="py-3 px-6 w-1/8"
|
||||
/>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((profile, index) => (
|
||||
<tr
|
||||
className="bg-white border-b dark:bg-gray-800 dark:border-gray-700"
|
||||
key={profile.id}
|
||||
>
|
||||
<td
|
||||
scope="row"
|
||||
className="py-4 px-6 font-medium text-gray-900 whitespace-nowrap dark:text-white"
|
||||
>
|
||||
{profile.name}
|
||||
</td>
|
||||
<td
|
||||
scope="row"
|
||||
className="py-4 px-6"
|
||||
>
|
||||
{profile.location.name}
|
||||
</td>
|
||||
<td
|
||||
scope="row"
|
||||
className="py-4 px-6"
|
||||
>
|
||||
{profile.quota}
|
||||
</td>
|
||||
<td
|
||||
scope="row"
|
||||
className="py-4 px-6"
|
||||
>
|
||||
{profile.diplay_expired}
|
||||
</td>
|
||||
<td className="py-4 px-6 flex justify-end">
|
||||
<Dropdown
|
||||
label={'Opsi'}
|
||||
floatingArrow={true}
|
||||
arrowIcon={true}
|
||||
dismissOnClick={true}
|
||||
size={'sm'}
|
||||
>
|
||||
{canUpdate && (
|
||||
<Dropdown.Item>
|
||||
<Link
|
||||
href={route(
|
||||
'location-profile.edit',
|
||||
profile
|
||||
)}
|
||||
className="flex space-x-1 items-center"
|
||||
>
|
||||
<HiPencil />
|
||||
<div>
|
||||
Ubah
|
||||
</div>
|
||||
</Link>
|
||||
</Dropdown.Item>
|
||||
)}
|
||||
{canDelete && (
|
||||
<Dropdown.Item
|
||||
onClick={() =>
|
||||
handleDeleteClick(
|
||||
profile
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex space-x-1 items-center">
|
||||
<HiTrash />
|
||||
<div>
|
||||
Hapus
|
||||
</div>
|
||||
</div>
|
||||
</Dropdown.Item>
|
||||
)}
|
||||
</Dropdown>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="w-full flex items-center justify-center">
|
||||
<Pagination links={links} params={params} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ModalConfirm modalState={confirmModal} onConfirm={onDelete} />
|
||||
</AuthenticatedLayout>
|
||||
)
|
||||
}
|
@ -0,0 +1 @@
|
||||
export const DEFAULT_EXPIRED_UNIT = 'Hari'
|
Loading…
Reference in New Issue