mirror of
https://github.com/anna-sara/lan_kiosk
synced 2026-03-16 11:45:40 +01:00
Feature: Create groups
This commit is contained in:
parent
0ee99592b5
commit
8770925309
20 changed files with 1019 additions and 82 deletions
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Customer;
|
||||
use App\Models\CustomerGroup;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Purchase;
|
||||
use Inertia\Inertia;
|
||||
|
|
@ -14,7 +15,8 @@ class CustomerController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
$customers = Customer::orderBy('name', 'asc')->get();
|
||||
$customers = Customer::where('is_in_group', 0)->orderBy('name', 'asc')->get();
|
||||
|
||||
return Inertia::render('Dashboard', ['customers' => $customers]);
|
||||
}
|
||||
|
||||
|
|
@ -52,16 +54,22 @@ class CustomerController extends Controller
|
|||
public function show($id)
|
||||
{
|
||||
$customer = Customer::with('purchases')->with('deposits')->findOrFail($id);
|
||||
$groupmembers = Customer::where('is_in_group', 1)->where('customer_group_id', $customer->customer_group_id)->get();
|
||||
|
||||
return Inertia::render('Customer', ['customer' => $customer]);
|
||||
|
||||
return Inertia::render('Customer', ['customer' => $customer, 'groupmembers' => $groupmembers]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(Customers $customers)
|
||||
public function edit($id)
|
||||
{
|
||||
//
|
||||
$customer = Customer::findOrFail($id);
|
||||
|
||||
$customer->customer_group_id = null;
|
||||
$customer->is_in_group = 0;
|
||||
$customer->save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -112,4 +120,5 @@ class CustomerController extends Controller
|
|||
'success' => true, 'message' => 'Customer deleted successfully'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
142
app/Http/Controllers/CustomerGroupController.php
Normal file
142
app/Http/Controllers/CustomerGroupController.php
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\CustomerGroup;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Deposit;
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Inertia;
|
||||
|
||||
class CustomerGroupController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$groups = CustomerGroup::with('customers')->get();
|
||||
$customers = Customer::whereNull('customer_group_id')->where('is_in_group', false)->orderBy('name', 'asc')->get();
|
||||
|
||||
return Inertia::render('CustomerGroups', ['groups' => $groups, 'customers' => $customers]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
|
||||
$request->validate([
|
||||
'group_name' => 'required',
|
||||
'customers' => 'required',
|
||||
]);
|
||||
|
||||
$customers = $request->customers;
|
||||
|
||||
$guardian_name = Customer::where('id', (int) $customers[0])->pluck('guardian_name');
|
||||
|
||||
$customerGroup = CustomerGroup::create([
|
||||
'name' => $request->group_name,
|
||||
]);
|
||||
|
||||
|
||||
$groupCustomer = Customer::create([
|
||||
'name' => $request->group_name,
|
||||
'guardian_name' => $guardian_name[0],
|
||||
'is_in_group' => false,
|
||||
'customer_group_id' => $customerGroup->id
|
||||
]);
|
||||
|
||||
$groupAmount= 0;
|
||||
|
||||
foreach ($customers as $customerItem) {
|
||||
$customer = Customer::findOrFail($customerItem);
|
||||
$customer->customer_group_id = $customerGroup->id;
|
||||
$customer->is_in_group = 1;
|
||||
$groupAmount += $customer->deposit;
|
||||
$customer->deposit = 0;
|
||||
$customer->save();
|
||||
}
|
||||
|
||||
Deposit::create([
|
||||
'customer_id' => $groupCustomer->id,
|
||||
'amount' => $groupAmount,
|
||||
]);
|
||||
|
||||
$groupCustomer->amount_left = $groupAmount;
|
||||
$groupCustomer->deposit = $groupAmount;
|
||||
$groupCustomer->save();
|
||||
|
||||
return redirect('customer-groups/');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(CustomerGroup $customerGroup)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(CustomerGroup $customerGroup)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update($id, Request $request)
|
||||
{
|
||||
|
||||
$request->validate([
|
||||
'customers' => 'required',
|
||||
]);
|
||||
|
||||
$customers = $request->customers;
|
||||
$groupCustomer = Customer::where('customer_group_id', $id)->where('is_in_group', 0)->first();
|
||||
|
||||
foreach ($customers as $customerItem) {
|
||||
$customer = Customer::findOrFail($customerItem);
|
||||
$groupCustomer->deposit += $customer->deposit;
|
||||
$groupCustomer->amount_left += $customer->deposit;
|
||||
$groupCustomer->save();
|
||||
$customer->customer_group_id = $id;
|
||||
$customer->is_in_group = 1;
|
||||
$customer->deposit = 0;
|
||||
$customer->save();
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true, 'message' => 'Customer group was updated'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$group = CustomerGroup::findOrFail( $id );
|
||||
$customerGroup = Customer::where('customer_group_id', $group->id);
|
||||
$customerGroup->delete();
|
||||
$group->delete();
|
||||
|
||||
return response()->json([
|
||||
'success' => true, 'message' => 'Customer group deleted successfully'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -41,12 +41,37 @@ class DepositController extends Controller
|
|||
]);
|
||||
|
||||
$customer = Customer::findOrFail($request->customer_id);
|
||||
|
||||
if ($customer->is_in_group) {
|
||||
$groupCustomer = Customer::where('customer_group_id', $customer->customer_group_id)->where('is_in_group', 0)->first();
|
||||
$groupCustomer->deposit += $customer->deposit;
|
||||
$groupCustomer->amount_left += $request->deposit;
|
||||
$groupCustomer->save();
|
||||
$customer->deposit = 0;
|
||||
$customer->save();
|
||||
|
||||
if ($request->manual_deposit === 1) {
|
||||
return redirect('customer/' . $request->customer_id);
|
||||
}
|
||||
return response()->json([
|
||||
'success' => true, 'message' => 'Deposit added successfully'
|
||||
]);
|
||||
|
||||
|
||||
} else {
|
||||
$customer->deposit = $customer->deposit + $request->deposit;
|
||||
$customer->amount_left = $customer->amount_left + $request->deposit;
|
||||
$customer->save();
|
||||
|
||||
if ($request->manual_deposit === 1) {
|
||||
return redirect('customer/' . $request->customer_id);
|
||||
}
|
||||
return response()->json([
|
||||
'success' => true, 'message' => 'Deposit added successfully'
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
|
|
|
|||
27
app/Http/Middleware/ApiToken.php
Normal file
27
app/Http/Middleware/ApiToken.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ApiToken
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if ($request->header('X-API-KEY') === config('app.apikey_deposit')) {
|
||||
|
||||
return $next($request);
|
||||
|
||||
} else {
|
||||
return response()->json(['code' => 401, 'message' => 'Unauthorized']);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -14,13 +14,16 @@ class Customer extends Model
|
|||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'lan_id',
|
||||
'name',
|
||||
'guardian_name',
|
||||
'amount left',
|
||||
'amount used',
|
||||
'deposit',
|
||||
'give_leftover',
|
||||
'comment'
|
||||
'comment',
|
||||
'customer_group_id',
|
||||
'is_in_group'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
26
app/Models/CustomerGroup.php
Normal file
26
app/Models/CustomerGroup.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Models\Customer;
|
||||
|
||||
class CustomerGroup extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the customers for the group.
|
||||
*/
|
||||
public function customers()
|
||||
{
|
||||
return $this->hasMany(Customer::class);
|
||||
}
|
||||
}
|
||||
13
app/Models/Tableversion.php
Normal file
13
app/Models/Tableversion.php
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Tableversion extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'table',
|
||||
'version'
|
||||
];
|
||||
}
|
||||
|
|
@ -123,4 +123,9 @@ return [
|
|||
'store' => env('APP_MAINTENANCE_STORE', 'database'),
|
||||
],
|
||||
|
||||
'apikey_deposit' => env('API_KEY_DEPOSIT'),
|
||||
'apilan_key' => env('API_LAN_KEY'),
|
||||
'apilan_url' => env('API_LAN_URL'),
|
||||
'apilan_clientcert_path' => env('API_LAN_CLIENTCERT_PATH')
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('customers', function (Blueprint $table) {
|
||||
$table->boolean('is_in_group')->default(false);
|
||||
$table->integer('customer_group_id')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('customers', function (Blueprint $table) {
|
||||
$table->dropColumn('is_in_group');
|
||||
$table->dropColumn('customer_group_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('customer_groups', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('customer_groups');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('customers', function (Blueprint $table) {
|
||||
$table->integer('lan_id')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('customers', function (Blueprint $table) {
|
||||
$table->dropColumn('lan_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('tableversions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('table')->nullable();
|
||||
$table->integer('version')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('tableversions');
|
||||
}
|
||||
};
|
||||
|
|
@ -91,6 +91,10 @@ details {
|
|||
right: 1em;
|
||||
background: #ffffff;
|
||||
|
||||
&.group {
|
||||
top: 0.5em;
|
||||
}
|
||||
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
|
|
@ -113,3 +117,41 @@ details {
|
|||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.customer-box:nth-child(even) {
|
||||
background-color:rgba(0, 128, 187, 0.075)
|
||||
}
|
||||
|
||||
.customers-list {
|
||||
max-height: 200px;
|
||||
overflow-y: scroll;
|
||||
padding: 5px;}
|
||||
|
||||
|
||||
.add-customer-to-group-modal {
|
||||
//display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
padding-top: 100px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgb(0,0,0);
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.add-customer-to-group-modal-content {
|
||||
background-color: #fefefe;
|
||||
margin: auto;
|
||||
padding: 40px;
|
||||
width: 60%;
|
||||
position: relative;
|
||||
|
||||
.delete {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
|
|
@ -24,15 +24,23 @@ export default function Authenticated({
|
|||
<img className="navbar-logo" src="/img/logo.png" />
|
||||
</Link>
|
||||
</div>
|
||||
{/*
|
||||
|
||||
<div className="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
|
||||
<NavLink
|
||||
href={route('dashboard')}
|
||||
href="/dashboard"
|
||||
active={route().current('dashboard')}
|
||||
>
|
||||
Dashboard
|
||||
Deltagare
|
||||
</NavLink>
|
||||
</div>*/}
|
||||
</div>
|
||||
<div className="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
|
||||
<NavLink
|
||||
href="/customer-groups"
|
||||
active={route().current('customer-groups')}
|
||||
>
|
||||
Grupper
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="hidden sm:ms-6 sm:flex sm:items-center">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import TextInput from '@/Components/TextInput';
|
||||
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
|
||||
import { Textarea } from '@headlessui/react';
|
||||
import { Head, useForm } from '@inertiajs/react';
|
||||
import axios from 'axios';
|
||||
import { FormEventHandler } from 'react';
|
||||
|
|
@ -8,6 +7,7 @@ import { FormEventHandler } from 'react';
|
|||
interface CustomerProps {
|
||||
customer:{
|
||||
id: number
|
||||
lan_id: number,
|
||||
name: string
|
||||
deposit: number
|
||||
amount_left: number
|
||||
|
|
@ -25,16 +25,31 @@ interface CustomerProps {
|
|||
}
|
||||
};
|
||||
|
||||
export default function Customer({customer}: CustomerProps) {
|
||||
interface GroupmembersProps {
|
||||
groupmembers:[{
|
||||
id: number
|
||||
lan_id: number,
|
||||
name: string
|
||||
deposit: number
|
||||
amount_left: number
|
||||
give_leftover: number
|
||||
guardian_name: string
|
||||
comment: string;
|
||||
}]
|
||||
};
|
||||
|
||||
export default function Customer({customer, groupmembers}: (CustomerProps & GroupmembersProps) ) {
|
||||
|
||||
const { data, setData, post, processing, errors, reset } = useForm({
|
||||
amount: "",
|
||||
customer_id: customer.id,
|
||||
deposit: "",
|
||||
id: customer.id,
|
||||
comment: ""
|
||||
comment: "",
|
||||
manual_deposit: 0
|
||||
});
|
||||
|
||||
|
||||
const submit: FormEventHandler = (e) => {
|
||||
e.preventDefault()
|
||||
post(route('register_purchase'), {
|
||||
|
|
@ -47,10 +62,11 @@ export default function Customer({customer}: CustomerProps) {
|
|||
const submitDeposit: FormEventHandler = (e) => {
|
||||
e.preventDefault()
|
||||
post(route('register_deposit'), {
|
||||
headers: {'X-API-KEY': '123', 'Accept': 'application/json', 'Content-Type': 'application/json'},
|
||||
onFinish: () => setData(
|
||||
'deposit', ''
|
||||
),
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
const updateComment: FormEventHandler = (e) => {
|
||||
|
|
@ -73,13 +89,24 @@ export default function Customer({customer}: CustomerProps) {
|
|||
|
||||
<section className='section'>
|
||||
<div className="container is-max-desktop">
|
||||
<h1 className="title is-2">{customer.name}</h1>
|
||||
<a href="/dashboard" className="button mb-5 is-small is-white">Tillbaka</a>
|
||||
<h1 className="title is-2">{customer.lan_id ? customer.lan_id + "." : "Grupp"} {customer.name}</h1>
|
||||
<div className='container is-centered'>
|
||||
<div className="box">
|
||||
<h2 className='title is-4'>Saldo: {customer.amount_left ? customer.amount_left : 0} kr</h2>
|
||||
<p>Inbetalad summa: {customer.deposit ? customer.deposit : 0} kr</p>
|
||||
<p>Vårnadshavare: {customer.guardian_name}</p>
|
||||
<p>Ge ev överblivet saldo till vBytes: {customer.give_leftover ? "Ja" : "Nej"}</p>
|
||||
{groupmembers.length > 0 &&
|
||||
<>
|
||||
<h2 className='title is-5 mt-5 mb-2'>Gruppmedlemmar</h2>
|
||||
{groupmembers && groupmembers.map( member => {
|
||||
console.log(member)
|
||||
return <p>{member.lan_id}. {member.name} </p>
|
||||
|
||||
})}
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className="box">
|
||||
|
|
@ -144,7 +171,7 @@ export default function Customer({customer}: CustomerProps) {
|
|||
</svg>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
{groupmembers.length < 1 &&
|
||||
<details className="box">
|
||||
<summary className='title is-4 my-3'>
|
||||
<span>Inbetalning Swish/kontant</span>
|
||||
|
|
@ -164,7 +191,7 @@ export default function Customer({customer}: CustomerProps) {
|
|||
name="deposit"
|
||||
value={data.deposit}
|
||||
placeholder="Summa"
|
||||
onChange={(e) => setData('deposit', e.target.value)}
|
||||
onChange={(e) => [setData('deposit', e.target.value), setData('manual_deposit', 1)]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -181,7 +208,7 @@ export default function Customer({customer}: CustomerProps) {
|
|||
</svg>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
}
|
||||
|
||||
|
||||
<details className="box">
|
||||
|
|
|
|||
384
resources/js/Pages/CustomerGroups.tsx
Normal file
384
resources/js/Pages/CustomerGroups.tsx
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
|
||||
import TextInput from '@/Components/TextInput';
|
||||
import { Head, useForm } from '@inertiajs/react';
|
||||
import { FormEventHandler, SetStateAction, useState } from 'react';
|
||||
import axios from 'axios';
|
||||
import Customer from './Customer';
|
||||
|
||||
|
||||
interface CustomerProps {
|
||||
customers: [{
|
||||
id: number
|
||||
name: string
|
||||
customer_group_id: string,
|
||||
is_in_group: boolean
|
||||
}],
|
||||
};
|
||||
|
||||
type Customer = {
|
||||
id: number
|
||||
name: string
|
||||
customer_group_id: string,
|
||||
is_in_group: boolean
|
||||
|
||||
};
|
||||
|
||||
interface CustomerGroupProps {
|
||||
groups: [{
|
||||
name: string,
|
||||
id: number,
|
||||
customers: [{
|
||||
id: number
|
||||
name: string
|
||||
customer_group_id: string,
|
||||
is_in_group: boolean
|
||||
}],
|
||||
}]
|
||||
};
|
||||
|
||||
type CustomerGroup = {
|
||||
name: string,
|
||||
id: number,
|
||||
customers: [{
|
||||
id: number
|
||||
name: string
|
||||
customer_group_id: string,
|
||||
is_in_group: boolean
|
||||
}],
|
||||
};
|
||||
|
||||
type FormInputs = {
|
||||
id: number | null;
|
||||
customers: Customer[],
|
||||
group_name: string,
|
||||
};
|
||||
|
||||
interface CurrentGroup {
|
||||
id?: number | null ;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export default function CustomerGroups({groups, customers} :( CustomerGroupProps & CustomerProps) ) {
|
||||
const [addCustomerToGroupModal, setAddCustomerToGroupModal] = useState(false);
|
||||
const [currentGroup, setCurrentGroup] = useState<CurrentGroup>({id: null, name: ""});
|
||||
const [searchItemGroup, setSearchItemGroup] = useState('');
|
||||
const [searchItemCustomers, setSearchItemCustomers] = useState('')
|
||||
const [searchItemCustomersAddToGroup, setSearchItemCustomersAddToGroup] = useState('')
|
||||
const [uniqueGroupNameError, setUniqueGroupNameError,] = useState(false)
|
||||
const [activeTabLetter, setActiveTabLetter] = useState('')
|
||||
const [activeTab, setActiveTab] = useState('groups')
|
||||
const [filteredCustomers, setFilteredCustomers] = useState<Customer[]>(customers)
|
||||
const [filteredCustomersAddToGroup, setFilteredCustomersAddToGroup] = useState<Customer[]>(customers)
|
||||
const [filteredGroups, setFilteredGroups] = useState<CustomerGroup[]>(groups)
|
||||
const [checkboxes, setCheckboxes] = useState<any[]>([]);
|
||||
const [checkboxesAddToGroup, setCheckboxesAddToGroup] = useState<any[]>([]);
|
||||
const letterArray = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","Å","Ä","Ö"];
|
||||
|
||||
const { data, setData, post, processing, errors, reset } = useForm<FormInputs>({
|
||||
id: null,
|
||||
group_name: "",
|
||||
customers: []
|
||||
});
|
||||
|
||||
//Group
|
||||
const handleInputChangeCreateGroup = (e: any) => {
|
||||
const searchTerm = e.target.value;
|
||||
setSearchItemCustomers(searchTerm)
|
||||
|
||||
const filteredItems = customers.filter((customer) =>
|
||||
customer.name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
setFilteredCustomers(filteredItems);
|
||||
}
|
||||
|
||||
const submitGroup: FormEventHandler = (e : any) => {
|
||||
e.preventDefault()
|
||||
let submit = true;
|
||||
groups.map( group => {
|
||||
if (data.group_name.toLowerCase() === group.name.toLowerCase()) {
|
||||
setUniqueGroupNameError(true);
|
||||
submit = false;
|
||||
}
|
||||
})
|
||||
|
||||
if (submit) {
|
||||
post(route('register_customer_group'), {
|
||||
onFinish: () => [setData(
|
||||
'group_name', '',
|
||||
|
||||
), setCheckboxes([]),
|
||||
window.location.href = "/customer-groups"],
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const handleInputChangeGroup = (e: any) => {
|
||||
const searchTerm = e.target.value;
|
||||
setSearchItemGroup(searchTerm)
|
||||
|
||||
const filteredItems = groups.filter((customer) =>
|
||||
customer.name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
setFilteredGroups(filteredItems);
|
||||
}
|
||||
|
||||
|
||||
const handleInputClick = (searchTerm: string) => {
|
||||
const filteredItems = groups.filter((customer) =>
|
||||
customer.name.toLowerCase().startsWith(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
setFilteredGroups(filteredItems);
|
||||
}
|
||||
|
||||
const handleCheckBoxChange = (e: any) => {
|
||||
let index = e.target.dataset.id;
|
||||
let prev = checkboxes;
|
||||
let itemIndex = prev.indexOf(index);
|
||||
if (itemIndex !== -1) {
|
||||
prev.splice(itemIndex, 1);
|
||||
} else {
|
||||
prev.push(index);
|
||||
}
|
||||
setCheckboxes([...prev]);
|
||||
setData('customers', checkboxes)
|
||||
}
|
||||
|
||||
const deleteCustomerGroup = (id: string | number | undefined) => {
|
||||
axios.delete('/api/customer-group/' + id)
|
||||
.then(response => {
|
||||
window.location.href = "/customer-groups";
|
||||
})
|
||||
.catch(error => {console.log(error)})
|
||||
}
|
||||
|
||||
// Add to group
|
||||
const handleInputChangeAddToGroup = (e: any) => {
|
||||
const searchTerm = e.target.value;
|
||||
setSearchItemCustomersAddToGroup(searchTerm)
|
||||
|
||||
const filteredItems = customers.filter((customer) =>
|
||||
customer.name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
setFilteredCustomersAddToGroup(filteredItems);
|
||||
}
|
||||
|
||||
const addToGroup = (id: number | null | undefined) => {
|
||||
axios.post('/api/add-to-customer-group/' + id, {customers: data.customers})
|
||||
.then(response => {
|
||||
window.location.href = "/customer-groups";
|
||||
})
|
||||
.catch(error => {console.log(error)})
|
||||
}
|
||||
|
||||
const handleCheckBoxChangeAddToGroup = (e: any) => {
|
||||
let index = e.target.dataset.id;
|
||||
let prev = checkboxesAddToGroup;
|
||||
let itemIndex = prev.indexOf(index);
|
||||
if (itemIndex !== -1) {
|
||||
prev.splice(itemIndex, 1);
|
||||
} else {
|
||||
prev.push(index);
|
||||
}
|
||||
setCheckboxesAddToGroup([...prev]);
|
||||
setData('customers', checkboxesAddToGroup)
|
||||
}
|
||||
|
||||
const deleteCustomerFromGroup = (id: string | number) => {
|
||||
axios.put('/api/customer/' + id)
|
||||
.then(response => {
|
||||
window.location.href = "/customer-groups";
|
||||
})
|
||||
.catch(error => {console.log(error)})
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout>
|
||||
<Head title="Dashboard" />
|
||||
{ addCustomerToGroupModal &&
|
||||
<div className='add-customer-to-group-modal'>
|
||||
<div className='add-customer-to-group-modal-content'>
|
||||
<button onClick={() => setAddCustomerToGroupModal(false)} className="delete is-large" aria-label="close"></button>
|
||||
<form className='container is-centered'>
|
||||
<h2 className="mt-4 title is-3" >Lägg till deltagare i grupp {currentGroup.name}</h2>
|
||||
<div className='customers-list is-flex is-flex-direction-column gap-3 container is-centered my-4'>
|
||||
{filteredCustomersAddToGroup && filteredCustomersAddToGroup
|
||||
.map( customer => {
|
||||
return <label className='checkbox'>
|
||||
<input type="checkbox" className='mr-2' data-id={customer.id} onClick={handleCheckBoxChangeAddToGroup}/>
|
||||
{customer.name}
|
||||
</label>
|
||||
})}
|
||||
</div>
|
||||
<input
|
||||
className='input'
|
||||
type="text"
|
||||
value={searchItemCustomersAddToGroup}
|
||||
onChange={handleInputChangeAddToGroup}
|
||||
placeholder='Skriv för att söka deltagare/funktionär'
|
||||
/>
|
||||
<div className='is-flex mt-3'>
|
||||
<span className='mr-2 has-text-weight-bold'>Valda deltagare/funktionärer: </span>
|
||||
{filteredCustomersAddToGroup && filteredCustomersAddToGroup
|
||||
.filter((filteredCustomer) => checkboxesAddToGroup.includes("" + filteredCustomer.id))
|
||||
.map( customer => {
|
||||
return <p key={customer.id} className='mr-2 tag'>
|
||||
{customer.name}
|
||||
</p>
|
||||
|
||||
})}
|
||||
</div>
|
||||
<button onClick={() => addToGroup(currentGroup.id)} className="button mt-4 is-small is-white">Lägg till deltagare</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<section className='section'>
|
||||
<div className="container is-max-desktop">
|
||||
<a href="/dashboard" className="button mb-5 is-small is-white">Tillbaka</a>
|
||||
<div className="tabs is-centered is-boxed">
|
||||
<ul>
|
||||
<li className={activeTab === "groups" ? "is-active" : ""}>
|
||||
<a onClick={() => setActiveTab('groups') }>
|
||||
<span>Grupper</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className={activeTab === "create-group" ? "is-active" : ""}>
|
||||
<a onClick={() => setActiveTab('create-group') }>
|
||||
<span>Skapa grupp</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{activeTab === "create-group" && <>
|
||||
<h2 className="title is-2">Skapa grupp</h2>
|
||||
<div className='create-group-container mb-7'>
|
||||
<div>
|
||||
<form onSubmit={submitGroup} className='container is-centered'>
|
||||
<p className="mb-4">Namn på grupp:</p>
|
||||
<TextInput
|
||||
required
|
||||
className="input"
|
||||
type="text"
|
||||
name="group_name"
|
||||
value={data.group_name}
|
||||
placeholder="Namn på grupp"
|
||||
min={0}
|
||||
//max={customer.group_name_left}
|
||||
onChange={(e) => setData('group_name', e.target.value)}
|
||||
/>
|
||||
{uniqueGroupNameError && <p>Gruppnamn är inte unikt</p>}
|
||||
|
||||
<p className="mt-4" >Välj vilka som ska ingå i gruppen:</p>
|
||||
|
||||
<div className='customers-list is-flex is-flex-direction-column gap-3 container is-centered my-4'>
|
||||
{filteredCustomers && filteredCustomers
|
||||
.map( customer => {
|
||||
return <label key={customer.id} className='checkbox'>
|
||||
<input type="checkbox" className='mr-2' data-id={customer.id} onClick={handleCheckBoxChange}/>
|
||||
{customer.name}
|
||||
</label>
|
||||
})}
|
||||
</div>
|
||||
<input
|
||||
className='input'
|
||||
type="text"
|
||||
value={searchItemCustomers}
|
||||
onChange={handleInputChangeCreateGroup}
|
||||
placeholder='Skriv för att söka deltagare/funktionär'
|
||||
/>
|
||||
<div className='is-flex mt-3'>
|
||||
<span className='mr-2 has-text-weight-bold'>Valda deltagare/funktionärer: </span>
|
||||
{filteredCustomers && filteredCustomers
|
||||
.filter((filteredCustomer) => checkboxes.includes("" + filteredCustomer.id))
|
||||
.map( customer => {
|
||||
return <p key={customer.id} className='mr-2 tag'>
|
||||
{customer.name}
|
||||
</p>
|
||||
|
||||
})}
|
||||
</div>
|
||||
<button className="button mt-4 is-small is-white">Skapa grupp</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
{ activeTab === "groups" && <>
|
||||
<h2 className="title is-2">Grupper</h2>
|
||||
<input
|
||||
className='input my-4'
|
||||
type="text"
|
||||
value={searchItemGroup}
|
||||
onChange={handleInputChangeGroup}
|
||||
placeholder='Skriv för att söka'
|
||||
/>
|
||||
<div>
|
||||
<ul className='grid is-col-min-2 is-column-gap-1 mb-5'>
|
||||
{ letterArray && letterArray.map( letter => {
|
||||
return <li className={`${activeTabLetter == letter ? "is-active" : ""} cell button letter is-small is-white`} onClick={ () => [setActiveTabLetter(letter) ,handleInputClick(letter)]}>
|
||||
{letter}
|
||||
</li>
|
||||
})
|
||||
}
|
||||
<li className='cell button is-small is-white' onClick={ () => [setActiveTabLetter(""), setFilteredGroups(groups), setSearchItemGroup("") ]}>
|
||||
Rensa
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div className='container is-centered'>
|
||||
|
||||
{filteredGroups && filteredGroups.map( group => {
|
||||
return <details className="box">
|
||||
<summary className='title is-4 my-3'>
|
||||
<span>{group.name}</span>
|
||||
<div className="summary-chevron-up">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="feather feather-chevron-down">
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
</summary>
|
||||
|
||||
{ group.customers.length < 2 &&
|
||||
<button onClick={() => deleteCustomerGroup(group.id)} className="button is-danger is-outlined is-small">
|
||||
<span>Ta bort grupp</span>
|
||||
</button>
|
||||
}
|
||||
<ul>
|
||||
{ group.customers.length > 0 && group.customers.filter((customer) => customer.is_in_group).map( customer => {
|
||||
return <div className='is-flex gap-4 border-b p-2 is-justify-content-space-between'>
|
||||
<p className="is-size-5">{customer.name}</p>
|
||||
<button onClick={() => deleteCustomerFromGroup(customer.id)} className="button is-danger is-outlined is-small">
|
||||
<span>Ta bort från grupp</span>
|
||||
</button>
|
||||
</div>
|
||||
})}
|
||||
|
||||
</ul>
|
||||
<button className="button mt-4 is-small is-white" onClick={() => [setAddCustomerToGroupModal(true), setCurrentGroup({id: group.id, name: group.name})]}>Lägg till deltagare</button>
|
||||
<div className="summary-chevron-down">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="feather feather-chevron-up">
|
||||
<polyline points="18 15 12 9 6 15"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
</details>
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</AuthenticatedLayout>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
|
||||
import { Head } from '@inertiajs/react';
|
||||
import { SetStateAction, useState } from 'react';
|
||||
import { Head, useForm } from '@inertiajs/react';
|
||||
import {useState } from 'react';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faArrowRight } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
|
|
@ -9,21 +9,25 @@ interface CustomerProps {
|
|||
customers: [{
|
||||
id: number
|
||||
name: string
|
||||
group_id: string,
|
||||
is_group: boolean
|
||||
}],
|
||||
};
|
||||
|
||||
interface Customer {
|
||||
type Customer = {
|
||||
id: number
|
||||
name: string
|
||||
group_id: string,
|
||||
is_group: boolean
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
export default function Dashboard({customers}: CustomerProps) {
|
||||
export default function Dashboard({ customers }: CustomerProps) {
|
||||
const [searchItem, setSearchItem] = useState('')
|
||||
const [activeTab, setActiveTab] = useState('')
|
||||
const [filteredCustomers, setFilteredCustomers] = useState<Customer[]>(customers)
|
||||
const letterArray = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","Å","Ä","Ö"];
|
||||
const letterArray = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "Å", "Ä", "Ö"];
|
||||
|
||||
const handleInputChange = (e: any) => {
|
||||
const searchTerm = e.target.value;
|
||||
|
|
@ -44,6 +48,7 @@ export default function Dashboard({customers}: CustomerProps) {
|
|||
setFilteredCustomers(filteredItems);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout>
|
||||
<Head title="Dashboard" />
|
||||
|
|
@ -60,21 +65,21 @@ export default function Dashboard({customers}: CustomerProps) {
|
|||
/>
|
||||
<div>
|
||||
<ul className='grid is-col-min-2 is-column-gap-1 mb-5'>
|
||||
{ letterArray && letterArray.map( letter => {
|
||||
return <li className={`${activeTab == letter ? "is-active" : ""} cell button letter is-small is-white`} onClick={ () => [setActiveTab(letter) ,handleInputClick(letter)]}>
|
||||
{letterArray && letterArray.map(letter => {
|
||||
return <li className={`${activeTab == letter ? "is-active" : ""} cell button letter is-small is-white`} onClick={() => [setActiveTab(letter), handleInputClick(letter)]}>
|
||||
{letter}
|
||||
</li>
|
||||
})
|
||||
}
|
||||
<li className='cell button is-small is-white' onClick={ () => [setActiveTab(""), setFilteredCustomers(customers), setSearchItem("") ]}>
|
||||
<li className='cell button is-small is-white' onClick={() => [setActiveTab(""), setFilteredCustomers(customers), setSearchItem("")]}>
|
||||
Rensa
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div className='container is-centered'>
|
||||
{filteredCustomers && filteredCustomers.map( customer => {
|
||||
return <a key={customer.id} className="box is-flex is-justify-content-space-between" href={`/customer/` + customer.id}>
|
||||
{filteredCustomers && filteredCustomers.map(customer => {
|
||||
return <a key={customer.id} className="box customer-box is-flex is-justify-content-space-between" href={`/customer/` + customer.id}>
|
||||
<p>{customer.name}</p>
|
||||
<span className="icon has-text-black">
|
||||
<FontAwesomeIcon icon={faArrowRight} />
|
||||
|
|
|
|||
|
|
@ -3,14 +3,22 @@
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\CustomerController;
|
||||
use App\Http\Controllers\CustomerGroupController;
|
||||
use App\Http\Controllers\PurchaseController;
|
||||
use App\Http\Controllers\DepositController;
|
||||
use App\Http\Middleware\ApiToken;
|
||||
|
||||
Route::post('register_customer', [CustomerController::class, 'store'])->name('register_customer');
|
||||
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
Route::post('register_deposit', [DepositController::class, 'store'])->name('register_deposit');
|
||||
//Route::post('register_deposit', [DepositController::class, 'store'])->name('register_deposit');
|
||||
Route::post('update_comment', [CustomerController::class, 'updateComment'])->name('update_comment');
|
||||
Route::post('register_purchase', [PurchaseController::class, 'store'])->name('register_purchase');
|
||||
Route::post('customer-group', [CustomerGroupController::class, 'store'])->name('register_customer_group');
|
||||
Route::post('add-to-customer-group/{id}', [CustomerGroupController::class, 'update'])->name('add_to_customer_group');
|
||||
Route::delete('customer-group/{id}', [CustomerGroupController::class, 'destroy'])->name('delete_customer_group');
|
||||
Route::delete('customer/{id}', [CustomerController::class, 'destroy'])->name('delete_customer');
|
||||
Route::put('customer/{id}', [CustomerController::class, 'edit'])->name('edit_customer');
|
||||
});
|
||||
|
||||
Route::post('register_deposit', [DepositController::class, 'store'])->name('register_deposit')->middleware([ApiToken::class]);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,103 @@
|
|||
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Schedule;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Tableversion;
|
||||
|
||||
Artisan::command('inspire', function () {
|
||||
$this->comment(Inspiring::quote());
|
||||
})->purpose('Display an inspiring quote');
|
||||
Schedule::call(function () {
|
||||
|
||||
$latestVersionParticipant = Tableversion::where('table', 'participants')->latest()->first();
|
||||
$latestVersionVolunteer = Tableversion::where('table', 'volunteers')->latest()->first();
|
||||
|
||||
$client = new Client();
|
||||
|
||||
$responseVersions= $client->request(
|
||||
'GET',
|
||||
config('app.apilan_url') . "version",
|
||||
[
|
||||
'headers'=> [
|
||||
'X-Api-Key' => config('app.apilan_key'),
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json'
|
||||
],
|
||||
//'cert' => config('app.apilan_clientcert_path')
|
||||
'cert' => Storage::disk('public')->path('lan.vbytes.se.pem')
|
||||
],
|
||||
);
|
||||
$versions = json_decode((string) $responseVersions->getBody(), true);
|
||||
|
||||
if ($latestVersionParticipant === null ) {
|
||||
Tableversion::create([
|
||||
'table' => 'participants',
|
||||
'version' => $versions['participants'] - 1,
|
||||
]);
|
||||
$latestVersionParticipant = Tableversion::where('table', 'participants')->latest()->first();
|
||||
}
|
||||
|
||||
if ( $latestVersionVolunteer === null ) {
|
||||
Tableversion::create([
|
||||
'table' => 'volunteers',
|
||||
'version' => $versions['volunteers'] - 1,
|
||||
]);
|
||||
$latestVersionVolunteer = Tableversion::where('table', 'volunteers')->latest()->first();
|
||||
}
|
||||
|
||||
|
||||
if($latestVersionParticipant->version < $versions['participants'] || $latestVersionVolunteer->version < $versions['volunteers'] ) {
|
||||
$response = $client->request(
|
||||
'GET',
|
||||
config('app.apilan_url') . "data",
|
||||
[
|
||||
'headers'=> [
|
||||
'X-Api-Key' => config('app.apilan_key'),
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json'
|
||||
],
|
||||
//'cert' => config('app.apilan_clientcert_path')
|
||||
'cert' => Storage::disk('public')->path('lan.vbytes.se.pem')
|
||||
],
|
||||
);
|
||||
$response_data = json_decode((string) $response->getBody(), true);
|
||||
|
||||
foreach ($response_data['participants'] as $participant) {
|
||||
Customer::updateOrCreate(
|
||||
['lan_id' => $participant['lan_id']],
|
||||
[
|
||||
'lan_id' => $participant['lan_id'],
|
||||
'name' => $participant['first_name'] . " " . $participant['surname'],
|
||||
'guardian_name' => "Anna",
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($response_data['volunteers'] as $volunteer) {
|
||||
Customer::updateOrCreate(
|
||||
['lan_id' => $volunteer['lan_id']],
|
||||
[
|
||||
'lan_id' => $volunteer['lan_id'],
|
||||
'name' => $volunteer['first_name'] . " " . $volunteer['surname'],
|
||||
'guardian_name' => "Anna",
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if($latestVersionParticipant->version < $versions['participants']) {
|
||||
Tableversion::create([
|
||||
'table' => 'participants',
|
||||
'version' =>$latestVersionParticipant->version + 1,
|
||||
]);
|
||||
}
|
||||
|
||||
if($latestVersionVolunteer->version < $versions['volunteers']) {
|
||||
Tableversion::create([
|
||||
'table' => 'volunteers',
|
||||
'version' =>$latestVersionVolunteer->version + 1,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
})->everyMinute();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use Illuminate\Foundation\Application;
|
|||
use Illuminate\Support\Facades\Route;
|
||||
use Inertia\Inertia;
|
||||
use App\Http\Controllers\CustomerController;
|
||||
use App\Http\Controllers\CustomerGroupController;
|
||||
|
||||
Route::get('/', function () {
|
||||
return Inertia::render('Auth/Login');
|
||||
|
|
@ -12,6 +13,7 @@ Route::get('/', function () {
|
|||
|
||||
Route::get('/dashboard', [CustomerController::class, 'index'])->middleware(['auth', 'verified'])->name('dashboard');
|
||||
Route::get('/customer/{id}', [CustomerController::class, 'show'])->middleware(['auth', 'verified']);
|
||||
Route::get('/customer-groups', [CustomerGroupController::class, 'index'])->middleware(['auth', 'verified'])->name('customer-groups');
|
||||
|
||||
Route::get('/form', function () {
|
||||
return Inertia::render('Form');
|
||||
|
|
|
|||
Loading…
Reference in a new issue