Compare commits
47 commits
master
...
funcion/ac
Author | SHA1 | Date | |
---|---|---|---|
9ee6de7877 | |||
8362cacc84 | |||
e029c42c0a | |||
596ac50e60 | |||
f6de37a1eb | |||
9d98a5cd5b | |||
4062f4b786 | |||
bd92c26b0a | |||
6ea534932f | |||
96516a5083 | |||
9c07a91914 | |||
d5e70dc291 | |||
dd463a6a79 | |||
35e1d6455e | |||
572a8cf3be | |||
b976826bf5 | |||
da4fd472ae | |||
89f886e32c | |||
92d6bc2035 | |||
fee23f389c | |||
7619196179 | |||
537bfd52ff | |||
3a313d033d | |||
cee049c545 | |||
0207fca0cc | |||
ed89065faf | |||
502aefd7a8 | |||
44f0d8c66b | |||
03475daa99 | |||
aa75e3de79 | |||
21b16e0243 | |||
e0d17e052b | |||
e3b17eea4a | |||
5e54d2afea | |||
9a57a826dc | |||
a1aa381052 | |||
ea9a9e2195 | |||
251dbd1120 | |||
98120f1ce9 | |||
71c4b166be | |||
c35eb49001 | |||
0cdb491246 | |||
01cf18b540 | |||
8dba92e8c1 | |||
c602742e33 | |||
a4951bfdfd | |||
88c82d9439 |
47 changed files with 4315 additions and 26576 deletions
|
@ -4,9 +4,11 @@ APP_KEY=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
APP_URL=http://localhost
|
APP_URL=http://localhost
|
||||||
|
|
||||||
|
VITE_DEV_SERVER_URL=http://vite:5173
|
||||||
|
|
||||||
LOG_CHANNEL=stack
|
LOG_CHANNEL=stack
|
||||||
|
|
||||||
USERID=
|
USERID=1000
|
||||||
|
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
DB_HOST=db
|
DB_HOST=db
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM php:7.4-fpm
|
FROM php:8.3-fpm
|
||||||
|
|
||||||
# Arguments defined in docker-compose.yml
|
# Arguments defined in docker-compose.yml
|
||||||
ARG user
|
ARG user
|
||||||
|
@ -12,7 +12,8 @@ RUN apt-get update && apt-get install -y \
|
||||||
libonig-dev \
|
libonig-dev \
|
||||||
libxml2-dev \
|
libxml2-dev \
|
||||||
zip \
|
zip \
|
||||||
unzip
|
unzip \
|
||||||
|
libzip-dev
|
||||||
|
|
||||||
# Install node
|
# Install node
|
||||||
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
|
RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
|
||||||
|
@ -22,7 +23,7 @@ RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
|
||||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Install PHP extensions
|
# Install PHP extensions
|
||||||
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
|
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip
|
||||||
|
|
||||||
# Get latest Composer
|
# Get latest Composer
|
||||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||||
|
|
87
README.md
87
README.md
|
@ -2,13 +2,14 @@
|
||||||
|
|
||||||
Aplicación de pedidos del Mercado Popular de Subsistencia.
|
Aplicación de pedidos del Mercado Popular de Subsistencia.
|
||||||
|
|
||||||
Pedi2 está hecha en Laravel 7 y utiliza laravel7-docker de dyarleniber.
|
Pedi2 está hecha en Laravel 12 y Vue 2 con Vite y Vuex.
|
||||||
|
|
||||||
Se utilizan los siguientes servicios, separadamente:
|
Se utilizan los siguientes servicios, separadamente:
|
||||||
|
|
||||||
- `app`, un servicio que corre PHP7.4-FPM.
|
- `app`, un servicio que corre PHP8.3-FPM.
|
||||||
- `db`, un servicio que corre MySQL 5.7.
|
- `db`, un servicio que corre MySQL 5.7.
|
||||||
- `nginx`, un servicio que usa el servicio app para parsear código PHP antes de servir la aplicación de Laravel al usuario final.
|
- `nginx`, un servicio que usa el servicio app para parsear código PHP antes de servir la aplicación de Laravel al usuario final.
|
||||||
|
- `vite`, un servicio que corre el frontend de la aplicación.
|
||||||
|
|
||||||
## Pre-requisitos
|
## Pre-requisitos
|
||||||
- docker
|
- docker
|
||||||
|
@ -17,28 +18,28 @@ Se utilizan los siguientes servicios, separadamente:
|
||||||
## Instalación
|
## Instalación
|
||||||
1. Una vez descargado el proyecto, hacé una copia del archivo `.env.example` que se encuentra en la raíz del proyecto y nombrala `.env`. Seteá los valores correctos - específicamente, para las variables, `APP_URL`, `DB_USERNAME` y `DB_PASSWORD`. Prestá atención a que `DB_HOST` sea el nombre del servicio que corre MySQL (por defecto `DB_HOST=db`).
|
1. Una vez descargado el proyecto, hacé una copia del archivo `.env.example` que se encuentra en la raíz del proyecto y nombrala `.env`. Seteá los valores correctos - específicamente, para las variables, `APP_URL`, `DB_USERNAME` y `DB_PASSWORD`. Prestá atención a que `DB_HOST` sea el nombre del servicio que corre MySQL (por defecto `DB_HOST=db`).
|
||||||
|
|
||||||
2. Levantá los contenedores, construyendo la imagen de la app primero
|
2. Levantá los contenedores, construyendo la imagen de la app primero:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d --build
|
docker-compose up --build
|
||||||
```
|
```
|
||||||
|
|
||||||
El ambiente ahora está andando, pero necesitamos ejecutar un par de comandos para terminar la instalación de Laravel. Podemos usar `docker-compose exec [nombre-del-servicio]` previo a un comando para ejecutarlo dentro del contenedor.
|
El ambiente ahora está andando, deberías ver los logs de cada servicio en la terminal. Falta ejecutar un par de comandos para terminar la instalación de Laravel. Podemos usar `docker-compose exec [nombre-del-servicio]` previo a un comando para ejecutarlo dentro del contenedor.
|
||||||
|
|
||||||
3. Terminá de instalar las dependencias de la app, según fueron definidas en `composer.json`.
|
3. Abrí una nueva terminal, y terminá de instalar las dependencias de la app, según fueron definidas en `composer.json`:
|
||||||
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose exec app composer install
|
docker-compose exec app composer install
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Generá una clave de aplicación. Esta clave se usa para encriptar datos sensibles.
|
4. Generá una clave de aplicación. Esta clave se usa para encriptar datos sensibles:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose exec app php artisan key:generate
|
docker-compose exec app php artisan key:generate
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Corré las migraciones y seeders de Laravel
|
5. Corré las migraciones y seeders de Laravel:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose exec app php artisan migrate:fresh --seed
|
docker-compose exec app php artisan migrate:fresh --seed
|
||||||
|
@ -46,7 +47,7 @@ docker-compose exec app php artisan migrate:fresh --seed
|
||||||
|
|
||||||
6. Copia el token que se imprime al correr los seeders. Lo necesitamos para autenticar las llamadas que hagamos desde nuestro cliente web
|
6. Copia el token que se imprime al correr los seeders. Lo necesitamos para autenticar las llamadas que hagamos desde nuestro cliente web
|
||||||
|
|
||||||
7. Instala las dependencias de npm
|
7. Instala las dependencias de npm:
|
||||||
```bash
|
```bash
|
||||||
docker-compose exec app npm install
|
docker-compose exec app npm install
|
||||||
```
|
```
|
||||||
|
@ -54,73 +55,13 @@ docker-compose exec app npm install
|
||||||
Ahora la aplicación está corriendo y la podés ver en el puerto 8000 de tu dominio o IP. En caso de que estés en tu máquina local, la vas a ver accediendo a `http://localhost:8000` desde tu navegador.
|
Ahora la aplicación está corriendo y la podés ver en el puerto 8000 de tu dominio o IP. En caso de que estés en tu máquina local, la vas a ver accediendo a `http://localhost:8000` desde tu navegador.
|
||||||
|
|
||||||
Podés usar el comando `logs` para ver los logs generados por tus servicios:
|
Podés usar el comando `logs` para ver los logs generados por tus servicios:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose logs nginx
|
docker-compose logs nginx
|
||||||
```
|
```
|
||||||
|
---
|
||||||
|
|
||||||
8. Ejecuta npm para compilar el js y css
|
Si estás actualizando o no te anda, probá limpiar los caches:
|
||||||
```bash
|
|
||||||
docker-compose exec app npm run prod
|
|
||||||
```
|
```
|
||||||
|
docker-compose exec app php artisan optimize:clear
|
||||||
## Services description
|
docker-compose exec app composer dump-autoload
|
||||||
|
|
||||||
### Dockerfile
|
|
||||||
|
|
||||||
Although both `db` service and `nginx` service, will be based on default images obtained from the Docker Hub, the `app` service will be based on a custom image created by the `Dockerfile`.
|
|
||||||
|
|
||||||
The `Dockerfile` starts by defining the base image `php:7.4-fpm`.
|
|
||||||
|
|
||||||
After installing system packages and PHP extensions, the Composer will be installed by copying the composer executable from its latest official image.
|
|
||||||
|
|
||||||
A new system user is then created and set up using the `user` and `uid` arguments that were declared at the beginning of the `Dockerfile`. These values will be injected by Docker Compose at build time.
|
|
||||||
|
|
||||||
> This new system user is necessary to execute Laravel Artisan and Composer commands while developing the application. The `uid` setting ensures that the user inside the container has the same `uid` as your system user on your host machine. This way, any files created by these commands are replicated in the host with the correct permissions. This also means that you’ll be able to use your code editor of choice in the host machine to develop the application that is running inside containers.
|
|
||||||
|
|
||||||
Finally, the default working dir as `/var/www` and the newly created user are set. This will make sure you’re connecting as a regular user, and that you’re on the right directory, when running Laravel Artisan and Composer commands on the application container.
|
|
||||||
|
|
||||||
### PHP service
|
|
||||||
|
|
||||||
The `app` service will build an image called `laravel-image`, based on the `Dockerfile` previously created. The container defined by this service will run a php-fpm server to parse PHP code and send the results back to the nginx service, which will be running on a separate container. The mysql service defines a container running a MySQL 5.7 server. All these services will share a bridge network named `app-network`.
|
|
||||||
|
|
||||||
The application files will be synchronized on both the `app` and the `nginx` services via bind mounts. Bind mounts are useful in development environments because they allow for a performant two-way sync between host machine and containers.
|
|
||||||
|
|
||||||
Inside the `app` container you will be able to execute command line tasks with the Laravel Artisan and Composer.
|
|
||||||
|
|
||||||
The `app` service will set up a container named `laravel-app`. It builds a new Docker image based on a `Dockerfile` located in the same path as the `docker-compose.yml` file. The new image will be saved locally under the name `laravel-image`.
|
|
||||||
|
|
||||||
The `volumes` setting creates a shared volume that will synchronize contents from the current directory to `/var/www` inside the container. Notice that this is not your document root, since that will live in the nginx container.
|
|
||||||
|
|
||||||
Another file which will be synchronized is the `local.ini` file from the directory `./php/local.ini` to `/usr/local/etc/php/conf.d/local.ini` inside the container.
|
|
||||||
|
|
||||||
The `local.ini` is the configuration file (php.ini) that is read when PHP starts up.
|
|
||||||
|
|
||||||
### Nginx service
|
|
||||||
|
|
||||||
The `nginx` service uses a pre-built Nginx image on top of Alpine, a lightweight Linux distribution. It creates a container named `laravel-nginx`, and it uses the ports definition to create a redirection from port `8000` on the host system to port `80` inside the container.
|
|
||||||
|
|
||||||
The `volumes` setting creates two shared volumes. The first one will synchronize contents from the current directory to `/var/www` inside the container. This way, when you make local changes to the application files, they will be quickly reflected in the application being served by Nginx inside the container. The second volume will make sure the Nginx configuration file, located at `./nginx/conf.d/app.conf`, is copied to the container’s Nginx configuration folder. This configuration file will configure Nginx to listen on port `80` and use `index.php` as default index page. It will set the document root to `/var/www/public`, and then configure Nginx to use the `app` service on port `9000` to process all the php files.
|
|
||||||
|
|
||||||
### MySQL service
|
|
||||||
|
|
||||||
The `db` service uses a pre-built MySQL 5.7 image from Docker Hub. Because Docker Compose automatically loads `.env` variable files located in the same directory as the `docker-compose.yml` file, you can obtain the database settings from the Laravel `.env` file.
|
|
||||||
|
|
||||||
The `volumes` setting creates two shared volumes. The first one will make sure the MySQL configuration file, located at `./mysql/my.cnf`, is copied to the container’s MySQL configuration folder. The second volume will share a `.sql` database dump that will be used to initialize the application database. The MySQL image will automatically import `.sql` files placed in the `/docker-entrypoint-initdb.d` directory inside the container.
|
|
||||||
|
|
||||||
The `environment` setting defines environment variables in the new container. You can use values obtained from the Laravel `.env` file to set up the MySQL service, which will automatically create a new database and user based on the provided environment variables:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
DB_HOST=db
|
|
||||||
DB_DATABASE=laravelapp
|
|
||||||
DB_USERNAME=laravelapp_user
|
|
||||||
DB_PASSWORD=password
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## References
|
|
||||||
|
|
||||||
- https://www.digitalocean.com/community/tutorials/how-to-install-and-set-up-laravel-with-docker-compose-on-ubuntu-20-04
|
|
||||||
- https://docs.docker.com/
|
|
||||||
- https://docs.docker.com/compose/
|
|
||||||
- https://github.com/dyarleniber/laravel7-docker
|
|
||||||
- https://laravel.com/docs/7.x/installation
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ use TypeError;
|
||||||
class Filtro extends Model
|
class Filtro extends Model
|
||||||
{
|
{
|
||||||
protected Request $request;
|
protected Request $request;
|
||||||
protected $builder;
|
|
||||||
protected array $MENSAJES_ERROR = [
|
protected array $MENSAJES_ERROR = [
|
||||||
'ARGUMENTO' => 'Argumento inválido para el parámetro %s. Revise la documentación.'
|
'ARGUMENTO' => 'Argumento inválido para el parámetro %s. Revise la documentación.'
|
||||||
];
|
];
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Kernel extends HttpKernel
|
||||||
protected $middleware = [
|
protected $middleware = [
|
||||||
// \App\Http\Middleware\TrustHosts::class,
|
// \App\Http\Middleware\TrustHosts::class,
|
||||||
\App\Http\Middleware\TrustProxies::class,
|
\App\Http\Middleware\TrustProxies::class,
|
||||||
\Fruitcake\Cors\HandleCors::class,
|
\Illuminate\Http\Middleware\HandleCors::class,
|
||||||
\App\Http\Middleware\CheckForMaintenanceMode::class,
|
\App\Http\Middleware\CheckForMaintenanceMode::class,
|
||||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||||
\App\Http\Middleware\TrimStrings::class,
|
\App\Http\Middleware\TrimStrings::class,
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
use Fideloper\Proxy\TrustProxies as Middleware;
|
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||||
use Illuminate\Http\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
class TrustProxies extends Middleware
|
class TrustProxies extends Middleware
|
||||||
{
|
{
|
||||||
|
@ -19,5 +19,8 @@ class TrustProxies extends Middleware
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
protected $headers = Request::HEADER_X_FORWARDED_ALL;
|
protected $headers = Request::HEADER_X_FORWARDED_FOR |
|
||||||
|
Request::HEADER_X_FORWARDED_HOST |
|
||||||
|
Request::HEADER_X_FORWARDED_PORT |
|
||||||
|
Request::HEADER_X_FORWARDED_PROTO;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,23 +8,20 @@
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.4",
|
"php": "^8.3",
|
||||||
"doctrine/dbal": "^2.2.0",
|
"doctrine/dbal": "^3.0",
|
||||||
"fideloper/proxy": "^4.4",
|
"guzzlehttp/guzzle": "^7.0.1",
|
||||||
"fruitcake/laravel-cors": "^2.0",
|
"laravel/framework": "^12.0",
|
||||||
"guzzlehttp/guzzle": "^6.3.1|^7.0.1",
|
"laravel/sanctum": "^4.0",
|
||||||
"laravel/framework": "^7.29",
|
"laravel/tinker": "^2.8",
|
||||||
"laravel/sanctum": "^2.13",
|
"laravel/ui": "^4.3",
|
||||||
"laravel/tinker": "^2.5",
|
|
||||||
"laravel/ui": "*",
|
|
||||||
"league/csv": "^9.8",
|
"league/csv": "^9.8",
|
||||||
"mpdf/mpdf": "^8.1",
|
"mpdf/mpdf": "^8.2",
|
||||||
"prexview/prexview": "^1.1"
|
"prexview/prexview": "^1.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"facade/ignition": "^2.0",
|
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
"nunomaduro/collision": "^4.3"
|
"nunomaduro/collision": "^8.0"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"optimize-autoloader": true,
|
"optimize-autoloader": true,
|
||||||
|
@ -55,13 +52,13 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"post-autoload-dump": [
|
"post-autoload-dump": [
|
||||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||||
"@php7.4 artisan package:discover --ansi"
|
"@php artisan package:discover --ansi"
|
||||||
],
|
],
|
||||||
"post-root-package-install": [
|
"post-root-package-install": [
|
||||||
"@php7.4 -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||||
],
|
],
|
||||||
"post-create-project-cmd": [
|
"post-create-project-cmd": [
|
||||||
"@php7.4 artisan key:generate --ansi"
|
"@php artisan key:generate --ansi"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3435
composer.lock
generated
3435
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,7 @@ class UserSeeder extends Seeder
|
||||||
$usersToInsert = [];
|
$usersToInsert = [];
|
||||||
|
|
||||||
$usersToInsert[] = DatabaseSeeder::addTimestamps([
|
$usersToInsert[] = DatabaseSeeder::addTimestamps([
|
||||||
'name' => 'comi',
|
'name' => 'comision',
|
||||||
'password' => Hash::make("123"),
|
'password' => Hash::make("123"),
|
||||||
'role_id' => UserRole::where('nombre', 'comision')->first()->id,
|
'role_id' => UserRole::where('nombre', 'comision')->first()->id,
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -18,6 +18,22 @@ services:
|
||||||
networks:
|
networks:
|
||||||
- app-network
|
- app-network
|
||||||
|
|
||||||
|
vite:
|
||||||
|
build:
|
||||||
|
args:
|
||||||
|
user: www
|
||||||
|
uid: ${USERID}
|
||||||
|
context: ./
|
||||||
|
container_name: vite
|
||||||
|
working_dir: /var/www
|
||||||
|
command: npm run dev
|
||||||
|
volumes:
|
||||||
|
- ./:/var/www
|
||||||
|
ports:
|
||||||
|
- "5173:5173"
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: mysql:5.7
|
image: mysql:5.7
|
||||||
container_name: pedi2-db
|
container_name: pedi2-db
|
||||||
|
|
|
@ -13,6 +13,22 @@ server {
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
}
|
}
|
||||||
|
location ^~ /@vite/ {
|
||||||
|
proxy_pass http://vite:5173;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
}
|
||||||
|
location ^~ /resources/ {
|
||||||
|
proxy_pass http://vite:5173;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection 'upgrade';
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_cache_bypass $http_upgrade;
|
||||||
|
}
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.php?$query_string;
|
try_files $uri $uri/ /index.php?$query_string;
|
||||||
gzip_static on;
|
gzip_static on;
|
||||||
|
|
26580
package-lock.json
generated
26580
package-lock.json
generated
File diff suppressed because it is too large
Load diff
17
package.json
17
package.json
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "npm run development",
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
|
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||||
"watch": "npm run development -- --watch",
|
"watch": "npm run development -- --watch",
|
||||||
"watch-poll": "npm run watch -- --watch-poll",
|
"watch-poll": "npm run watch -- --watch-poll",
|
||||||
|
@ -10,20 +11,24 @@
|
||||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
|
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"axios": "^0.19.2",
|
"@types/axios": "^0.9.36",
|
||||||
|
"@vitejs/plugin-vue2": "^2.3.3",
|
||||||
|
"axios": "^0.27.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"laravel-mix": "^5.0.1",
|
"laravel-vite-plugin": "^1.3.0",
|
||||||
"resolve-url-loader": "^2.3.1",
|
|
||||||
"sass": "^1.20.1",
|
"sass": "^1.20.1",
|
||||||
"sass-loader": "^8.0.0",
|
"sass-loader": "^8.0.0",
|
||||||
"vue": "^2.5.17",
|
"typescript": "^5.4.5",
|
||||||
"vue-template-compiler": "^2.6.10"
|
"vite": "^5.2.8"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"vue": "^2.7.16",
|
||||||
|
"vue-template-compiler": "^2.7.16",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"bulma": "^0.9.4",
|
"bulma": "^0.9.4",
|
||||||
"bulma-switch": "^2.0.4",
|
"bulma-switch": "^2.0.4",
|
||||||
"bulma-toast": "^2.4.1",
|
"bulma-toast": "^2.4.1",
|
||||||
|
"vue-router": "^3.5.4",
|
||||||
"vuex": "^3.6.2"
|
"vuex": "^3.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
45
resources/js/app.js
vendored
45
resources/js/app.js
vendored
|
@ -1,45 +0,0 @@
|
||||||
/**
|
|
||||||
* First we will load all of this project's JavaScript dependencies which
|
|
||||||
* includes Vue and other libraries. It is a great starting point when
|
|
||||||
* building robust, powerful web applications using Vue and Laravel.
|
|
||||||
*/
|
|
||||||
import axios from 'axios';
|
|
||||||
import Vue from 'vue';
|
|
||||||
|
|
||||||
window.Vue = require('vue');
|
|
||||||
window.Event = new Vue();
|
|
||||||
window.axios = axios;
|
|
||||||
window.bulmaToast = require('bulma-toast');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The following block of code may be used to automatically register your
|
|
||||||
* Vue components. It will recursively scan this directory for the Vue
|
|
||||||
* components and automatically register them with their "basename".
|
|
||||||
*
|
|
||||||
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
|
|
||||||
*/
|
|
||||||
import './components';
|
|
||||||
import store from "./store";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Global methods
|
|
||||||
*/
|
|
||||||
Vue.prototype.$toast = function (mensaje, duration = 2000) {
|
|
||||||
return window.bulmaToast.toast({
|
|
||||||
message: mensaje,
|
|
||||||
duration: duration,
|
|
||||||
type: 'is-danger',
|
|
||||||
position: 'bottom-center',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Next, we will create a fresh Vue application instance and attach it to
|
|
||||||
* the page. Then, you may begin adding components to this application
|
|
||||||
* or customize the JavaScript scaffolding to fit your unique needs.
|
|
||||||
*/
|
|
||||||
new Vue({
|
|
||||||
el: '#root',
|
|
||||||
store,
|
|
||||||
});
|
|
||||||
|
|
27
resources/js/app.ts
Normal file
27
resources/js/app.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import * as bulmaToast from 'bulma-toast';
|
||||||
|
import Vue from '../../node_modules/vue/dist/vue.esm.js';
|
||||||
|
import axios from 'axios';
|
||||||
|
import store from "./store";
|
||||||
|
import './shims-vue.d.ts';
|
||||||
|
|
||||||
|
// Registro de components
|
||||||
|
const components = import.meta.glob('./components/**/*.vue', { eager: true });
|
||||||
|
Object.entries(components).forEach(([path, module]) => {
|
||||||
|
let name = path
|
||||||
|
.replace(/^\.\/components\//, '') // Remove leading folder
|
||||||
|
.replace(/\.vue$/, '') // Remove file extension
|
||||||
|
.replace(/\//g, '-') // Replace subfolders with hyphens
|
||||||
|
.replace(/([a-z])([A-Z])/g, '$1-$2') // camelCase to kebab-case
|
||||||
|
.toLowerCase(); // Enforce kebab-case for HTML
|
||||||
|
Vue.component(name, (module as any).default);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.Vue = Vue;
|
||||||
|
window.Event = new Vue();
|
||||||
|
window.axios = axios;
|
||||||
|
window.bulmaToast = bulmaToast;
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#root',
|
||||||
|
store,
|
||||||
|
});
|
25
resources/js/components.js
vendored
25
resources/js/components.js
vendored
|
@ -1,25 +0,0 @@
|
||||||
import Vue from 'vue';
|
|
||||||
|
|
||||||
const requireComponent = require.context('./components', true, /\.vue$/);
|
|
||||||
|
|
||||||
// Registro automático de componentes:
|
|
||||||
// e.g. components/foo/bar/UnComponente.vue
|
|
||||||
// se registra como 'foo-bar-un-componente'
|
|
||||||
requireComponent.keys().forEach(fileName => {
|
|
||||||
// Get the component config
|
|
||||||
const componentConfig = requireComponent(fileName);
|
|
||||||
// Get the PascalCase name of the component
|
|
||||||
const componentName = fileName
|
|
||||||
.replace(/^\.\/(.*)\.\w+$/, '$1') // Remove "./" from the beginning and the file extension from the end
|
|
||||||
.replace(/\//g, '-') // Replace directories with hyphens
|
|
||||||
.replace(/([a-z])([A-Z])/g, '$1-$2') // Insert hyphen between camelCase words
|
|
||||||
.toLowerCase() // Convert to lowercase
|
|
||||||
// Globally register the component
|
|
||||||
Vue.component(
|
|
||||||
componentName,
|
|
||||||
// Look for the component options on `.default`, which will
|
|
||||||
// exist if the component was exported with `export default`,
|
|
||||||
// otherwise fall back to module's root.
|
|
||||||
componentConfig.default || componentConfig
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -1,12 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
import LoginInput from "./login/LoginInput.vue";
|
import LoginInput from "./login/LoginInput.vue";
|
||||||
import LoginLoginTitulos from "./login/LoginTitulos.vue";
|
import LoginTitulos from "./login/LoginTitulos.vue";
|
||||||
import { mapGetters } from "vuex";
|
import { mapGetters } from "vuex";
|
||||||
import LoginDropdown from "./login/LoginDropdown.vue";
|
import LoginDropdown from "./login/LoginDropdown.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'LoginForm',
|
name: 'AppLogin',
|
||||||
components: { LoginDropdown, LoginTitulos: LoginLoginTitulos, LoginInput },
|
components: { LoginDropdown, LoginTitulos, LoginInput },
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters("login", ["estilos"])
|
...mapGetters("login", ["estilos"])
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ export default {
|
||||||
<div id="login-form" :class="estilos.fondo">
|
<div id="login-form" :class="estilos.fondo">
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
<div class="column is-half">
|
<div class="column is-three-quarters">
|
||||||
<login-dropdown class="is-hidden-tablet"/>
|
<login-dropdown class="is-hidden-tablet"/>
|
||||||
<login-titulos/>
|
<login-titulos/>
|
||||||
<login-input/>
|
<login-input/>
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
||||||
<div class="dropdown-content">
|
<div class="dropdown-content">
|
||||||
<a :href="'/admin/exportar-pedido-a-csv/' + grupo_de_compra_id" class="dropdown-item has-background-primary">
|
|
||||||
Planilla para central (CSV)
|
|
||||||
</a>
|
|
||||||
<a :href="'/admin/exportar-planillas-a-pdf/' + grupo_de_compra_id" class="dropdown-item">
|
<a :href="'/admin/exportar-planillas-a-pdf/' + grupo_de_compra_id" class="dropdown-item">
|
||||||
Planillas para armado (PDF)
|
Planillas para armado (PDF)
|
||||||
</a>
|
</a>
|
||||||
<a :href="'/admin/exportar-pedido-con-nucleos-a-csv/' + grupo_de_compra_id" class="dropdown-item">
|
<a :href="'/admin/exportar-pedido-con-nucleos-a-csv/' + grupo_de_compra_id" class="dropdown-item">
|
||||||
Planilla completa de la canasta (CSV)
|
Pedidos por núcleo (CSV)
|
||||||
|
</a>
|
||||||
|
<a :href="'/admin/exportar-pedido-a-csv/' + grupo_de_compra_id" class="dropdown-item">
|
||||||
|
Pedido barrial (CSV)
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -38,7 +38,6 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '../../../../node_modules/bulma';
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script >
|
<script >
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import { mapMutations, mapState } from "vuex";
|
import { mapGetters, mapMutations, mapState } from "vuex";
|
||||||
import CategoriasContainer from "./CategoriasContainer.vue";
|
import CategoriasContainer from "./CategoriasContainer.vue";
|
||||||
import ProductosContainer from "./ProductosContainer.vue";
|
import ProductosContainer from "./ProductosContainer.vue";
|
||||||
import Chismosa from "./Chismosa.vue";
|
import Chismosa from "./Chismosa.vue";
|
||||||
|
@ -9,7 +9,8 @@ import DevolucionesModal from "./DevolucionesModal.vue";
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { DevolucionesModal, CategoriasContainer, ProductosContainer, Chismosa },
|
components: { DevolucionesModal, CategoriasContainer, ProductosContainer, Chismosa },
|
||||||
computed: {
|
computed: {
|
||||||
...mapState('ui', ["show_chismosa", "show_devoluciones", "tags_interactuada"])
|
...mapState('ui', ["show_chismosa", "show_devoluciones", "tags_interactuada"]),
|
||||||
|
...mapGetters('productos', ["mostrarProductos"]),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations("ui", ["toggleTags"]),
|
...mapMutations("ui", ["toggleTags"]),
|
||||||
|
@ -23,8 +24,8 @@ export default defineComponent({
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="columns ml-3 mr-3" v-else>
|
<div class="columns ml-3 mr-3" v-else>
|
||||||
<categorias-container :class="show_chismosa ? 'hide-below-1024' : ''"/>
|
<productos-container v-if="mostrarProductos" :class="show_chismosa ? 'hide-below-1024' : ''"/>
|
||||||
<productos-container :class="show_chismosa ? 'hide-below-1024' : ''"/>
|
<categorias-container v-else :class="show_chismosa ? 'hide-below-1024' : ''"/>
|
||||||
<devoluciones-modal v-show="show_devoluciones"/>
|
<devoluciones-modal v-show="show_devoluciones"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-show="visible" class="column">
|
<div class="column">
|
||||||
<div ref="categorias"
|
<div ref="categorias"
|
||||||
class="columns is-multiline is-mobile"
|
class="columns is-multiline is-mobile"
|
||||||
:class="{ 'align-last-left': isLastRowIncomplete }">
|
:class="{ 'align-last-left': isLastRowIncomplete }">
|
||||||
|
@ -28,9 +28,6 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
...mapState('productos', ["categorias", "filtro"]),
|
...mapState('productos', ["categorias", "filtro"]),
|
||||||
...mapState('ui', ["show_chismosa"]),
|
...mapState('ui', ["show_chismosa"]),
|
||||||
visible() {
|
|
||||||
return this.filtro === null;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions('productos', ["seleccionarCategoria"]),
|
...mapActions('productos', ["seleccionarCategoria"]),
|
||||||
|
|
|
@ -85,7 +85,7 @@ export default {
|
||||||
...mapActions('pedido', ["getGrupoDeCompra", "crearPedido", "elegirPedido"]),
|
...mapActions('pedido', ["getGrupoDeCompra", "crearPedido", "elegirPedido"]),
|
||||||
...mapMutations("ui", ["toggleTags"]),
|
...mapMutations("ui", ["toggleTags"]),
|
||||||
async getPedidos(nombre) {
|
async getPedidos(nombre) {
|
||||||
const response = await axios.get('/api/subpedidos/',{
|
const response = await axios.get('/api/subpedidos',{
|
||||||
params: {
|
params: {
|
||||||
nombre: nombre,
|
nombre: nombre,
|
||||||
grupo_de_compra: this.grupo_de_compra.id,
|
grupo_de_compra: this.grupo_de_compra.id,
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
:requiere_notas="producto.requiere_notas"
|
:requiere_notas="producto.requiere_notas"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td class="has-text-right">{{ `${cantidad(producto.id) * producto.precio}` }}</td>
|
<td class="has-text-right">{{ `${producto.total}` }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-show="visible" class="column">
|
<div class="column">
|
||||||
<div ref="productos"
|
<div ref="productos"
|
||||||
class="columns is-multiline is-mobile"
|
class="columns is-multiline is-mobile"
|
||||||
:class="{ 'align-last-left': isLastRowIncomplete }">
|
:class="{ 'align-last-left': isLastRowIncomplete }">
|
||||||
|
@ -21,9 +21,6 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
...mapState('productos', ["productos", "filtro"]),
|
...mapState('productos', ["productos", "filtro"]),
|
||||||
...mapState('ui', ["show_chismosa"]),
|
...mapState('ui', ["show_chismosa"]),
|
||||||
visible() {
|
|
||||||
return this.filtro !== null;
|
|
||||||
},
|
|
||||||
miga: function () {
|
miga: function () {
|
||||||
return {
|
return {
|
||||||
nombre: this.filtro.valor,
|
nombre: this.filtro.valor,
|
||||||
|
|
10
resources/js/globals.d.ts
vendored
Normal file
10
resources/js/globals.d.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
Vue: typeof Vue;
|
||||||
|
Event: InstanceType<typeof Vue>;
|
||||||
|
axios: typeof axios;
|
||||||
|
bulmaToast: {
|
||||||
|
toast: (options: any) => void;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
5
resources/js/shims-vue.d.ts
vendored
Normal file
5
resources/js/shims-vue.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// resources/js/shims-vue.d.ts
|
||||||
|
declare module '*.vue' {
|
||||||
|
import Vue from '../../node_modules/vue/dist/vue.esm.js';
|
||||||
|
export default Vue;
|
||||||
|
}
|
53
resources/js/store/comunes.ts
Normal file
53
resources/js/store/comunes.ts
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
export interface ProductoResponse {
|
||||||
|
id: number,
|
||||||
|
fila: number,
|
||||||
|
nombre: string,
|
||||||
|
precio: number,
|
||||||
|
categoria: string,
|
||||||
|
bono: boolean,
|
||||||
|
created_at: Date,
|
||||||
|
updated_at: Date,
|
||||||
|
requiere_notas: boolean,
|
||||||
|
es_solidario: boolean,
|
||||||
|
pivot: {
|
||||||
|
subpedido_id: number,
|
||||||
|
producto_id: number,
|
||||||
|
notas: string,
|
||||||
|
cantidad: number,
|
||||||
|
total: number,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Producto {
|
||||||
|
id: number,
|
||||||
|
fila: number,
|
||||||
|
nombre: string,
|
||||||
|
precio: number,
|
||||||
|
categoria: string,
|
||||||
|
bono: boolean,
|
||||||
|
created_at: Date,
|
||||||
|
updated_at: Date,
|
||||||
|
requiere_notas: boolean,
|
||||||
|
es_solidario: boolean,
|
||||||
|
notas: string,
|
||||||
|
cantidad: number,
|
||||||
|
total: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function aplanarProducto(producto: ProductoResponse): Producto {
|
||||||
|
return {
|
||||||
|
id: producto.id,
|
||||||
|
fila: producto.fila,
|
||||||
|
nombre: producto.nombre,
|
||||||
|
precio: producto.precio,
|
||||||
|
categoria: producto.categoria,
|
||||||
|
bono: producto.bono,
|
||||||
|
created_at: producto.created_at,
|
||||||
|
updated_at: producto.updated_at,
|
||||||
|
requiere_notas: producto.requiere_notas,
|
||||||
|
es_solidario: producto.es_solidario,
|
||||||
|
notas: producto.pivot.notas,
|
||||||
|
cantidad: producto.pivot.cantidad,
|
||||||
|
total: producto.pivot.total,
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import Vue from 'vue';
|
import Vue from '../../../node_modules/vue/dist/vue.esm.js';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
|
import login from "./modules/login";
|
||||||
import admin from "./modules/admin";
|
import admin from "./modules/admin";
|
||||||
import comisiones from "./modules/comisiones";
|
import comisiones from "./modules/comisiones";
|
||||||
import login from "./modules/login";
|
|
||||||
import pedido from "./modules/pedido";
|
import pedido from "./modules/pedido";
|
||||||
import productos from "./modules/productos";
|
import productos from "./modules/productos";
|
||||||
import ui from "./modules/ui";
|
import ui from "./modules/ui";
|
||||||
|
@ -12,9 +12,9 @@ Vue.use(Vuex);
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
modules: {
|
modules: {
|
||||||
|
login,
|
||||||
admin,
|
admin,
|
||||||
comisiones,
|
comisiones,
|
||||||
login,
|
|
||||||
pedido,
|
pedido,
|
||||||
productos,
|
productos,
|
||||||
ui,
|
ui,
|
|
@ -1,29 +1,36 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { AdminState } from "./types";
|
||||||
|
import { aplanarProducto } from "../../comunes";
|
||||||
|
|
||||||
const state = {
|
const state: AdminState = {
|
||||||
lastFetch: null,
|
lastFetch: undefined,
|
||||||
grupo_de_compra_id: null,
|
grupo_de_compra_id: undefined,
|
||||||
nombre: null,
|
nombre: undefined,
|
||||||
devoluciones_habilitadas: null,
|
devoluciones_habilitadas: undefined,
|
||||||
pedidos: null,
|
pedidos: [],
|
||||||
total_a_recaudar: null,
|
total_a_recaudar: undefined,
|
||||||
total_sin_devoluciones: null,
|
total_sin_devoluciones: undefined,
|
||||||
total_barrial: null,
|
total_barrial: undefined,
|
||||||
total_devoluciones: null,
|
total_devoluciones: undefined,
|
||||||
total_de_pedido: null,
|
total_de_pedido: undefined,
|
||||||
total_a_transferir: null,
|
total_a_transferir: undefined,
|
||||||
total_transporte: null,
|
total_transporte: undefined,
|
||||||
cantidad_transporte: null,
|
cantidad_transporte: undefined,
|
||||||
saldo: null,
|
saldo: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setState(state, { grupo_de_compra }) {
|
setState(state: AdminState, { grupo_de_compra }) {
|
||||||
|
const aplanarProductos = (pedido) => {
|
||||||
|
pedido.productos = pedido.productos.map(p => aplanarProducto(p));
|
||||||
|
return pedido;
|
||||||
|
};
|
||||||
|
|
||||||
state.lastFetch = new Date();
|
state.lastFetch = new Date();
|
||||||
state.grupo_de_compra_id = grupo_de_compra.id;
|
state.grupo_de_compra_id = grupo_de_compra.id;
|
||||||
state.nombre = grupo_de_compra.nombre;
|
state.nombre = grupo_de_compra.nombre;
|
||||||
state.devoluciones_habilitadas = grupo_de_compra.devoluciones_habilitadas;
|
state.devoluciones_habilitadas = grupo_de_compra.devoluciones_habilitadas;
|
||||||
state.pedidos = grupo_de_compra.pedidos;
|
state.pedidos = grupo_de_compra.pedidos.map(p => aplanarProductos(p));
|
||||||
state.total_a_recaudar = grupo_de_compra.total_a_recaudar;
|
state.total_a_recaudar = grupo_de_compra.total_a_recaudar;
|
||||||
state.total_sin_devoluciones = grupo_de_compra.total_sin_devoluciones;
|
state.total_sin_devoluciones = grupo_de_compra.total_sin_devoluciones;
|
||||||
state.total_barrial = grupo_de_compra.total_barrial;
|
state.total_barrial = grupo_de_compra.total_barrial;
|
||||||
|
@ -41,8 +48,8 @@ const mutations = {
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
async getGrupoDeCompra({ commit }) {
|
async getGrupoDeCompra({ commit }) {
|
||||||
const response = await axios.get('/user/grupo_de_compra');
|
const { data } = await axios.get('/user/grupo_de_compra');
|
||||||
commit('setState', response.data);
|
commit('setState', data);
|
||||||
},
|
},
|
||||||
async setAprobacionPedido({ commit, dispatch }, { pedido_id, aprobacion }){
|
async setAprobacionPedido({ commit, dispatch }, { pedido_id, aprobacion }){
|
||||||
await axios.post("/api/admin/subpedidos/" + pedido_id + "/aprobacion", { aprobacion: aprobacion });
|
await axios.post("/api/admin/subpedidos/" + pedido_id + "/aprobacion", { aprobacion: aprobacion });
|
||||||
|
@ -59,7 +66,7 @@ const actions = {
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
grupoDeCompraDefinido() {
|
grupoDeCompraDefinido() {
|
||||||
return state.lastFetch !== null;
|
return state.lastFetch !== undefined;
|
||||||
},
|
},
|
||||||
barrio() {
|
barrio() {
|
||||||
return state.nombre?.replace('_admin','') ?? '';
|
return state.nombre?.replace('_admin','') ?? '';
|
33
resources/js/store/modules/admin/types.ts
Normal file
33
resources/js/store/modules/admin/types.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { Producto } from "../../comunes";
|
||||||
|
|
||||||
|
export interface AdminState extends Barrio {
|
||||||
|
lastFetch?: Date
|
||||||
|
}
|
||||||
|
export interface Barrio {
|
||||||
|
grupo_de_compra_id?: number,
|
||||||
|
nombre?: string,
|
||||||
|
devoluciones_habilitadas?: boolean,
|
||||||
|
pedidos: Pedido[],
|
||||||
|
total_a_recaudar?: number,
|
||||||
|
total_sin_devoluciones?: number,
|
||||||
|
total_barrial?: number,
|
||||||
|
total_devoluciones?: number,
|
||||||
|
total_de_pedido?: number,
|
||||||
|
total_a_transferir?: number,
|
||||||
|
total_transporte?: number,
|
||||||
|
cantidad_transporte?: number,
|
||||||
|
saldo?: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Pedido {
|
||||||
|
id: number,
|
||||||
|
nombre: string,
|
||||||
|
productos: Producto[],
|
||||||
|
aprobado: boolean,
|
||||||
|
total: number,
|
||||||
|
total_transporte: number,
|
||||||
|
cantidad_transporte: number,
|
||||||
|
total_sin_devoluciones: number,
|
||||||
|
devoluciones_total: number,
|
||||||
|
devoluciones_notas: string
|
||||||
|
}
|
|
@ -1,13 +1,14 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { ComisionesState } from "./types";
|
||||||
|
|
||||||
const state = {
|
const state: ComisionesState = {
|
||||||
lastFetch: undefined,
|
lastFetch: undefined,
|
||||||
grupos_de_compra: [],
|
grupos_de_compra: [],
|
||||||
parametros: [],
|
parametros: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setGruposDeCompra(state, { data }) {
|
setGruposDeCompra(state: ComisionesState, { data }) {
|
||||||
state.grupos_de_compra = data;
|
state.grupos_de_compra = data;
|
||||||
state.lastFetch = new Date();
|
state.lastFetch = new Date();
|
||||||
},
|
},
|
||||||
|
@ -20,17 +21,17 @@ const mutations = {
|
||||||
actualizarParametro(state, { parametro_id, valor }) {
|
actualizarParametro(state, { parametro_id, valor }) {
|
||||||
state.parametros.find(p => p.id === parametro_id).valor = valor;
|
state.parametros.find(p => p.id === parametro_id).valor = valor;
|
||||||
},
|
},
|
||||||
setSaldo(state, { gdc_id, saldo }) {
|
setSaldo(state: ComisionesState, { gdc_id, saldo }) {
|
||||||
const barrio = state.grupos_de_compra.find(gdc => gdc.id === gdc_id);
|
const barrio = state.grupos_de_compra.find(gdc => gdc.id === gdc_id);
|
||||||
const i = state.grupos_de_compra.indexOf(barrio);
|
const i = state.grupos_de_compra.indexOf(barrio!);
|
||||||
state.grupos_de_compra[i].saldo = saldo;
|
state.grupos_de_compra[i].saldo = saldo;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
async getGruposDeCompra({ commit }) {
|
async getGruposDeCompra({ commit }) {
|
||||||
const response = await axios.get('/api/grupos-de-compra/saldos');
|
const { data } = await axios.get('/api/grupos-de-compra/saldos');
|
||||||
commit('setGruposDeCompra', response.data);
|
commit('setGruposDeCompra', data);
|
||||||
},
|
},
|
||||||
async getParametros({ commit }) {
|
async getParametros({ commit }) {
|
||||||
const response = await axios.get('/api/parametros');
|
const response = await axios.get('/api/parametros');
|
10
resources/js/store/modules/comisiones/types.ts
Normal file
10
resources/js/store/modules/comisiones/types.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
export interface ComisionesState {
|
||||||
|
lastFetch?: Date,
|
||||||
|
grupos_de_compra: Barrio[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Barrio {
|
||||||
|
id: number,
|
||||||
|
nombre: string,
|
||||||
|
saldo: number,
|
||||||
|
}
|
|
@ -1,22 +1,23 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { Estilos, LoginState, OpcionLogin, Textos, UrlRol, UserRol } from "./types";
|
||||||
|
|
||||||
const state = {
|
const state: LoginState = {
|
||||||
regiones: null,
|
regiones: [],
|
||||||
grupos_de_compra: null,
|
grupos_de_compra: [],
|
||||||
region_elegida: null,
|
region_elegida: undefined,
|
||||||
grupo_de_compra_elegido: null,
|
grupo_de_compra_elegido: undefined,
|
||||||
rol: null,
|
rol: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setRegiones(state, { regiones }) {
|
setRegiones(state, { regiones }): void {
|
||||||
state.regiones = regiones;
|
state.regiones = regiones;
|
||||||
},
|
},
|
||||||
setRegionYBarrios(state, { region, grupos_de_compra }) {
|
setRegionYBarrios(state, { region, grupos_de_compra }): void {
|
||||||
state.region_elegida = region;
|
state.region_elegida = region;
|
||||||
state.grupos_de_compra = grupos_de_compra;
|
state.grupos_de_compra = grupos_de_compra;
|
||||||
},
|
},
|
||||||
selectGrupoDeCompra(state, { grupo_de_compra }) {
|
selectGrupoDeCompra(state, { grupo_de_compra }): void {
|
||||||
state.grupo_de_compra_elegido = grupo_de_compra;
|
state.grupo_de_compra_elegido = grupo_de_compra;
|
||||||
},
|
},
|
||||||
setRol(state, { rol }) {
|
setRol(state, { rol }) {
|
||||||
|
@ -25,29 +26,29 @@ const mutations = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
async getRegiones({ commit }) {
|
async getRegiones({ commit }): Promise<void> {
|
||||||
const response = await axios.get("/api/regiones");
|
const { data } = await axios.get("/api/regiones");
|
||||||
commit('setRegiones', { regiones: response.data });
|
commit('setRegiones', { regiones: data });
|
||||||
},
|
},
|
||||||
async selectRegion({ commit }, { region }) {
|
async selectRegion({ commit }, { region }): Promise<void> {
|
||||||
const response = await axios.get(`/api/regiones/${region}`);
|
const { data } = await axios.get(`/api/regiones/${region}`);
|
||||||
commit('setRegionYBarrios', { region: region, grupos_de_compra: response.data });
|
commit('setRegionYBarrios', { region: region, grupos_de_compra: data });
|
||||||
},
|
},
|
||||||
async getRol({ commit }) {
|
async getRol({ commit }): Promise<void> {
|
||||||
const response = await axios.get("/user/rol");
|
const { data }: UserRol = await axios.get("/user/rol");
|
||||||
commit('setRol', { rol: response.data.rol });
|
commit('setRol', { rol: data.rol });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
urlRol() {
|
urlRol(): UrlRol {
|
||||||
let split = window.location.pathname
|
let split = window.location.pathname
|
||||||
.replace('login', '')
|
.replace('login', '')
|
||||||
.split('/')
|
.split('/')
|
||||||
.filter(x => x.length);
|
.filter(x => x.length);
|
||||||
return split[0] ?? 'pedido';
|
return split[0] as UrlRol ?? 'pedido';
|
||||||
},
|
},
|
||||||
textos() {
|
textos(): Textos {
|
||||||
let rol = getters.urlRol();
|
let rol = getters.urlRol();
|
||||||
switch (rol) {
|
switch (rol) {
|
||||||
case 'pedido':
|
case 'pedido':
|
||||||
|
@ -86,7 +87,7 @@ const getters = {
|
||||||
throw new Error("Url inválida");
|
throw new Error("Url inválida");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
estilos() {
|
estilos(): Estilos {
|
||||||
let rol = getters.urlRol();
|
let rol = getters.urlRol();
|
||||||
switch (rol) {
|
switch (rol) {
|
||||||
case 'pedido':
|
case 'pedido':
|
||||||
|
@ -103,8 +104,8 @@ const getters = {
|
||||||
};
|
};
|
||||||
case 'comisiones':
|
case 'comisiones':
|
||||||
return {
|
return {
|
||||||
fondo: "has-background-grey",
|
fondo: "has-background-dark",
|
||||||
texto: "has-text-white",
|
texto: "has-text-danger-light",
|
||||||
botones: "danger-dark-button",
|
botones: "danger-dark-button",
|
||||||
};
|
};
|
||||||
case 'ollas':
|
case 'ollas':
|
||||||
|
@ -117,7 +118,7 @@ const getters = {
|
||||||
throw new Error("Url inválida");
|
throw new Error("Url inválida");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
opcionesLogin() {
|
opcionesLogin(): OpcionLogin[] {
|
||||||
let rol = getters.urlRol();
|
let rol = getters.urlRol();
|
||||||
switch (rol) {
|
switch (rol) {
|
||||||
case 'pedido':
|
case 'pedido':
|
43
resources/js/store/modules/login/types.ts
Normal file
43
resources/js/store/modules/login/types.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
export interface LoginState {
|
||||||
|
regiones: string[],
|
||||||
|
grupos_de_compra: Barrio[],
|
||||||
|
region_elegida?: string,
|
||||||
|
grupo_de_compra_elegido?: Barrio,
|
||||||
|
rol?: Rol,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Textos {
|
||||||
|
titulo: string,
|
||||||
|
subtitlo: string,
|
||||||
|
password: string,
|
||||||
|
ayuda: string,
|
||||||
|
label: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Estilos {
|
||||||
|
fondo: string,
|
||||||
|
texto: string,
|
||||||
|
botones: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OpcionLogin {
|
||||||
|
nombre: string,
|
||||||
|
href: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Barrio {
|
||||||
|
id: number,
|
||||||
|
nombre: string,
|
||||||
|
region: string,
|
||||||
|
created_at: Date,
|
||||||
|
updated_at: Date,
|
||||||
|
devoluciones_habilitadas: boolean,
|
||||||
|
saldo: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserRol {
|
||||||
|
rol: Rol
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UrlRol = 'pedido' | 'admin' | 'comisiones' | 'ollas';
|
||||||
|
export type Rol = 'barrio' | 'admin_barrio' | 'comision' | 'ollas';
|
|
@ -1,30 +1,32 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { PedidoState } from "./types";
|
||||||
|
import { aplanarProducto } from "../../comunes";
|
||||||
|
|
||||||
const state = {
|
const state: PedidoState = {
|
||||||
lastFetch: null,
|
lastFetch: undefined,
|
||||||
grupo_de_compra: null,
|
grupo_de_compra: undefined,
|
||||||
pedido_id: 0,
|
pedido_id: undefined,
|
||||||
nombre: "",
|
nombre: undefined,
|
||||||
productos: [],
|
productos: [],
|
||||||
aprobado: false,
|
aprobado: undefined,
|
||||||
total: 0,
|
total: undefined,
|
||||||
total_transporte: 0,
|
total_transporte: undefined,
|
||||||
cantidad_transporte: 0,
|
cantidad_transporte: undefined,
|
||||||
total_sin_devoluciones: 0,
|
total_sin_devoluciones: undefined,
|
||||||
devoluciones_total: 0,
|
devoluciones_total: undefined,
|
||||||
devoluciones_notas: "",
|
devoluciones_notas: undefined,
|
||||||
cantidad_de_ollas: 0,
|
cantidad_de_ollas: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setGrupoDeCompra(state, grupo_de_compra) {
|
setGrupoDeCompra(state: PedidoState, grupo_de_compra) {
|
||||||
state.grupo_de_compra = grupo_de_compra;
|
state.grupo_de_compra = grupo_de_compra;
|
||||||
},
|
},
|
||||||
setPedido(state, pedido) {
|
setPedido(state: PedidoState, pedido) {
|
||||||
state.lastFetch = new Date();
|
state.lastFetch = new Date();
|
||||||
state.pedido_id = pedido.id;
|
state.pedido_id = pedido.id;
|
||||||
state.nombre = pedido.nombre;
|
state.nombre = pedido.nombre;
|
||||||
state.productos = pedido.productos;
|
state.productos = pedido.productos.map(p => aplanarProducto(p));
|
||||||
state.aprobado = pedido.aprobado;
|
state.aprobado = pedido.aprobado;
|
||||||
state.total = Number.parseFloat(pedido.total.replace(',',''));
|
state.total = Number.parseFloat(pedido.total.replace(',',''));
|
||||||
state.total_transporte = Number.parseInt(pedido.total_transporte?.replace(',',''));
|
state.total_transporte = Number.parseInt(pedido.total_transporte?.replace(',',''));
|
||||||
|
@ -47,18 +49,18 @@ const mutations = {
|
||||||
delete state.devoluciones_total;
|
delete state.devoluciones_total;
|
||||||
delete state.devoluciones_notas;
|
delete state.devoluciones_notas;
|
||||||
},
|
},
|
||||||
reset(state) {
|
reset(state: PedidoState) {
|
||||||
state.lastFetch = null;
|
state.lastFetch = undefined;
|
||||||
state.pedido_id = null;
|
state.pedido_id = undefined;
|
||||||
state.nombre = null;
|
state.nombre = undefined;
|
||||||
state.productos = null;
|
state.productos = [];
|
||||||
state.aprobado = null;
|
state.aprobado = undefined;
|
||||||
state.total = null;
|
state.total = undefined;
|
||||||
state.total_transporte = null;
|
state.total_transporte = undefined;
|
||||||
state.cantidad_transporte = null;
|
state.cantidad_transporte = undefined;
|
||||||
state.total_sin_devoluciones = null;
|
state.total_sin_devoluciones = undefined;
|
||||||
state.devoluciones_total = null;
|
state.devoluciones_total = undefined;
|
||||||
state.devoluciones_notas = null;
|
state.devoluciones_notas = undefined;
|
||||||
},
|
},
|
||||||
setCantidadOllas(state, { cantidad }) {
|
setCantidadOllas(state, { cantidad }) {
|
||||||
if (cantidad >= 0)
|
if (cantidad >= 0)
|
||||||
|
@ -68,8 +70,8 @@ const mutations = {
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
async getGrupoDeCompra({ commit }) {
|
async getGrupoDeCompra({ commit }) {
|
||||||
const response = await axios.get('/user/grupo_de_compra');
|
const { data } = await axios.get('/user/grupo_de_compra');
|
||||||
commit('setGrupoDeCompra', response.data.grupo_de_compra);
|
commit('setGrupoDeCompra', data.grupo_de_compra);
|
||||||
},
|
},
|
||||||
async guardarSesion(_, { pedido_id }) {
|
async guardarSesion(_, { pedido_id }) {
|
||||||
const body = { id: pedido_id };
|
const body = { id: pedido_id };
|
||||||
|
@ -77,31 +79,35 @@ const actions = {
|
||||||
},
|
},
|
||||||
async crearPedido({ commit, dispatch }, { nombre, grupo_de_compra_id, tipo_id }) {
|
async crearPedido({ commit, dispatch }, { nombre, grupo_de_compra_id, tipo_id }) {
|
||||||
const body = { nombre, grupo_de_compra_id, tipo_id };
|
const body = { nombre, grupo_de_compra_id, tipo_id };
|
||||||
const response = await axios.post("/api/subpedidos", body);
|
const { data } = await axios.post("/api/subpedidos", body);
|
||||||
dispatch("guardarSesion", { pedido_id: response.data.data.id});
|
dispatch("guardarSesion", { pedido_id: data.data.id});
|
||||||
commit('setPedido', response.data.data);
|
commit('setPedido', data.data);
|
||||||
},
|
},
|
||||||
async elegirPedido({ commit, dispatch }, { pedido_id }) {
|
async elegirPedido({ commit, dispatch }, { pedido_id }) {
|
||||||
const response = await axios.get(`/api/subpedidos/${pedido_id}`);
|
const { data } = await axios.get(`/api/subpedidos/${pedido_id}`);
|
||||||
const body = { pedido_id: pedido_id};
|
dispatch("guardarSesion", { pedido_id: pedido_id})
|
||||||
dispatch("guardarSesion", body)
|
commit('setPedido', data.data);
|
||||||
commit('setPedido', response.data.data);
|
|
||||||
},
|
},
|
||||||
async modificarChismosa({ commit, dispatch }, { producto_id, cantidad, notas }) {
|
async modificarChismosa({ commit, dispatch }, { producto_id, cantidad, notas }) {
|
||||||
const body = { cantidad: cantidad, producto_id: producto_id, notas: notas };
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.post("/api/subpedidos/" + state.pedido_id + "/sync", body);
|
const { data } = await axios.post("/api/subpedidos/" + state.pedido_id + "/sync", {
|
||||||
commit('setPedido', response.data.data);
|
cantidad: cantidad,
|
||||||
|
producto_id: producto_id,
|
||||||
|
notas: notas,
|
||||||
|
});
|
||||||
|
commit('setPedido', data.data);
|
||||||
dispatch("ui/toast", { mensaje: 'Pedido modificado con éxito' }, { root: true });
|
dispatch("ui/toast", { mensaje: 'Pedido modificado con éxito' }, { root: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch("ui/error", { error: error }, { root: true });
|
dispatch("ui/error", { error: error }, { root: true });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async modificarDevoluciones({ commit, dispatch }, { monto, notas }) {
|
async modificarDevoluciones({ commit, dispatch }, { monto, notas }) {
|
||||||
const body = { total: monto, notas: notas };
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.post("api/subpedidos/" + state.pedido_id + "/sync_devoluciones", body);
|
const { data } = await axios.post("api/subpedidos/" + state.pedido_id + "/sync_devoluciones", {
|
||||||
commit('setPedido', response.data.data);
|
total: monto,
|
||||||
|
notas: notas,
|
||||||
|
});
|
||||||
|
commit('setPedido', data.data);
|
||||||
dispatch("ui/toast", { mensaje: 'Devoluciones modificadas con éxito' }, { root: true });
|
dispatch("ui/toast", { mensaje: 'Devoluciones modificadas con éxito' }, { root: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch("ui/error", { error: error }, { root: true });
|
dispatch("ui/error", { error: error }, { root: true });
|
||||||
|
@ -121,16 +127,16 @@ const actions = {
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
pedidoDefinido() {
|
pedidoDefinido() {
|
||||||
return state.lastFetch !== null;
|
return state.lastFetch !== undefined;
|
||||||
},
|
},
|
||||||
enChismosa() {
|
enChismosa() {
|
||||||
return ((producto_id) => state.productos.some(p => p.id === producto_id));
|
return ((producto_id) => state.productos.some(p => p.id === producto_id));
|
||||||
},
|
},
|
||||||
cantidad() {
|
cantidad() {
|
||||||
return ((producto_id) => state.productos.find(p => p.id === producto_id)?.pivot.cantidad ?? 0);
|
return ((producto_id) => state.productos.find(p => p.id === producto_id)?.cantidad ?? 0);
|
||||||
},
|
},
|
||||||
notas() {
|
notas() {
|
||||||
return ((producto_id) => state.productos.find(p => p.id === producto_id)?.pivot.notas ?? "");
|
return ((producto_id) => state.productos.find(p => p.id === producto_id)?.notas ?? "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
resources/js/store/modules/pedido/types.ts
Normal file
22
resources/js/store/modules/pedido/types.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { Producto } from "../../comunes";
|
||||||
|
|
||||||
|
export interface PedidoState {
|
||||||
|
lastFetch?: Date,
|
||||||
|
grupo_de_compra?: Barrio,
|
||||||
|
pedido_id?: number,
|
||||||
|
nombre?: string,
|
||||||
|
productos: Producto[],
|
||||||
|
aprobado?: boolean,
|
||||||
|
total?: number,
|
||||||
|
total_transporte?: number,
|
||||||
|
cantidad_transporte?: number,
|
||||||
|
total_sin_devoluciones?: number,
|
||||||
|
devoluciones_total?: number,
|
||||||
|
devoluciones_notas?: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Barrio {
|
||||||
|
id: number,
|
||||||
|
nombre: string,
|
||||||
|
devoluciones_habilitadas: boolean,
|
||||||
|
}
|
|
@ -1,22 +1,23 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { ProductosState } from "./types";
|
||||||
|
|
||||||
const state = {
|
const state: ProductosState = {
|
||||||
lastFetch: null,
|
lastFetch: undefined,
|
||||||
categorias: [],
|
categorias: [],
|
||||||
productos: [],
|
productos: [],
|
||||||
filtro: null,
|
filtro: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setCategorias(state, categorias) {
|
setCategorias(state: ProductosState, categorias) {
|
||||||
state.lastFetch = new Date();
|
state.lastFetch = new Date();
|
||||||
state.categorias = categorias;
|
state.categorias = categorias;
|
||||||
},
|
},
|
||||||
setProductos(state, productos) {
|
setProductos(state: ProductosState, productos) {
|
||||||
state.lastFetch = new Date();
|
state.lastFetch = new Date();
|
||||||
state.productos = productos;
|
state.productos = productos;
|
||||||
},
|
},
|
||||||
setFiltro(state, filtro) {
|
setFiltro(state: ProductosState, filtro) {
|
||||||
state.lastFetch = new Date();
|
state.lastFetch = new Date();
|
||||||
state.filtro = filtro;
|
state.filtro = filtro;
|
||||||
},
|
},
|
||||||
|
@ -28,23 +29,29 @@ const actions = {
|
||||||
dispatch('getProductos');
|
dispatch('getProductos');
|
||||||
},
|
},
|
||||||
async getCategorias({ commit }) {
|
async getCategorias({ commit }) {
|
||||||
const response = await axios.get('api/categorias');
|
const { data } = await axios.get('api/categorias');
|
||||||
commit('setCategorias', response.data);
|
commit('setCategorias', data);
|
||||||
},
|
},
|
||||||
async getProductos({ commit }) {
|
async getProductos({ commit }) {
|
||||||
const response = await axios.get("/api/productos");
|
const { data } = await axios.get("/api/productos");
|
||||||
commit('setFiltro', null);
|
commit('setFiltro', undefined);
|
||||||
commit('setProductos', response.data.data);
|
commit('setProductos', data.data);
|
||||||
},
|
},
|
||||||
async seleccionarCategoria({ dispatch }, { categoria }) {
|
async seleccionarCategoria({ dispatch }, { categoria }) {
|
||||||
dispatch('filtrarProductos', { filtro: "categoria", valor: categoria });
|
dispatch('filtrarProductos', { filtro: "categoria", valor: categoria });
|
||||||
},
|
},
|
||||||
async filtrarProductos({ commit }, { filtro, valor }) {
|
async filtrarProductos({ commit }, { filtro, valor }) {
|
||||||
const response = await axios.get("/api/productos", {
|
const { data } = await axios.get("/api/productos", {
|
||||||
params: { [filtro]: valor }
|
params: { [filtro]: valor }
|
||||||
});
|
});
|
||||||
commit('setFiltro', { clave: filtro, valor: valor });
|
commit('setFiltro', { clave: filtro, valor: valor });
|
||||||
commit('setProductos', response.data.data);
|
commit('setProductos', data.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getters = {
|
||||||
|
mostrarProductos() {
|
||||||
|
return state.filtro !== undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,4 +60,5 @@ export default {
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions,
|
actions,
|
||||||
|
getters,
|
||||||
};
|
};
|
21
resources/js/store/modules/productos/types.ts
Normal file
21
resources/js/store/modules/productos/types.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
export interface ProductosState {
|
||||||
|
lastFetch?: Date,
|
||||||
|
categorias: string[],
|
||||||
|
productos: Producto[],
|
||||||
|
filtro?: Filtro,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Producto {
|
||||||
|
id: number,
|
||||||
|
nombre: string,
|
||||||
|
precio: number,
|
||||||
|
categoria: string,
|
||||||
|
economia_solidaria: boolean,
|
||||||
|
nacional: boolean,
|
||||||
|
requiere_notas: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Filtro {
|
||||||
|
clave: string,
|
||||||
|
valor: string,
|
||||||
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
const state = {
|
import { UiState } from "./types";
|
||||||
|
|
||||||
|
const state: UiState = {
|
||||||
show_chismosa: false,
|
show_chismosa: false,
|
||||||
show_devoluciones: false,
|
show_devoluciones: false,
|
||||||
show_tags: true,
|
show_tags: true,
|
||||||
burger_activa: false,
|
burger_activa: false,
|
||||||
tags_interactuada: false,
|
tags_interactuada: false,
|
||||||
migas: [{ nombre: 'Pedidos', action: 'pedido/resetear' }],
|
migas: [{ nombre: 'Pedidos', action: 'pedido/resetear' }],
|
||||||
canasta_actual: null,
|
canasta_actual: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
|
@ -29,7 +31,7 @@ const mutations = {
|
||||||
state.migas.push(miga);
|
state.migas.push(miga);
|
||||||
},
|
},
|
||||||
popUltimaBusqueda(state) {
|
popUltimaBusqueda(state) {
|
||||||
if (!state.migas.at(-1).action)
|
if (!state.migas.at(-1)?.action)
|
||||||
state.migas.pop();
|
state.migas.pop();
|
||||||
},
|
},
|
||||||
reset(state) {
|
reset(state) {
|
||||||
|
@ -43,8 +45,8 @@ const mutations = {
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
async getCanastaActual({ commit }) {
|
async getCanastaActual({ commit }) {
|
||||||
const response = await axios.get('/api/canasta-actual');
|
const { data } = await axios.get('/api/canasta-actual');
|
||||||
commit("setCanastaActual", { canasta: response.data });
|
commit("setCanastaActual", { canasta: data });
|
||||||
},
|
},
|
||||||
clickMiga({ dispatch }, { miga }) {
|
clickMiga({ dispatch }, { miga }) {
|
||||||
let dropWhile = (array, pred) => {
|
let dropWhile = (array, pred) => {
|
20
resources/js/store/modules/ui/types.ts
Normal file
20
resources/js/store/modules/ui/types.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
export interface UiState {
|
||||||
|
show_chismosa: boolean,
|
||||||
|
show_devoluciones: boolean,
|
||||||
|
show_tags: boolean,
|
||||||
|
tags_interactuada: boolean,
|
||||||
|
migas: Miga[],
|
||||||
|
canasta_actual?: DatosCanasta,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Miga {
|
||||||
|
nombre: string,
|
||||||
|
action: string,
|
||||||
|
arguments?: { [key: string]: string },
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DatosCanasta {
|
||||||
|
nombre: string,
|
||||||
|
fecha: Date,
|
||||||
|
}
|
4
resources/sass/app.scss
vendored
4
resources/sass/app.scss
vendored
|
@ -4,8 +4,8 @@
|
||||||
// Variables
|
// Variables
|
||||||
@import 'variables';
|
@import 'variables';
|
||||||
|
|
||||||
@import 'bulma';
|
@import '../../node_modules/bulma/bulma.sass';
|
||||||
@import '~bulma-switch';
|
@import '../../node_modules/bulma-switch/src/sass/index.sass';
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>{{ config('app.name', 'Pedidos del MPS') }}</title>
|
<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="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
|
||||||
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
|
@vite(['resources/sass/app.scss', 'resources/js/app.ts'])
|
||||||
<script src="https://kit.fontawesome.com/9235d1c676.js" crossorigin="anonymous"></script>
|
<script src="https://kit.fontawesome.com/9235d1c676.js" crossorigin="anonymous"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -15,6 +15,5 @@
|
||||||
<app-login></app-login>
|
<app-login></app-login>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<script src="{{ mix('js/app.js') }}" defer></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<!-- Fonts -->
|
<!-- Fonts -->
|
||||||
<script src="https://kit.fontawesome.com/9235d1c676.js" crossorigin="anonymous"></script>
|
<script src="https://kit.fontawesome.com/9235d1c676.js" crossorigin="anonymous"></script>
|
||||||
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
|
@vite(['resources/sass/app.scss', 'resources/js/app.ts'])
|
||||||
@yield('stylesheets')
|
@yield('stylesheets')
|
||||||
</head>
|
</head>
|
||||||
<body class="has-navbar-fixed-top">
|
<body class="has-navbar-fixed-top">
|
||||||
|
@ -28,8 +28,6 @@
|
||||||
@yield('content')
|
@yield('content')
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
<!-- Scripts -->
|
|
||||||
<script src="{{ mix('js/app.js') }}" defer></script>
|
|
||||||
@yield('scripts')
|
@yield('scripts')
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -51,7 +51,7 @@ Route::get('/comisiones/login', 'ComisionesController@show')->name('comisiones.l
|
||||||
Route::middleware(['auth', 'role:comision'])->group( function() {
|
Route::middleware(['auth', 'role:comision'])->group( function() {
|
||||||
Route::get('/comisiones', 'RouteController@main')->name('comisiones');
|
Route::get('/comisiones', 'RouteController@main')->name('comisiones');
|
||||||
Route::get('/comisiones/pedidos/descargar', 'ComisionesController@descargarPedidos')->name('comisiones.pedidos.descargar');
|
Route::get('/comisiones/pedidos/descargar', 'ComisionesController@descargarPedidos')->name('comisiones.pedidos.descargar');
|
||||||
Route::get('/comisiones/pedidos/notas', 'ComisionesController@descargarNotas')->name('comisiones.pedidos.descargar');
|
Route::get('/comisiones/pedidos/notas', 'ComisionesController@descargarNotas')->name('comisiones.pedidos.notas');
|
||||||
Route::get('/comisiones/pedidos/pdf', 'ComisionesController@pdf')->name('comisiones.pedidos.pdf');
|
Route::get('/comisiones/pedidos/pdf', 'ComisionesController@pdf')->name('comisiones.pedidos.pdf');
|
||||||
Route::get('/comisiones/pedidos/ollas', 'ComisionesController@descargarPedidosDeOllas')->name('comisiones.pedidos.ollas');
|
Route::get('/comisiones/pedidos/ollas', 'ComisionesController@descargarPedidosDeOllas')->name('comisiones.pedidos.ollas');
|
||||||
Route::get('/comisiones/canasta/ejemplo', 'ComisionesController@descargarCanastaEjemplo')->name('comisiones.canasta.ejemplo');
|
Route::get('/comisiones/canasta/ejemplo', 'ComisionesController@descargarCanastaEjemplo')->name('comisiones.canasta.ejemplo');
|
||||||
|
|
17
tsconfig.json
Normal file
17
tsconfig.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "esnext",
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"lib": ["esnext", "dom"],
|
||||||
|
"jsx": "preserve",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"types": ["vite/client"]
|
||||||
|
},
|
||||||
|
"include": ["resources/js/**/*", "resources/**/*.vue"]
|
||||||
|
}
|
23
vite.config.mjs
Normal file
23
vite.config.mjs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import vue from '@vitejs/plugin-vue2';
|
||||||
|
import laravel from 'laravel-vite-plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
server: {
|
||||||
|
host: '0.0.0.0',
|
||||||
|
port: 5173,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
laravel({
|
||||||
|
input: ['resources/js/app.ts', 'resources/sass/app.scss'],
|
||||||
|
refresh: true,
|
||||||
|
}),
|
||||||
|
vue(),
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': '/resources/js',
|
||||||
|
'vue$': 'vue/dist/vue.esm.js',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
16
webpack.mix.js
vendored
16
webpack.mix.js
vendored
|
@ -1,16 +0,0 @@
|
||||||
const mix = require('laravel-mix');
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Mix Asset Management
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Mix provides a clean, fluent API for defining some Webpack build steps
|
|
||||||
| for your Laravel application. By default, we are compiling the Sass
|
|
||||||
| file for the application as well as bundling up all the JS files.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
mix.js('resources/js/app.js', 'public/js')
|
|
||||||
.sass('resources/sass/app.scss', 'public/css')
|
|
||||||
.version();
|
|
Loading…
Add table
Reference in a new issue