Compare commits
58 commits
7140796ccd
...
210c91f3a8
Author | SHA1 | Date | |
---|---|---|---|
210c91f3a8 | |||
2ee7fca584 | |||
258bccf59b | |||
ca42526a62 | |||
f484bfff79 | |||
9384d09ff6 | |||
f460cdd6ce | |||
4b4a284914 | |||
a641247748 | |||
82a518fa1d | |||
deaa65d857 | |||
4af9e53a50 | |||
8d64d85b8b | |||
2c720faca7 | |||
85fa9f1e9b | |||
c8d1969352 | |||
1eb77be1d0 | |||
3949cf3400 | |||
973d099bf1 | |||
802d4d0c0b | |||
134ed0cd22 | |||
2bfcf59f3e | |||
4e197204a9 | |||
2075bcab0f | |||
c0d8392f6e | |||
ef9a296f5c | |||
bc55b4c34f | |||
e779111856 | |||
d6990f8c88 | |||
8eb385c67e | |||
2970982c77 | |||
9e63c83126 | |||
439f69a30c | |||
d0ce8e8e23 | |||
3b858f5b2b | |||
0512ea9ab2 | |||
8488d9d6c5 | |||
354045c5df | |||
ae1f8673e7 | |||
4f74bf38f9 | |||
8a2539f207 | |||
04673b1754 | |||
88af33d998 | |||
23af6ccd61 | |||
777f442118 | |||
7cae00e613 | |||
5a61ca46c5 | |||
e379825fd9 | |||
6b2da42160 | |||
48cf57a6d8 | |||
aa545ff82a | |||
b29d63ed4d | |||
1e91f443a7 | |||
6782b7f675 | |||
85b3f1dd0f | |||
a006fc15fa | |||
37fd0fb4d3 | |||
d794dbd2b0 |
55 changed files with 1254 additions and 926 deletions
|
@ -43,6 +43,14 @@ class GrupoDeCompra extends Model
|
|||
return $total;
|
||||
}
|
||||
|
||||
public function totalSinDevoluciones() {
|
||||
$total = 0;
|
||||
foreach ($this->pedidosAprobados() as $subpedido) {
|
||||
$total = $total + $subpedido->totalSinDevoluciones();
|
||||
}
|
||||
return $total;
|
||||
}
|
||||
|
||||
public function totalBarrial()
|
||||
{
|
||||
$total = 0;
|
||||
|
@ -108,7 +116,7 @@ class GrupoDeCompra extends Model
|
|||
|
||||
function pedidoParaPdf(): array
|
||||
{
|
||||
$productos = $this->productosPedidos(true, true, 'producto_id');
|
||||
$productos = $this->productosPedidos(true, 'producto_id');
|
||||
$pedido = [];
|
||||
$pedido['productos'] = [];
|
||||
|
||||
|
@ -258,13 +266,12 @@ class GrupoDeCompra extends Model
|
|||
return $result;
|
||||
}
|
||||
|
||||
public function productosPedidos($excluirBarriales = false, $excluirBonos = false, $orderBy = 'producto_nombre'): Collection
|
||||
public function productosPedidos($excluirBonos = false, $orderBy = 'producto_nombre'): Collection
|
||||
{
|
||||
$query = DB::table('pedidos_aprobados')
|
||||
->where('grupo_de_compra_id', $this->id);
|
||||
->where('grupo_de_compra_id', $this->id)
|
||||
->where('producto_nombre','NOT LIKE','%barrial%');
|
||||
|
||||
if ($excluirBarriales)
|
||||
$query = $query->where('producto_nombre','NOT LIKE','%barrial%');
|
||||
if ($excluirBonos)
|
||||
$query = $query->where('producto_es_bono',false);
|
||||
|
||||
|
|
|
@ -101,7 +101,6 @@ class CanastaHelper
|
|||
});
|
||||
|
||||
Producto::create([
|
||||
'fila' => 420,
|
||||
'nombre' => "Bono barrial",
|
||||
'precio' => 20,
|
||||
'categoria' => $categoria,
|
||||
|
|
|
@ -6,6 +6,7 @@ use App\GrupoDeCompra;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\GrupoDeCompraReducido;
|
||||
use App\Http\Resources\GrupoDeCompraResource;
|
||||
use http\Env\Request;
|
||||
|
||||
class GrupoDeCompraController extends Controller
|
||||
{
|
||||
|
@ -17,8 +18,18 @@ class GrupoDeCompraController extends Controller
|
|||
{
|
||||
return new GrupoDeCompraResource($grupoDeCompra);
|
||||
}
|
||||
public function reducido(GrupoDeCompra $grupoDeCompra)
|
||||
public function regiones()
|
||||
{
|
||||
return new GrupoDeCompraReducido($grupoDeCompra);
|
||||
return GrupoDeCompra::all()->pluck('region')->unique()->flatten();
|
||||
}
|
||||
|
||||
public function region(string $region)
|
||||
{
|
||||
return GrupoDeCompra::where('region', $region)->get();
|
||||
}
|
||||
|
||||
public function toggleDevoluciones(int $gdc) {
|
||||
GrupoDeCompra::find($gdc)->toggleDevoluciones();
|
||||
return response()->noContent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Filtros\FiltroDeProducto;
|
||||
use App\Http\Resources\ProductoResource;
|
||||
use App\Producto;
|
||||
|
@ -15,9 +15,8 @@ class ProductoController extends Controller
|
|||
return ProductoResource::collection(Producto::filtrar($filtros)->paginate(Producto::getPaginar($request)));
|
||||
}
|
||||
|
||||
public function show(Producto $producto)
|
||||
public function categorias()
|
||||
{
|
||||
return new ProductoResource($producto);
|
||||
return Producto::all()->pluck('categoria')->unique()->flatten();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,13 +3,16 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Subpedido;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class SessionController extends Controller
|
||||
{
|
||||
public function store(Request $request) {
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
$grupo_de_compra_id = Auth::user()->grupo_de_compra_id;
|
||||
$validated = $request->validate([
|
||||
'id' => 'required',
|
||||
|
@ -19,7 +22,14 @@ class SessionController extends Controller
|
|||
return response()->noContent();
|
||||
}
|
||||
|
||||
public function fetch() {
|
||||
return session('pedido_id');
|
||||
public function fetch(): JsonResponse
|
||||
{
|
||||
return response()->json(['id' => session('pedido_id')]);
|
||||
}
|
||||
|
||||
public function destroy(): Response
|
||||
{
|
||||
session()->forget('pedido_id');
|
||||
return response()->noContent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ class GrupoDeCompraResource extends JsonResource
|
|||
'devoluciones_habilitadas' => $this->devoluciones_habilitadas,
|
||||
'pedidos' => SubpedidoResource::collection($this->subpedidos),
|
||||
'total_a_recaudar' => number_format($this->totalARecaudar(),2),
|
||||
'total_sin_devoluciones' => number_format($this->totalSinDevoluciones(),2),
|
||||
'total_barrial' => number_format($this->totalBarrial(),2),
|
||||
'total_devoluciones' => number_format($this->totalDevoluciones(),2),
|
||||
'total_a_transferir' => number_format($this->totalATransferir(),2),
|
||||
|
|
|
@ -14,13 +14,18 @@ use Illuminate\Support\Facades\DB;
|
|||
|
||||
class Producto extends Model
|
||||
{
|
||||
protected $fillable = ["nombre", "precio", "categoria"];
|
||||
protected $fillable = ["nombre", "precio", "categoria", "bono", "es_solidario", "requiere_notas"];
|
||||
|
||||
public function subpedidos(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Subpedido::class, 'productos_subpedidos')->withPivot(["cantidad", "notas"]);
|
||||
}
|
||||
|
||||
public static function noBarriales()
|
||||
{
|
||||
return self::where('nombre', 'not like', '%barrial%');
|
||||
}
|
||||
|
||||
// Este método permite que se apliquen los filtros al hacer una request (por ejemplo, de búsqueda)
|
||||
public function scopeFiltrar($query, FiltroDeProducto $filtros): Builder
|
||||
{
|
||||
|
@ -34,17 +39,17 @@ class Producto extends Model
|
|||
|
||||
public static function productosFilaID()
|
||||
{
|
||||
return Producto::pluck('id', 'fila')->all();
|
||||
return self::noBarriales()->pluck('id', 'fila')->all();
|
||||
}
|
||||
|
||||
public static function productosIDFila()
|
||||
{
|
||||
return Producto::pluck('fila', 'id')->all();
|
||||
return self::noBarriales()->pluck('fila', 'id')->all();
|
||||
}
|
||||
|
||||
public static function productosIDNombre()
|
||||
{
|
||||
return Producto::pluck('nombre', 'id')->all();
|
||||
return self::noBarriales()->pluck('nombre', 'id')->all();
|
||||
}
|
||||
|
||||
static public function cantidadesPorBarrio(): Collection
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.4",
|
||||
"doctrine/dbal": "^2.2.0",
|
||||
"fideloper/proxy": "^4.4",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
"guzzlehttp/guzzle": "^6.3.1|^7.0.1",
|
||||
|
|
809
composer.lock
generated
809
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class HacerFilaNullable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->integer('fila')->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('productos', function (Blueprint $table) {
|
||||
$table->integer('fila')->nullable(false)->change();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class QuitarPasswordDeGrupoDeCompra extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->dropColumn('password');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('grupos_de_compra', function (Blueprint $table) {
|
||||
$table->string('password')->nullable();
|
||||
});
|
||||
}
|
||||
}
|
60
package-lock.json
generated
60
package-lock.json
generated
|
@ -13,12 +13,8 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"bootstrap": "^4.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"jquery": "^3.2",
|
||||
"laravel-mix": "^5.0.1",
|
||||
"lodash": "^4.17.19",
|
||||
"popper.js": "^1.12",
|
||||
"resolve-url-loader": "^2.3.1",
|
||||
"sass": "^1.20.1",
|
||||
"sass-loader": "^8.0.0",
|
||||
|
@ -3090,26 +3086,6 @@
|
|||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/bootstrap": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz",
|
||||
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/twbs"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bootstrap"
|
||||
}
|
||||
],
|
||||
"peerDependencies": {
|
||||
"jquery": "1.9.1 - 3",
|
||||
"popper.js": "^1.16.1"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
|
@ -7939,12 +7915,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/jquery": {
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
|
||||
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
@ -9605,17 +9575,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/popper.js": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
||||
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
|
||||
"deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/portfinder": {
|
||||
"version": "1.0.37",
|
||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz",
|
||||
|
@ -17156,13 +17115,6 @@
|
|||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
||||
"dev": true
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz",
|
||||
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
|
@ -20894,12 +20846,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
|
||||
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
@ -22234,12 +22180,6 @@
|
|||
"find-up": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"popper.js": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
|
||||
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"portfinder": {
|
||||
"version": "1.0.37",
|
||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.37.tgz",
|
||||
|
|
|
@ -11,12 +11,8 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"bootstrap": "^4.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"jquery": "^3.2",
|
||||
"laravel-mix": "^5.0.1",
|
||||
"lodash": "^4.17.19",
|
||||
"popper.js": "^1.12",
|
||||
"resolve-url-loader": "^2.3.1",
|
||||
"sass": "^1.20.1",
|
||||
"sass-loader": "^8.0.0",
|
||||
|
|
41
resources/js/bootstrap.js
vendored
41
resources/js/bootstrap.js
vendored
|
@ -1,41 +0,0 @@
|
|||
window._ = require('lodash');
|
||||
|
||||
/**
|
||||
* We'll load jQuery and the Bootstrap jQuery plugin which provides support
|
||||
* for JavaScript based Bootstrap features such as modals and tabs. This
|
||||
* code may be modified to fit the specific needs of your application.
|
||||
*/
|
||||
|
||||
try {
|
||||
window.Popper = require('popper.js').default;
|
||||
window.$ = window.jQuery = require('jquery');
|
||||
|
||||
require('bootstrap');
|
||||
} catch (e) {}
|
||||
|
||||
/**
|
||||
* We'll load the axios HTTP library which allows us to easily issue requests
|
||||
* to our Laravel back-end. This library automatically handles sending the
|
||||
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
||||
*/
|
||||
|
||||
window.axios = require('axios');
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
/**
|
||||
* Echo exposes an expressive API for subscribing to channels and listening
|
||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
||||
* allows your team to easily build robust real-time web applications.
|
||||
*/
|
||||
|
||||
// import Echo from 'laravel-echo';
|
||||
|
||||
// window.Pusher = require('pusher-js');
|
||||
|
||||
// window.Echo = new Echo({
|
||||
// broadcaster: 'pusher',
|
||||
// key: process.env.MIX_PUSHER_APP_KEY,
|
||||
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
|
||||
// forceTLS: true
|
||||
// });
|
|
@ -23,7 +23,6 @@ import CaracteristicasOpcionales from "./CaracteristicasOpcionales.vue";
|
|||
import TabsSecciones from "../comunes/TabsSecciones.vue";
|
||||
import DropdownDescargar from "./DropdownDescargar.vue";
|
||||
import TablaPedidos from "./TablaPedidos.vue";
|
||||
import TablaBonos from "./TablaBonos.vue";
|
||||
import { mapActions, mapGetters } from "vuex";
|
||||
export default {
|
||||
components: {
|
||||
|
@ -31,7 +30,6 @@ export default {
|
|||
TabsSecciones,
|
||||
DropdownDescargar,
|
||||
TablaPedidos,
|
||||
TablaBonos,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script>
|
||||
import axios from "axios";
|
||||
import {mapActions, mapGetters, mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
<td class="has-text-right" >
|
||||
{{ devoluciones_habilitadas ? pedido.total : pedido.total_sin_devoluciones }}
|
||||
</td>
|
||||
<td><switch-aprobacion :pedido_id="pedido_id"></switch-aprobacion></td>
|
||||
<td>
|
||||
<switch-aprobacion :pedido_id="pedido_id"/>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
<template>
|
||||
<div class="block">
|
||||
<div class="block" v-show="!hayBonos">
|
||||
<p class="has-text-centered">
|
||||
Todavía no hay bonos pedidos.
|
||||
</p>
|
||||
</div>
|
||||
<div class="block" v-show="hayBonos">
|
||||
<table class="table is-bordered is-striped is-hoverable is-fullwidth">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><abbr title="Núcleo">Núcleo</abbr></th>
|
||||
<td v-for="(bono,i) in bonos" :key="i" class="is-1">
|
||||
{{ bono.nombre }}
|
||||
</td>
|
||||
<th><abbr title="Total a Pagar">Total $</abbr></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(bp, i) in bonosPorPedido" :key="i">
|
||||
<td> {{ bp.nucleo }} </td>
|
||||
<td v-for="(bono,j) in bp.bonos" :key="j" class="has-text-right">
|
||||
{{ bono.cantidad }}
|
||||
</td>
|
||||
<td class="has-text-right"> {{ bp.total }} </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th :colspan="bonos.length">Total bonos</th>
|
||||
<th class="has-text-right">$ {{ totalBonos }}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
pedidos: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
bonos: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pedidosAprobados: function() {
|
||||
return this.pedidos.filter(p => p.aprobado)
|
||||
},
|
||||
hayBonos: function() {
|
||||
return this.pedidosAprobados.filter(p => p.subtotal_bonos != 0).length !== 0
|
||||
},
|
||||
bonosPorPedido: function() {
|
||||
let bonosPorPedido = this.pedidosAprobados.map(p => p = {"nucleo":p.nombre, "bonos":p.productos.filter(x => x.bono), "total":p.subtotal_bonos});
|
||||
bonosPorPedido.forEach(bp => {
|
||||
bp.bonos = bp.bonos.map(b => b = {"bono":b.nombre, "cantidad":b.pivot.cantidad, "total":b.pivot.total, "id":b.id})
|
||||
})
|
||||
return bonosPorPedido.map(bp => this.completarBonos(bp));
|
||||
},
|
||||
totalBonos: function() {
|
||||
let total = 0
|
||||
this.bonosPorPedido.map(bp => total += parseInt(bp.total))
|
||||
return total
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
completarBonos(bonosPedido) {
|
||||
this.bonos.map(b => {
|
||||
if (!bonosPedido.bonos.map(x => x.id).includes(b.id))
|
||||
bonosPedido.bonos.push({"bono":b.nombre, "cantidad":0, "total":0, "id":b.id})
|
||||
})
|
||||
bonosPedido.bonos = bonosPedido.bonos.sort((b1,b2) => b1.id - b2.id)
|
||||
return bonosPedido
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
axios.get("../api/productos", {
|
||||
params: {
|
||||
categoria:'TRANSPORTE, BONOS Y FINANCIAMIENTO SORORO',
|
||||
}
|
||||
}).then(response => {
|
||||
this.bonos = response.data.data;
|
||||
});
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
|
@ -24,7 +24,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<th>Total a recaudar:</th>
|
||||
<td class="has-text-right">$ {{ total_a_recaudar }}</td>
|
||||
<td class="has-text-right">$ {{ devoluciones_habilitadas ? total_a_recaudar : total_sin_devoluciones }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Total bonos barriales:</th>
|
||||
|
@ -62,6 +62,7 @@ export default {
|
|||
"devoluciones_habilitadas",
|
||||
"pedidos",
|
||||
"total_a_recaudar",
|
||||
"total_sin_devoluciones",
|
||||
"total_barrial",
|
||||
"total_devoluciones",
|
||||
"cantidad_transporte",
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<div class="block pb-6" id="pedidos-compras-seccion"
|
||||
:class="seccionActiva === 'pedidos-compras-seccion' ? 'is-active' : 'is-hidden'">
|
||||
<div class="block" id="pedidos-compras-tabla-y-dropdown">
|
||||
<compras-dropdown-descargar>
|
||||
</compras-dropdown-descargar>
|
||||
<dropdown-descargar>
|
||||
</dropdown-descargar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block pb-6" id="canasta-compras-seccion"
|
||||
|
@ -37,7 +37,7 @@
|
|||
</div>
|
||||
</article>
|
||||
<div class="buttons is-right">
|
||||
<compras-canasta-input></compras-canasta-input>
|
||||
<canasta-input></canasta-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
</span>
|
||||
<span class="file-label">Subir canasta</span>
|
||||
</span>
|
||||
<span class="file-name" v-if="archivo">
|
||||
<span class="file-name" v-if="cargando">
|
||||
{{ 'Cargando ' + archivo.nombre }}
|
||||
</span>
|
||||
</label>
|
||||
|
@ -24,6 +24,7 @@
|
|||
|
||||
<script>
|
||||
import axios from "axios";
|
||||
import { mapActions } from "vuex";
|
||||
|
||||
export default {
|
||||
name: "CanastaInput",
|
||||
|
@ -34,10 +35,11 @@ export default {
|
|||
};
|
||||
},
|
||||
methods: {
|
||||
...mapActions('ui',["toast"]),
|
||||
async archivoSubido(event) {
|
||||
const archivo = event.target.files[0];
|
||||
if (archivo && archivo.type === "text/csv") {
|
||||
this.archivo = {data: archivo, nombre: archivo.name};
|
||||
this.archivo = { data: archivo, nombre: archivo.name };
|
||||
const formData = new FormData();
|
||||
formData.append("data", this.archivo.data);
|
||||
|
||||
|
@ -48,15 +50,15 @@ export default {
|
|||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
});
|
||||
this.$root.$toast(response.data.message || "Canasta cargada exitosamente");
|
||||
this.toast({ mensaje: (response.data.message || "Canasta cargada exitosamente") });
|
||||
} catch (error) {
|
||||
this.$root.$toast(error.response?.data?.message || "Hubo errores.");
|
||||
this.toast({ mensaje: (error.response?.data?.message || "Hubo errores.") });
|
||||
} finally {
|
||||
this.cargando = false;
|
||||
this.archivo = null;
|
||||
}
|
||||
} else {
|
||||
this.$root.$toast("La canasta debe ser .CSV")
|
||||
this.toast("La canasta debe ser .CSV")
|
||||
this.archivo = null;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div v-if="region_elegida !== null" class="block">
|
||||
<div v-if="region_elegida" class="block">
|
||||
<div class="field">
|
||||
<label class="label" :class="adminUrl ? 'has-text-white' : ''">
|
||||
Seleccioná tu barrio o grupo de compra
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div v-if="grupo_de_compra_elegido !== null" class="block">
|
||||
<div v-if="grupo_de_compra_elegido" class="block">
|
||||
<div class="field">
|
||||
<label class="label"
|
||||
:class="adminUrl ? 'has-text-white' : ''">{{ mensajes.mensaje }}</label>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</a>
|
||||
<div class="navbar-item" id="datos-pedido" v-if="pedidoDefinido">
|
||||
<p class="hide-below-1024">
|
||||
{{ `Núcleo: ${nombre} - Barrio: ${grupo_de_compra}` }}
|
||||
{{ `Núcleo: ${nombre} - Barrio: ${grupo_de_compra.nombre}` }}
|
||||
</p>
|
||||
</div>
|
||||
<chismosa-dropdown
|
||||
|
@ -42,7 +42,6 @@
|
|||
class="text-a">
|
||||
Cerrar sesión
|
||||
</a>
|
||||
<slot name="logout-form"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -63,12 +62,12 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
...mapGetters('pedido', ["pedidoDefinido"]),
|
||||
...mapState('pedido',["nombre"]),
|
||||
...mapState('barrio',["grupo_de_compra"]),
|
||||
...mapState('pedido', ["nombre"]),
|
||||
...mapState('pedido', ["grupo_de_compra"]),
|
||||
},
|
||||
methods: {
|
||||
...mapActions('productos', ["filtrarProductos"]),
|
||||
...mapMutations('ui',["addMiga"]),
|
||||
...mapMutations('ui', ["addMiga", "popUltimaBusqueda"]),
|
||||
toggleBurger() {
|
||||
this.burgerActiva = !this.burgerActiva
|
||||
},
|
||||
|
@ -76,6 +75,7 @@ export default {
|
|||
if (this.burgerActiva)
|
||||
this.toggleBurger();
|
||||
this.filtrarProductos({ filtro: "nombre", valor: this.searchString });
|
||||
this.popUltimaBusqueda();
|
||||
this.addMiga({ nombre: this.searchString });
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div class="control">
|
||||
<div class="select">
|
||||
<select @change="selectRegion({ region })" v-model="region">
|
||||
<option :disabled="region_elegida !== null" value=null>
|
||||
<option :disabled="region_elegida" value=null>
|
||||
Seleccionar
|
||||
</option>
|
||||
<option v-for="(region, index) in regiones"
|
||||
|
@ -25,6 +25,7 @@
|
|||
<script>
|
||||
import {mapActions, mapGetters, mapState} from "vuex";
|
||||
export default {
|
||||
name: 'RegionSelect',
|
||||
async mounted() {
|
||||
await this.getRegiones();
|
||||
},
|
||||
|
|
27
resources/js/components/login/Titulos.vue
Normal file
27
resources/js/components/login/Titulos.vue
Normal file
|
@ -0,0 +1,27 @@
|
|||
<script>
|
||||
import { mapGetters } from "vuex";
|
||||
|
||||
export default {
|
||||
name:'LoginTitulos',
|
||||
computed: {
|
||||
...mapGetters('login',["titulos", "urlRol"]),
|
||||
whiteText() {
|
||||
console.log(this.urlRol);
|
||||
return this.urlRol === 'admin';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="block">
|
||||
<h1 class="title" :class="{'has-text-white': whiteText}">{{ titulos.titulo }}</h1>
|
||||
<p class="subtitle" :class="{'has-text-white': whiteText}">
|
||||
{{ `Bienvenidx a la ${titulos.subtitlo} del ` }}<strong :class="{'has-text-white': whiteText}">Mercado Popular de Subistencia</strong>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -1,29 +1,40 @@
|
|||
<template>
|
||||
<div id="pedidos-body">
|
||||
<cartel-pedido-aprobado></cartel-pedido-aprobado>
|
||||
<pedido-select-section v-if="!pedidoDefinido"></pedido-select-section>
|
||||
<pedido v-else></pedido>
|
||||
<pedido-select v-if="!pedidoDefinido"/>
|
||||
<div v-else>
|
||||
<nav-migas/>
|
||||
<div class="columns">
|
||||
<div class="column" :class="{ 'is-two-thirds-desktop is-hidden-touch': show_chismosa }">
|
||||
<cartel-pedido-aprobado/>
|
||||
<canasta/>
|
||||
</div>
|
||||
<div class="column is-full-touch" v-if="show_chismosa">
|
||||
<chismosa/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from "vuex";
|
||||
import PedidoSelectSection from "./PedidoSelectSection.vue";
|
||||
import Pedido from "./Pedido.vue";
|
||||
import { mapActions, mapGetters, mapState } from "vuex";
|
||||
import CartelPedidoAprobado from "./CartelPedidoAprobado.vue";
|
||||
import PedidoSelect from "./PedidoSelect.vue";
|
||||
import Canasta from "./Canasta.vue";
|
||||
import NavMigas from "./NavMigas.vue";
|
||||
import Chismosa from "./Chismosa.vue";
|
||||
|
||||
export default {
|
||||
components: { CartelPedidoAprobado, Pedido, Productos: Pedido, PedidoSelectSection },
|
||||
components: { Chismosa, NavMigas, CartelPedidoAprobado, PedidoSelect, Canasta },
|
||||
computed: {
|
||||
...mapGetters('pedido',["pedidoDefinido"]),
|
||||
...mapGetters('pedido', ["pedidoDefinido"]),
|
||||
...mapState('ui', ["show_chismosa"]),
|
||||
},
|
||||
methods: {
|
||||
...mapActions('productos',["init"]),
|
||||
...mapActions('pedido',["getSesion"]),
|
||||
...mapActions('productos', ["init"]),
|
||||
},
|
||||
async mounted() {
|
||||
await this.init();
|
||||
await this.getSesion();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
<script >
|
||||
import { defineComponent } from "vue";
|
||||
import { mapActions, mapState } from "vuex";
|
||||
import SubpedidoSelect from "./SubpedidoSelect.vue";
|
||||
import { mapState } from "vuex";
|
||||
import CategoriasContainer from "./CategoriasContainer.vue";
|
||||
import ProductosContainer from "./ProductosContainer.vue";
|
||||
import Chismosa from "./Chismosa.vue";
|
||||
import DevolucionesModal from "./DevolucionesModal.vue";
|
||||
import CartelPedidoAprobado from "./CartelPedidoAprobado.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: { CartelPedidoAprobado, DevolucionesModal, SubpedidoSelect, CategoriasContainer, ProductosContainer, Chismosa },
|
||||
components: { DevolucionesModal, CategoriasContainer, ProductosContainer, Chismosa },
|
||||
computed: {
|
||||
...mapState('ui',["show_chismosa","show_devoluciones"])
|
||||
},
|
||||
...mapState('ui', ["show_chismosa", "show_devoluciones"])
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
@ -20,7 +18,6 @@ export default defineComponent({
|
|||
<div class="columns ml-3 mr-3" v-else>
|
||||
<categorias-container :class="show_chismosa ? 'hide-below-1024' : ''"></categorias-container>
|
||||
<productos-container :class="show_chismosa ? 'hide-below-1024' : ''"></productos-container>
|
||||
<chismosa v-show="show_chismosa"></chismosa>
|
||||
<devoluciones-modal v-show="show_devoluciones"></devoluciones-modal>
|
||||
</div>
|
||||
</template>
|
|
@ -1,39 +1,92 @@
|
|||
<template>
|
||||
<div v-show="visible" class="column">
|
||||
<div class="columns is-multiline is-mobile">
|
||||
<div ref="categorias"
|
||||
class="columns is-multiline is-mobile"
|
||||
:class="{ 'align-last-left': isLastRowIncomplete }">
|
||||
<div v-for="(categoria,i) in categorias" :key="i"
|
||||
class="block column is-one-quarter-desktop is-one-third-tablet is-half-mobile">
|
||||
<div @click.capture="seleccionar(categoria)" class="card" style="height:100%">
|
||||
:class="{ 'is-3-desktop is-2-fullhd': !show_chismosa }"
|
||||
class="column is-4-tablet is-6-mobile hover-dedito">
|
||||
<div @click.capture="seleccionar(categoria)" class="card" style="height: 100%">
|
||||
<div class="card-content">
|
||||
<div class="media">
|
||||
<div class="media-content" style="overflow:hidden">
|
||||
<p class="title is-6" v-text="categoria"></p>
|
||||
<div class="media-content" style="overflow: hidden">
|
||||
<p class="title is-size-7-mobile is-size-6-tablet has-text-centered" v-text="categoria"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- END CARD -->
|
||||
</div><!-- END BLOCK COLUMN -->
|
||||
</div><!-- END COLUMNS -->
|
||||
</div><!-- END CONTAINER -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { mapActions, mapMutations, mapState } from "vuex";
|
||||
export default {
|
||||
name: 'CategoriasContainer',
|
||||
computed: {
|
||||
...mapState('productos',["categorias", "filtro"]),
|
||||
...mapState('productos', ["categorias", "filtro"]),
|
||||
...mapState('ui', ["show_chismosa"]),
|
||||
visible() {
|
||||
return this.filtro === null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('productos',["seleccionarCategoria"]),
|
||||
...mapMutations('ui',["addMiga"]),
|
||||
...mapActions('productos', ["seleccionarCategoria"]),
|
||||
...mapMutations('ui', ["addMiga"]),
|
||||
seleccionar(categoria) {
|
||||
this.seleccionarCategoria({ categoria: categoria });
|
||||
this.addMiga({ nombre: categoria });
|
||||
this.addMiga({ nombre: categoria, action: "productos/seleccionarCategoria", arguments: { categoria: categoria }});
|
||||
},
|
||||
checkIfLastRowIncomplete() {
|
||||
this.$nextTick(() => {
|
||||
const wrapper = this.$refs.categorias;
|
||||
if (!wrapper) return;
|
||||
|
||||
const columns = wrapper.querySelectorAll('.column');
|
||||
if (columns.length === 0) {
|
||||
this.isLastRowIncomplete = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const firstRowTop = columns[0].offsetTop;
|
||||
let firstRowCount = 0;
|
||||
columns.forEach(col => {
|
||||
if (col.offsetTop === firstRowTop) firstRowCount++;
|
||||
});
|
||||
this.isLastRowIncomplete = this.categorias.length % firstRowCount !== 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLastRowIncomplete: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.checkIfLastRowIncomplete();
|
||||
window.addEventListener('resize', this.checkIfLastRowIncomplete);
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.checkIfLastRowIncomplete);
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.hover-dedito {
|
||||
cursor: pointer;
|
||||
}
|
||||
.columns.align-last-left {
|
||||
justify-content: flex-start !important;
|
||||
}
|
||||
.columns.align-last-left > .column:last-child:nth-child(3n),
|
||||
.columns.align-last-left > .column:last-child:nth-child(2n),
|
||||
.columns.align-last-left > .column:last-child {
|
||||
margin-right: auto;
|
||||
}
|
||||
.title {
|
||||
word-break: keep-all;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,46 +1,44 @@
|
|||
<template>
|
||||
<div class="column is-one-third">
|
||||
<div class="fixed-right">
|
||||
<table v-show="mostrar_tabla" class="table is-striped is-bordered tabla-chismosa is-narrow">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Producto</th>
|
||||
<th>Cantidad</th>
|
||||
<th><abbr title="Precio Total">$</abbr></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th><abbr title="Bonos de Transporte">B. Transporte</abbr></th>
|
||||
<th class="has-text-right">{{ cantidad_transporte }}</th>
|
||||
<th class="has-text-right">{{ total_transporte }}</th>
|
||||
</tr>
|
||||
<tr v-if="devoluciones_habilitadas">
|
||||
<th><p>Devoluciones</p></th>
|
||||
<td>
|
||||
<abbr :title="devoluciones_notas">{{ notas_abreviadas }}</abbr>
|
||||
<button @click.capture="toggleDevoluciones()" class="button is-warning is-small">
|
||||
<span class="icon">
|
||||
<i class="fas fa-edit"></i>
|
||||
</span>
|
||||
</button>
|
||||
</td>
|
||||
<th class="has-text-right">-{{ devoluciones_total }}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Total total</th>
|
||||
<th></th>
|
||||
<th class="has-text-right">{{ total }}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<producto-row v-for="producto in productos" :producto="producto" :key="producto.id"></producto-row>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="has-text-centered" v-show="!mostrar_tabla">
|
||||
Compa, todavía no agregaste nada a la chismosa.
|
||||
</p>
|
||||
</div>
|
||||
<div class="fixed-right mr-3 ml-3">
|
||||
<table v-show="mostrar_tabla" class="table is-striped is-bordered tabla-chismosa is-narrow">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Producto</th>
|
||||
<th>Cantidad</th>
|
||||
<th><abbr title="Precio Total">$</abbr></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th><abbr title="Bonos de Transporte">B. Transporte</abbr></th>
|
||||
<th class="has-text-right">{{ cantidad_transporte }}</th>
|
||||
<th class="has-text-right">{{ total_transporte }}</th>
|
||||
</tr>
|
||||
<tr v-if="grupo_de_compra.devoluciones_habilitadas">
|
||||
<th><p>Devoluciones</p></th>
|
||||
<td>
|
||||
<abbr :title="devoluciones_notas">{{ notas_abreviadas }}</abbr>
|
||||
<button @click.capture="toggleDevoluciones()" class="button is-warning is-small">
|
||||
<span class="icon">
|
||||
<i class="fas fa-edit"></i>
|
||||
</span>
|
||||
</button>
|
||||
</td>
|
||||
<th class="has-text-right">-{{ devoluciones_total }}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Total total</th>
|
||||
<th></th>
|
||||
<th class="has-text-right">{{ total }}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<producto-row v-for="producto in productos" :producto="producto" :key="producto.id"></producto-row>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="has-text-centered" v-show="!mostrar_tabla">
|
||||
Compa, todavía no agregaste nada a la chismosa.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -51,8 +49,8 @@ import { mapMutations, mapState } from "vuex";
|
|||
export default {
|
||||
components: { ProductoRow },
|
||||
computed: {
|
||||
...mapState('barrio',["devoluciones_habilitadas"]),
|
||||
...mapState('pedido',[
|
||||
"grupo_de_compra",
|
||||
"productos",
|
||||
"total",
|
||||
"total_transporte",
|
||||
|
@ -82,6 +80,5 @@ export default {
|
|||
position: fixed;
|
||||
overflow-y: auto;
|
||||
max-height: 81vh;
|
||||
margin-right: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<nav v-if="pedidoDefinido" class="breadcrumb is-centered has-background-danger-light is-fixed-top"
|
||||
<nav class="breadcrumb is-centered has-background-danger-light is-fixed-top"
|
||||
aria-label="breadcrumbs" v-show="visible">
|
||||
<ul class="mt-4">
|
||||
<li v-for="(miga, i) in migas" :key="i" :class="{'is-active': i === migaActiva}">
|
||||
|
@ -11,22 +11,25 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters, mapState } from "vuex";
|
||||
import { mapActions, mapMutations, mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
...mapActions('productos',["getProductos"]),
|
||||
...mapActions('ui',["clickMiga"]),
|
||||
...mapActions('productos', ["getProductos"]),
|
||||
...mapActions('ui', ["clickMiga"]),
|
||||
...mapMutations('ui', ["addMiga"]),
|
||||
},
|
||||
computed: {
|
||||
...mapState('ui',["migas"]),
|
||||
...mapGetters('pedido',["pedidoDefinido"]),
|
||||
...mapState('ui', ["migas"]),
|
||||
visible() {
|
||||
return this.migas.length > 0
|
||||
return this.migas.length > 0;
|
||||
},
|
||||
migaActiva() {
|
||||
return this.migas.length - 1
|
||||
}
|
||||
return this.migas.length - 1;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.addMiga({ nombre: 'Categorias', action: 'productos/getProductos' });
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
114
resources/js/components/pedidos/PedidoSelect.vue
Normal file
114
resources/js/components/pedidos/PedidoSelect.vue
Normal file
|
@ -0,0 +1,114 @@
|
|||
<template>
|
||||
<section class="section">
|
||||
<div id="root" class="container">
|
||||
<h1 class="title">
|
||||
Pedidos MPS
|
||||
</h1>
|
||||
<p class="subtitle">
|
||||
Bienvenidx a la aplicación de pedidos del <strong>Mercado Popular de Subsistencia</strong>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<label class="label">Escribí el nombre de tu familia o grupo de convivencia</label>
|
||||
<div class="columns">
|
||||
<div class="column is-two-thirds">
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input class="input" @input="onType" v-model="searchString"/>
|
||||
</div>
|
||||
<p class="help">Debe ser claro para que tus compas del barrio te identifiquen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-one-third buttons">
|
||||
<button class="button is-danger" v-if="!deshabilitado" @click="submit(undefined)">
|
||||
Crear nuevo pedido
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="pedidos.length" class="block">
|
||||
<label class="label">
|
||||
Si ya comenzaste a hacer tu pedido este mes, elegilo en esta lista:
|
||||
</label>
|
||||
<p class="help">
|
||||
Podés seguir escribiendo en el campo de arriba para refinar la búsqueda.
|
||||
</p>
|
||||
<div class="columns is-mobile"
|
||||
v-for="(subpedidoExistente, index) in pedidos"
|
||||
:class="{'has-background-grey-lighter': index % 2}"
|
||||
:key="index">
|
||||
<div class="column is-half-mobile is-two-thirds-desktop is-two-thirds-tablet">
|
||||
<p class="nombre">
|
||||
{{ subpedidoExistente.nombre }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="buttons column is-half-mobile is-one-third-desktop is-one-third-tablet">
|
||||
<button class="button is-danger" @click="submit(subpedidoExistente)">
|
||||
Continuar pedido
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template><script>
|
||||
import { mapActions, mapMutations, mapState } from "vuex";
|
||||
import axios from "axios";
|
||||
|
||||
export default {
|
||||
name: 'PedidoSelect',
|
||||
async mounted() {
|
||||
await this.getGrupoDeCompra();
|
||||
const sesion = await axios.get("/pedido/sesion");
|
||||
if (sesion.data.id) {
|
||||
await this.elegirPedido({ pedido_id: sesion.data.id });
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pedidos: [],
|
||||
searchString: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('pedido', ["grupo_de_compra"]),
|
||||
deshabilitado: function () {
|
||||
return !this.searchString?.trim()
|
||||
|| this.pedidos.some(p => p.nombre.toLowerCase() === this.searchString.toLowerCase())
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('pedido', ["getGrupoDeCompra", "crearPedido", "elegirPedido"]),
|
||||
async getPedidos(nombre) {
|
||||
const response = await axios.get('/api/subpedidos/',{
|
||||
params: {
|
||||
nombre: nombre,
|
||||
grupo_de_compra: this.grupo_de_compra.id
|
||||
}
|
||||
});
|
||||
this.pedidos = response.data;
|
||||
},
|
||||
onType() {
|
||||
if (!this.searchString) {
|
||||
this.setPedidos([]);
|
||||
return;
|
||||
}
|
||||
this.getPedidos(this.searchString);
|
||||
},
|
||||
async submit(pedido) {
|
||||
if (pedido)
|
||||
await this.elegirPedido({ pedido_id: pedido.id });
|
||||
else
|
||||
await this.crearPedido({ nombre: this.searchString, grupo_de_compra_id: this.grupo_de_compra.id });
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.nombre {
|
||||
padding-top: calc(.5em - 1px);
|
||||
margin-bottom: .5rem
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import SubpedidoSelect from "./SubpedidoSelect.vue";
|
||||
import { mapGetters } from "vuex";
|
||||
|
||||
export default defineComponent({
|
||||
components: { SubpedidoSelect },
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="section">
|
||||
<div id="root" class="container">
|
||||
<h1 class="title">
|
||||
Pedidos MPS
|
||||
</h1>
|
||||
<p class="subtitle">
|
||||
Bienvenidx a la aplicación de pedidos del <strong>Mercado Popular de Subsistencia</strong>
|
||||
</p>
|
||||
<subpedido-select></subpedido-select>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -1,32 +1,37 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="field has-addons contador">
|
||||
<div class="is-justify-content-center">
|
||||
<div class="field has-addons is-justify-content-center contador">
|
||||
<div class="control">
|
||||
<button class="button is-small" @click.capture="decrementar();">
|
||||
<button class="button is-small" :disabled="cantidadControl < 1" v-if="!aprobado" @click.capture="decrementar();">
|
||||
<i class="fa fa-solid fa-minus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<input id="cantidad" v-model="cantidadControl" class="input is-small" type="number"
|
||||
style="text-align: center">
|
||||
<input id="cantidad"
|
||||
v-model="cantidadControl"
|
||||
class="input is-small"
|
||||
type="number"
|
||||
style="text-align: center"
|
||||
:readonly="aprobado">
|
||||
</div>
|
||||
<div class="control" @click="incrementar();">
|
||||
<button class="button is-small">
|
||||
<div class="control">
|
||||
<button class="button is-small" v-if="!aprobado" @click="incrementar();">
|
||||
<i class="fa fa-solid fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button :disabled="!hayCambios" class="button is-small is-success ml-1" @click="confirmar()">
|
||||
<button :disabled="!hayCambios || cantidadControl < 0" v-if="!aprobado" class="button is-small is-success ml-1" @click="confirmar()">
|
||||
<span class="icon">
|
||||
<i class="fas fa-check"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button :disabled="!puedeBorrar" class="button is-small is-danger ml-1" @click="borrar()">
|
||||
<button :disabled="!puedeBorrar" v-if="!aprobado" class="button is-small is-danger ml-1" @click="borrar()">
|
||||
<span class="icon">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="requiere_notas" :class="{'has-icons-right': notas_warning_visible}"
|
||||
<div v-if="!aprobado && requiere_notas"
|
||||
:class="{'has-icons-right': notas_warning_visible}"
|
||||
class="control is-full-width has-icons-left">
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-sticky-note"></i>
|
||||
|
@ -45,7 +50,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters } from "vuex";
|
||||
import { mapActions, mapGetters, mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -77,6 +82,7 @@ export default {
|
|||
this.actualizar();
|
||||
},
|
||||
computed: {
|
||||
...mapState('pedido', ["aprobado"]),
|
||||
...mapGetters('pedido', ["enChismosa", "cantidad", "notas"]),
|
||||
cantidadEnChismosa() {
|
||||
return this.cantidad(this.producto_id);
|
||||
|
@ -88,7 +94,7 @@ export default {
|
|||
return this.cantidadControl !== this.cantidadEnChismosa || this.notasControl !== this.notasEnChismosa;
|
||||
},
|
||||
puedeBorrar() {
|
||||
return this.enChismosa(this.producto_id);
|
||||
return this.enChismosa(this.producto_id) && !this.aprobado;
|
||||
},
|
||||
faltaNotas() {
|
||||
return this.requiere_notas && this.cantidadControl > 0 && !this.notasControl;
|
||||
|
@ -140,7 +146,7 @@ input[type=number] {
|
|||
}
|
||||
|
||||
.contador {
|
||||
min-width: 178px;
|
||||
min-width: 1.5rem;
|
||||
}
|
||||
|
||||
.is-danger {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import ProductoCantidad from "./ProductoCantidad.vue";
|
||||
import { mapGetters } from "vuex";
|
||||
import { mapGetters, mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
name: "ProductoCard",
|
||||
|
@ -12,49 +12,57 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('pedido',["enChismosa", "cantidad"]),
|
||||
...mapState('ui', ["show_chismosa"]),
|
||||
...mapState('pedido', ["aprobado"]),
|
||||
...mapGetters('pedido', ["enChismosa", "cantidad"]),
|
||||
fuePedido() {
|
||||
return this.enChismosa(this.producto.id);
|
||||
},
|
||||
cantidadEnChismosa() {
|
||||
return this.cantidad(this.producto.id);
|
||||
},
|
||||
conIconos() {
|
||||
return this.producto.economia_solidaria || this.producto.nacional;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="block column is-one-quarter-desktop is-full-mobile is-half-tablet min-width-from-desktop">
|
||||
<div class="box" style="height:100%">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<p class="title is-6">
|
||||
{{ producto.nombre }}
|
||||
</p>
|
||||
<span class="subtitle is-7 hidden-from-tablet" v-if="fuePedido">{{ cantidadEnChismosa }}</span>
|
||||
</div>
|
||||
<div class="column is-one-quarter has-text-right">
|
||||
<p class="has-text-weight-bold has-text-primary">
|
||||
<span class="is-left-mobile">
|
||||
<img v-show="producto.economia_solidaria" height="30px" width="30px" src="/assets/solidaria.png" alt="proveedor de economía solidaria">
|
||||
<img v-show="producto.nacional" height="30px" width="30px" src="/assets/uruguay.png" alt="proveedor nacional"/>
|
||||
</span>
|
||||
$<span v-text="producto.precio"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="box" style="height:100%">
|
||||
<div class="columns is-mobile">
|
||||
<div class="column">
|
||||
<p class="title is-6">
|
||||
{{ producto.nombre }}
|
||||
</p>
|
||||
</div>
|
||||
<footer class="columns">
|
||||
<div class="column is-three-quarters">
|
||||
<div class="column is-one-quarter has-text-right">
|
||||
<p class="has-text-weight-bold has-text-primary block">
|
||||
${{ producto.precio }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="columns is-justify-content-left is-mobile">
|
||||
<div v-if="conIconos" class="column has-text-left">
|
||||
<span>
|
||||
<img v-show="producto.economia_solidaria" height="30px" width="30px" src="/assets/solidaria.png" alt="proveedor de economía solidaria">
|
||||
<img v-show="producto.nacional" height="30px" width="30px" src="/assets/uruguay.png" alt="proveedor nacional"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="column"
|
||||
:class="conIconos ? 'is-three-quarters-mobile is-two-thirds-tablet' : 'is-full'">
|
||||
<producto-cantidad
|
||||
v-if="!aprobado"
|
||||
:producto_id="producto.id"
|
||||
:requiere_notas="producto.requiere_notas">
|
||||
</producto-cantidad>
|
||||
<div class="has-text-centered mt-2" v-if="fuePedido && aprobado">
|
||||
<p class="subtitle is-7">{{ cantidadEnChismosa }} en chismosa</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<p class="subtitle is-7 is-hidden-mobile" v-if="fuePedido">{{ cantidadEnChismosa }} en chismosa</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<tr>
|
||||
<td>{{ this.producto.nombre }}</td>
|
||||
<td class="has-text-right">
|
||||
<producto-cantidad
|
||||
:producto_id="producto.id"
|
||||
:requiere_notas="producto.requiere_notas">
|
||||
</producto-cantidad>
|
||||
</td>
|
||||
<td class="has-text-right">{{ cantidad(producto.id) }}</td>
|
||||
<td>{{ this.producto.nombre }}</td>
|
||||
<td class="has-text-right">
|
||||
<producto-cantidad
|
||||
:producto_id="producto.id"
|
||||
:requiere_notas="producto.requiere_notas">
|
||||
</producto-cantidad>
|
||||
</td>
|
||||
<td class="has-text-right">{{ cantidad(producto.id) }}</td>
|
||||
</tr>
|
||||
</template>
|
||||
<script>
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
<template>
|
||||
<div v-show="visible" class="column">
|
||||
<div class="columns is-multiline is-mobile">
|
||||
<producto-card
|
||||
v-for="(producto,i) in this.productos"
|
||||
:key="i"
|
||||
:producto="producto">
|
||||
</producto-card>
|
||||
<div ref="productos"
|
||||
class="columns is-multiline is-mobile"
|
||||
:class="{ 'align-last-left': isLastRowIncomplete }">
|
||||
<div v-for="(producto,i) in this.productos"
|
||||
class="block column is-full-mobile is-half-tablet is-one-quarter-fullhd"
|
||||
:class="show_chismosa ? 'is-half-desktop' : 'is-one-third-desktop'">
|
||||
<producto-card :key="i"
|
||||
:producto="producto">
|
||||
</producto-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -18,6 +22,7 @@ export default {
|
|||
components: { ProductoCard },
|
||||
computed: {
|
||||
...mapState('productos', ["productos", "filtro"]),
|
||||
...mapState('ui', ["show_chismosa"]),
|
||||
visible() {
|
||||
return this.filtro !== null;
|
||||
},
|
||||
|
@ -28,5 +33,49 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkIfLastRowIncomplete() {
|
||||
this.$nextTick(() => {
|
||||
const wrapper = this.$refs.productos;
|
||||
if (!wrapper) return;
|
||||
|
||||
const columns = wrapper.querySelectorAll('.column');
|
||||
if (columns.length === 0) {
|
||||
this.isLastRowIncomplete = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const firstRowTop = columns[0].offsetTop;
|
||||
let firstRowCount = 0;
|
||||
columns.forEach(col => {
|
||||
if (col.offsetTop === firstRowTop) firstRowCount++;
|
||||
});
|
||||
this.isLastRowIncomplete = this.productos.length % firstRowCount !== 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLastRowIncomplete: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.checkIfLastRowIncomplete();
|
||||
window.addEventListener('resize', this.checkIfLastRowIncomplete);
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.checkIfLastRowIncomplete);
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.columns.align-last-left {
|
||||
justify-content: flex-start !important;
|
||||
}
|
||||
.columns.align-last-left > .column:last-child:nth-child(3n),
|
||||
.columns.align-last-left > .column:last-child:nth-child(2n),
|
||||
.columns.align-last-left > .column:last-child {
|
||||
margin-right: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<label class="label">Escribí el nombre de tu familia o grupo de convivencia</label>
|
||||
<div class="columns">
|
||||
<div class="column is-two-thirds">
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input class="input" @input="onType" v-model="searchString"/>
|
||||
</div>
|
||||
<p class="help">Debe ser claro para que tus compas del barrio te identifiquen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-one-third buttons">
|
||||
<button class="button is-danger" v-if="!deshabilitado" @click="submit">Crear nuevo pedido
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="pedidos.length" class="block">
|
||||
<label class="label">Si ya comenzaste a hacer tu pedido este mes, elegilo en esta lista:</label>
|
||||
<p class="help">Podés seguir escribiendo en el campo de arriba para refinar la búsqueda.</p>
|
||||
<div class="columns is-mobile" v-for="(subpedidoExistente, index) in pedidos"
|
||||
:class="{'has-background-grey-lighter': index % 2}" :key="index">
|
||||
<div class="column is-half-mobile is-two-thirds-desktop is-two-thirds-tablet">
|
||||
<p style="padding-top: calc(.5em - 1px); margin-bottom: .5rem"
|
||||
v-text="subpedidoExistente.nombre"></p>
|
||||
</div>
|
||||
<div class="buttons column is-half-mobile is-one-third-desktop is-one-third-tablet">
|
||||
<button class="button is-danger" @click="elegirPedido({ pedido: subpedidoExistente })">Continuar pedido
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapMutations, mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
name: 'SubpedidoSelect',
|
||||
async mounted() {
|
||||
await this.getGrupoDeCompra();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchString: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('barrio',["grupo_de_compra_id","pedidos"]),
|
||||
...mapState('pedido',["nombre","pedido_id"]),
|
||||
deshabilitado: function () {
|
||||
return !this.searchString?.trim()
|
||||
|| this.pedidos.some(p => p.nombre.toLowerCase() === this.searchString.toLowerCase())
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('barrio',["getGrupoDeCompra","getPedidos"]),
|
||||
...mapActions('pedido',["crearPedido","elegirPedido"]),
|
||||
...mapMutations('barrio',["setPedidos"]),
|
||||
onType() {
|
||||
if (!this.searchString) {
|
||||
this.setPedidos([]);
|
||||
return;
|
||||
}
|
||||
this.getPedidos(this.searchString);
|
||||
},
|
||||
async submit() {
|
||||
await this.crearPedido({ nombre: this.searchString, grupo_de_compra_id: this.grupo_de_compra_id });
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
2
resources/js/store/index.js
vendored
2
resources/js/store/index.js
vendored
|
@ -3,7 +3,6 @@ import Vuex from 'vuex';
|
|||
import admin from "./modules/admin";
|
||||
import login from "./modules/login";
|
||||
import pedido from "./modules/pedido";
|
||||
import barrio from "./modules/barrio";
|
||||
import productos from "./modules/productos";
|
||||
import ui from "./modules/ui";
|
||||
|
||||
|
@ -14,7 +13,6 @@ export default new Vuex.Store({
|
|||
admin,
|
||||
login,
|
||||
pedido,
|
||||
barrio,
|
||||
productos,
|
||||
ui,
|
||||
},
|
||||
|
|
8
resources/js/store/modules/admin.js
vendored
8
resources/js/store/modules/admin.js
vendored
|
@ -7,6 +7,7 @@ const state = {
|
|||
devoluciones_habilitadas: null,
|
||||
pedidos: null,
|
||||
total_a_recaudar: null,
|
||||
total_sin_devoluciones: null,
|
||||
total_barrial: null,
|
||||
total_devoluciones: null,
|
||||
total_a_transferir: null,
|
||||
|
@ -22,6 +23,7 @@ const mutations = {
|
|||
state.devoluciones_habilitadas = grupo_de_compra.devoluciones_habilitadas;
|
||||
state.pedidos = grupo_de_compra.pedidos;
|
||||
state.total_a_recaudar = grupo_de_compra.total_a_recaudar;
|
||||
state.total_sin_devoluciones = grupo_de_compra.total_sin_devoluciones;
|
||||
state.total_barrial = grupo_de_compra.total_barrial;
|
||||
state.total_devoluciones = grupo_de_compra.total_devoluciones;
|
||||
state.total_a_transferir = grupo_de_compra.total_a_transferir;
|
||||
|
@ -56,16 +58,16 @@ const getters = {
|
|||
return state.lastFetch !== null;
|
||||
},
|
||||
hayPedidos() {
|
||||
return getters.grupoDeCompraDefinido() && state.pedidos.length > 0;
|
||||
return state.pedidos?.length > 0;
|
||||
},
|
||||
pedidosAprobados() {
|
||||
return getters.grupoDeCompraDefinido() ? state.pedidos.filter(p => p.aprobado) : [];
|
||||
return state.pedidos?.filter(p => p.aprobado) ?? [];
|
||||
},
|
||||
hayAprobados() {
|
||||
return getters.pedidosAprobados().length !== 0;
|
||||
},
|
||||
getPedido() {
|
||||
return (pedido_id) => state.pedidos.find(p => p.id === pedido_id);
|
||||
return (pedido_id) => state.pedidos?.find(p => p.id === pedido_id);
|
||||
},
|
||||
getCaracteristica() {
|
||||
return (caracteristica) => state[`${caracteristica}_habilitadas`];
|
||||
|
|
42
resources/js/store/modules/barrio.js
vendored
42
resources/js/store/modules/barrio.js
vendored
|
@ -1,42 +0,0 @@
|
|||
import axios from "axios";
|
||||
|
||||
const state = {
|
||||
grupo_de_compra_id: null,
|
||||
grupo_de_compra: null,
|
||||
devoluciones_habilitadas: null,
|
||||
pedidos: [],
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
setGrupoDeCompra(state, { grupo_de_compra }) {
|
||||
state.grupo_de_compra_id = grupo_de_compra.id;
|
||||
state.grupo_de_compra = grupo_de_compra.nombre;
|
||||
state.devoluciones_habilitadas = grupo_de_compra.devoluciones_habilitadas;
|
||||
},
|
||||
setPedidos(state, pedidos) {
|
||||
state.pedidos = pedidos;
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
async getGrupoDeCompra({ commit }) {
|
||||
const response = await axios.get('/user/grupo_de_compra');
|
||||
commit('setGrupoDeCompra', response.data);
|
||||
},
|
||||
async getPedidos({ commit }, nombre) {
|
||||
const response = await axios.get('/api/subpedidos/',{
|
||||
params: {
|
||||
nombre: nombre,
|
||||
grupo_de_compra: state.grupo_de_compra_id
|
||||
}
|
||||
});
|
||||
commit('setPedidos', response.data);
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions,
|
||||
};
|
25
resources/js/store/modules/login.js
vendored
25
resources/js/store/modules/login.js
vendored
|
@ -30,8 +30,8 @@ const actions = {
|
|||
commit('setRegiones', { regiones: response.data });
|
||||
},
|
||||
async selectRegion({ commit }, { region }) {
|
||||
const response = await axios.get("/api/grupos-de-compra");
|
||||
commit('setRegionYBarrios', { region: region, grupos_de_compra: response.data[region] });
|
||||
const response = await axios.get(`/api/regiones/${region}`);
|
||||
commit('setRegionYBarrios', { region: region, grupos_de_compra: response.data });
|
||||
},
|
||||
async getRol({ commit }) {
|
||||
const response = await axios.get("/user/rol");
|
||||
|
@ -49,6 +49,27 @@ const getters = {
|
|||
ayuda: `Si no la sabés, consultá a ${getters.adminUrl() ? 'la comisión informática ' : 'tus compañerxs'}.`
|
||||
};
|
||||
},
|
||||
urlRol() {
|
||||
let split = window.location.pathname
|
||||
.replace('login', '')
|
||||
.split('/')
|
||||
.filter(x => x.length);
|
||||
return split[0] ?? 'pedido';
|
||||
},
|
||||
titulos() {
|
||||
let rol = getters.urlRol();
|
||||
switch (rol) {
|
||||
case 'admin':
|
||||
return { titulo: "Administración de Pedidos MPS", subtitlo: "administración de pedidos" };
|
||||
case 'compras':
|
||||
return { titulo: "Comisiones MPS", subtitlo: "página de comisiones" };
|
||||
case 'pedido':
|
||||
return { titulo: "Pedidos MPS", subtitlo: "aplicación de pedidos" };
|
||||
default:
|
||||
throw new Error("Url inválida");
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default {
|
||||
|
|
52
resources/js/store/modules/pedido.js
vendored
52
resources/js/store/modules/pedido.js
vendored
|
@ -2,6 +2,7 @@ import axios from "axios";
|
|||
|
||||
const state = {
|
||||
lastFetch: null,
|
||||
grupo_de_compra: null,
|
||||
pedido_id: null,
|
||||
nombre: null,
|
||||
productos: null,
|
||||
|
@ -15,7 +16,10 @@ const state = {
|
|||
};
|
||||
|
||||
const mutations = {
|
||||
setState(state, pedido) {
|
||||
setGrupoDeCompra(state, grupo_de_compra) {
|
||||
state.grupo_de_compra = grupo_de_compra;
|
||||
},
|
||||
setPedido(state, pedido) {
|
||||
state.lastFetch = new Date();
|
||||
state.pedido_id = pedido.id;
|
||||
state.nombre = pedido.nombre;
|
||||
|
@ -28,18 +32,28 @@ const mutations = {
|
|||
state.devoluciones_total = pedido.devoluciones_total;
|
||||
state.devoluciones_notas = pedido.devoluciones_notas;
|
||||
},
|
||||
reset(state) {
|
||||
state.lastFetch = null;
|
||||
state.pedido_id = null;
|
||||
state.nombre = null;
|
||||
state.productos = null;
|
||||
state.aprobado = null;
|
||||
state.total = null;
|
||||
state.total_transporte = null;
|
||||
state.cantidad_transporte = null;
|
||||
state.total_sin_devoluciones = null;
|
||||
state.devoluciones_total = null;
|
||||
state.devoluciones_notas = null;
|
||||
}
|
||||
};
|
||||
|
||||
const actions = {
|
||||
async guardarSesion(_, { pedido_id }) {
|
||||
await axios.post("/subpedidos/sesion", { id: pedido_id });
|
||||
async getGrupoDeCompra({ commit }) {
|
||||
const response = await axios.get('/user/grupo_de_compra');
|
||||
commit('setGrupoDeCompra', response.data.grupo_de_compra);
|
||||
},
|
||||
async getSesion({ commit }) {
|
||||
const sesion = await axios.get("/subpedidos/sesion");
|
||||
if (sesion.data) {
|
||||
const response = await axios.get(`/api/subpedidos/${sesion.data}`);
|
||||
commit('setState', response.data.data);
|
||||
}
|
||||
async guardarSesion(_, { pedido_id }) {
|
||||
await axios.post("/pedido/sesion", { id: pedido_id });
|
||||
},
|
||||
async crearPedido({ commit, dispatch }, { nombre, grupo_de_compra_id }) {
|
||||
const response = await axios.post("/api/subpedidos", {
|
||||
|
@ -47,12 +61,12 @@ const actions = {
|
|||
grupo_de_compra_id: grupo_de_compra_id
|
||||
});
|
||||
dispatch("guardarSesion", { pedido_id: response.data.data.id});
|
||||
commit('setState', response.data.data);
|
||||
commit('setPedido', response.data.data);
|
||||
},
|
||||
async elegirPedido({ commit, dispatch }, { pedido }) {
|
||||
const response = await axios.get(`/api/subpedidos/${pedido.id}`);
|
||||
dispatch("guardarSesion", { pedido_id: response.data.data.id})
|
||||
commit('setState', response.data.data);
|
||||
async elegirPedido({ commit, dispatch }, { pedido_id }) {
|
||||
const response = await axios.get(`/api/subpedidos/${pedido_id}`);
|
||||
dispatch("guardarSesion", { pedido_id: pedido_id})
|
||||
commit('setPedido', response.data.data);
|
||||
},
|
||||
async modificarChismosa({ commit, dispatch }, { producto_id, cantidad, notas }) {
|
||||
try {
|
||||
|
@ -61,7 +75,7 @@ const actions = {
|
|||
producto_id: producto_id,
|
||||
notas: notas,
|
||||
});
|
||||
commit('setState', response.data.data);
|
||||
commit('setPedido', response.data.data);
|
||||
dispatch("ui/toast", { mensaje: 'Pedido modificado con éxito' }, { root: true });
|
||||
} catch (error) {
|
||||
dispatch("ui/error", { error: error }, { root: true });
|
||||
|
@ -73,12 +87,18 @@ const actions = {
|
|||
total: monto,
|
||||
notas: notas,
|
||||
});
|
||||
commit('setState', response.data.data);
|
||||
commit('setPedido', response.data.data);
|
||||
dispatch("ui/toast", { mensaje: 'Devoluciones modificadas con éxito' }, { root: true });
|
||||
} catch (error) {
|
||||
dispatch("ui/error", { error: error }, { root: true });
|
||||
}
|
||||
},
|
||||
async resetear({ commit, dispatch }) {
|
||||
await axios.delete("/pedido/sesion");
|
||||
dispatch("productos/getProductos", null, { root: true });
|
||||
dispatch("ui/resetear", null, { root: true });
|
||||
commit('reset');
|
||||
},
|
||||
};
|
||||
|
||||
const getters = {
|
||||
|
|
26
resources/js/store/modules/ui.js
vendored
26
resources/js/store/modules/ui.js
vendored
|
@ -1,10 +1,7 @@
|
|||
import { dropWhile } from "lodash/array";
|
||||
|
||||
const state = {
|
||||
show_chismosa: false,
|
||||
show_devoluciones: false,
|
||||
miga_inicial: { nombre: 'Categorias', action: 'productos/getProductos' },
|
||||
migas: [{ nombre: 'Categorias', action: 'productos/getProductos' }],
|
||||
migas: [{ nombre: 'Pedidos', action: 'pedido/resetear' }],
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
|
@ -17,11 +14,27 @@ const mutations = {
|
|||
addMiga(state, miga) {
|
||||
state.migas.push(miga);
|
||||
},
|
||||
popUltimaBusqueda(state) {
|
||||
if (!state.migas.at(-1).action)
|
||||
state.migas.pop();
|
||||
},
|
||||
reset(state) {
|
||||
state.show_chismosa = false;
|
||||
state.show_devoluciones = false;
|
||||
}
|
||||
};
|
||||
|
||||
const actions = {
|
||||
clickMiga({ dispatch }, { miga }) {
|
||||
dispatch(miga.action, null, { root: true });
|
||||
let dropWhile = (array, pred) => {
|
||||
let result = array.slice(0);
|
||||
while (result.length && pred(result[0])) {
|
||||
result = result.slice(1)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
dispatch(miga.action, miga.arguments ?? null, { root: true });
|
||||
state.migas = dropWhile(state.migas.reverse(),(m => m.nombre !== miga.nombre)).reverse();
|
||||
},
|
||||
toast(_, { mensaje }) {
|
||||
|
@ -38,6 +51,9 @@ const actions = {
|
|||
: error.message;
|
||||
dispatch("toast", { mensaje: errorMsg });
|
||||
},
|
||||
resetear({ commit }) {
|
||||
commit("reset");
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
|
|
5
resources/sass/app.scss
vendored
5
resources/sass/app.scss
vendored
|
@ -7,6 +7,11 @@
|
|||
@import 'bulma';
|
||||
@import '~bulma-switch';
|
||||
|
||||
html, body {
|
||||
overflow-x: hidden;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
main.has-top-padding {
|
||||
padding-top: 4.5rem !important;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,7 @@
|
|||
<body>
|
||||
<section class="section">
|
||||
<div id="root" class="container">
|
||||
<h1 class="title has-text-white">
|
||||
Administración de Pedidos MPS
|
||||
</h1>
|
||||
<p class="subtitle has-text-white">
|
||||
Bienvenidx a la administración de pedidos del <strong class="has-text-white">Mercado Popular de Subsistencia</strong>
|
||||
</p>
|
||||
<login-titulos></login-titulos>
|
||||
@error('name')
|
||||
<div class="notification is-warning">
|
||||
Contraseña incorrecta, intentalo nuevamente.
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<admin-body></admin-body>
|
||||
@endsection
|
|
@ -11,13 +11,8 @@
|
|||
<body>
|
||||
<section class="section">
|
||||
<div id="root" class="container">
|
||||
<h1 class="title">
|
||||
Pedidos MPS
|
||||
</h1>
|
||||
<p class="subtitle">
|
||||
Bienvenidx a la sección de compras de la aplicación del <strong>Mercado Popular de Subsistencia</strong>
|
||||
</p>
|
||||
@error('name')
|
||||
<login-titulos></login-titulos>
|
||||
@error('name')
|
||||
<div class="notification is-danger">
|
||||
Contraseña incorrecta, intentalo nuevamente.
|
||||
</div>
|
||||
|
|
|
@ -1,35 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{ config('app.name', 'Pedidos del MPS') }}</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
|
||||
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
|
||||
<script src="https://kit.fontawesome.com/9235d1c676.js" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
<section class="section">
|
||||
<div id="root" class="container">
|
||||
<admin-boton-login></admin-boton-login>
|
||||
<h1 class="title">
|
||||
Pedidos MPS
|
||||
</h1>
|
||||
<p class="subtitle">
|
||||
Bienvenidx a la aplicación de pedidos del <strong>Mercado Popular de Subsistencia</strong>
|
||||
</p>
|
||||
@error('name')
|
||||
<div class="notification is-danger">
|
||||
Contraseña incorrecta, intentalo nuevamente.
|
||||
</div>
|
||||
@enderror
|
||||
<comunes-region-select></comunes-region-select>
|
||||
<form method="post" action="/login">
|
||||
@csrf
|
||||
<comunes-login-form></comunes-login-form>
|
||||
</form>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{ config('app.name', 'Pedidos del MPS') }}</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
|
||||
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
|
||||
<script src="https://kit.fontawesome.com/9235d1c676.js" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
<section class="section">
|
||||
<div id="root" class="container">
|
||||
<admin-boton-login></admin-boton-login>
|
||||
<login-titulos></login-titulos>
|
||||
@error('name')
|
||||
<div class="notification is-danger">
|
||||
Contraseña incorrecta, intentalo nuevamente.
|
||||
</div>
|
||||
</section>
|
||||
<script src="{{ mix('js/app.js') }}" defer></script>
|
||||
</body>
|
||||
@enderror
|
||||
<comunes-region-select></comunes-region-select>
|
||||
<form method="post" action="/login">
|
||||
@csrf
|
||||
<comunes-login-form></comunes-login-form>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
<script src="{{ mix('js/app.js') }}" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<compras-body></compras-body>
|
||||
@endsection
|
|
@ -17,14 +17,9 @@
|
|||
</head>
|
||||
<body class="has-navbar-fixed-top">
|
||||
<div id="root">
|
||||
<comunes-nav-bar>
|
||||
<template #logout-form>
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
|
||||
@csrf
|
||||
</form>
|
||||
</template>
|
||||
</comunes-nav-bar>
|
||||
<pedidos-nav-migas></pedidos-nav-migas>
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none" hidden="hidden">
|
||||
@csrf
|
||||
</form>
|
||||
<main id="main" class="py-4 has-top-padding">
|
||||
@yield('content')
|
||||
</main>
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<pedidos-body></pedidos-body>
|
||||
<pedidos-devoluciones-modal></pedidos-devoluciones-modal>
|
||||
@endsection
|
|
@ -1,8 +0,0 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<app-main></app-main>
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
@endsection
|
|
@ -1,8 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\GrupoDeCompra;
|
||||
use App\Producto;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -15,33 +13,17 @@ use App\Producto;
|
|||
|
|
||||
*/
|
||||
|
||||
Route::middleware('api')->group(function () {
|
||||
Route::get('/regiones', function() {
|
||||
return GrupoDeCompra::all()->pluck('region')->unique()->flatten();
|
||||
});
|
||||
|
||||
Route::prefix('grupos-de-compra')->group( function(){
|
||||
Route::get('/', function() {
|
||||
$atributos_a_ocultar = ['telefono', 'cantidad_de_nucleos', 'correo', 'referente_finanzas', 'created_at', 'updated_at'];
|
||||
return GrupoDeCompra::all()->makeHidden($atributos_a_ocultar)->sortBy('nombre')->groupBy('region');
|
||||
});
|
||||
Route::middleware('api')->group(function() {
|
||||
Route::get('/regiones', 'Api\GrupoDeCompraController@regiones');
|
||||
Route::get('/regiones/{region}', 'Api\GrupoDeCompraController@region');
|
||||
|
||||
Route::prefix('grupos-de-compra')->group(function() {
|
||||
Route::get('/{grupoDeCompra}', 'Api\GrupoDeCompraController@show');
|
||||
|
||||
Route::get('/{gdc}/devoluciones', function($gdc) {
|
||||
$habilitadas = GrupoDeCompra::find($gdc)->devoluciones_habilitadas;
|
||||
return ['devoluciones' => $habilitadas];
|
||||
});
|
||||
|
||||
Route::post('/{gdc}/devoluciones', function($gdc) {
|
||||
GrupoDeCompra::find($gdc)->toggleDevoluciones();
|
||||
return response()->noContent();
|
||||
});
|
||||
Route::post('/{gdc}/devoluciones', 'Api\GrupoDeCompraController@toggleDevoluciones');
|
||||
});
|
||||
|
||||
Route::prefix('subpedidos')->group(function () {
|
||||
Route::get('/','Api\SubpedidoController@index');
|
||||
Route::get('/resources', 'Api\SubpedidoController@indexResources');
|
||||
Route::get('{subpedido}','Api\SubpedidoController@show');
|
||||
Route::post('/','Api\SubpedidoController@store');
|
||||
Route::post('/{subpedido}/sync', 'Api\SubpedidoController@syncProductos');
|
||||
|
@ -55,13 +37,10 @@ Route::middleware('api')->group(function () {
|
|||
});
|
||||
|
||||
//@TO DO -> esta ruta debe estar en middleware de auth y/o subpedido
|
||||
Route::get('/categorias', function() {
|
||||
return Producto::all()->pluck('categoria')->unique()->flatten();
|
||||
});
|
||||
Route::get('/categorias', 'Api\ProductoController@categorias');
|
||||
|
||||
//@TO DO -> esta ruta debe estar en middleware de auth y/o subpedido
|
||||
Route::prefix('productos')->group(function () {
|
||||
Route::get('/','Api\ProductoController@index');
|
||||
Route::get('{producto}','Api\ProductoController@show');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,7 +4,6 @@ use Illuminate\Support\Facades\App;
|
|||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Routes
|
||||
|
@ -31,42 +30,9 @@ Route::middleware(['auth'])->group(function () {
|
|||
|
||||
Route::middleware(['auth', 'role:barrio'])->group(function() {
|
||||
Route::get('/pedido', 'RouteController@main')->name('pedido');
|
||||
|
||||
Route::get('/productos', 'ProductoController@index')->name('productos.index');
|
||||
|
||||
Route::name('subpedidos.')->prefix("subpedidos")->group(function() {
|
||||
Route::get('/', function() {
|
||||
return view('subpedidos_create');
|
||||
})->name('create');
|
||||
|
||||
Route::post('guardar_sesion', function() {
|
||||
$r = request();
|
||||
if (!isset($r["subpedido"])) {
|
||||
throw new HttpException(400, "La request necesita un subpedido para guardar en sesión");
|
||||
}
|
||||
if (!isset($r["grupo_de_compra_id"])) {
|
||||
throw new HttpException(400, "La request necesita un grupo de compra para guardar en sesión");
|
||||
}
|
||||
session(["subpedido_nombre" => $r["subpedido"]["nombre"]]);
|
||||
session(["subpedido_id" => $r["subpedido"]["id"]]);
|
||||
session(["gdc" => $r["grupo_de_compra_id"]]);
|
||||
return "Subpedido guardado en sesión";
|
||||
})->name('guardarSesion');
|
||||
|
||||
Route::get('obtener_sesion', function() {
|
||||
return [
|
||||
'subpedido' => [
|
||||
'nombre' => session("subpedido_nombre"),
|
||||
'id' => session("subpedido_id")
|
||||
],
|
||||
'gdc' => session("gdc")
|
||||
];
|
||||
})->name('obtenerSesion');
|
||||
|
||||
Route::post('sesion', 'SessionController@store');
|
||||
|
||||
Route::get('sesion', 'SessionController@fetch');
|
||||
});
|
||||
Route::get('/pedido/sesion', 'SessionController@fetch');
|
||||
Route::post('/pedido/sesion', 'SessionController@store');
|
||||
Route::delete('/pedido/sesion', 'SessionController@destroy');
|
||||
});
|
||||
|
||||
Route::get('/admin/login', 'AdminController@show')->name('admin.login');
|
||||
|
@ -75,9 +41,7 @@ Route::middleware(['auth', 'role:admin_barrio'])->group(function () {
|
|||
Route::get('/admin', 'RouteController@main')->name('admin');
|
||||
|
||||
Route::get('/admin/exportar-planillas-a-pdf/{gdc}', 'AdminController@exportarPedidosAPdf');
|
||||
|
||||
Route::get('/admin/exportar-pedido-a-csv/{gdc}', 'AdminController@exportarPedidoACSV');
|
||||
|
||||
Route::get('/admin/exportar-pedido-con-nucleos-a-csv/{gdc}', 'AdminController@exportarPedidoConNucleosACSV');
|
||||
});
|
||||
|
||||
|
@ -88,6 +52,6 @@ Route::middleware(['auth', 'role:comision'])->group( function() {
|
|||
Route::get('/compras/pedidos/descargar', 'ComprasController@descargarPedidos')->name('compras.pedidos.descargar');
|
||||
Route::get('/compras/pedidos/notas', 'ComprasController@descargarNotas')->name('compras.pedidos.descargar');
|
||||
Route::get('/compras/pedidos/pdf', 'ComprasController@pdf')->name('compras.pedidos.pdf');
|
||||
Route::post('/compras/canasta', 'ComprasController@cargarCanasta')->name('compras.canasta');
|
||||
Route::get('/compras/canasta/ejemplo', 'ComprasController@descargarCanastaEjemplo')->name('compras.canasta.ejemplo');
|
||||
Route::post('/compras/canasta', 'ComprasController@cargarCanasta')->name('compras.canasta');
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue