first commit
This commit is contained in:
commit
839bbbac82
|
|
@ -0,0 +1,82 @@
|
||||||
|
upstream fastcgi_backend {
|
||||||
|
server unix:/run/php/php8.1-fpm.sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
#server {
|
||||||
|
|
||||||
|
# listen 8080;
|
||||||
|
#server_name mag1.kentest.xyz;
|
||||||
|
#server_name ipsupply.com.au www.ipsupply.com.au;
|
||||||
|
# server_name prology.net;
|
||||||
|
# set $MAGE_ROOT /var/www/html/ipsupply_prod;
|
||||||
|
# set $MAGE_RUN_TYPE website;
|
||||||
|
# set $MAGE_MODE developer;
|
||||||
|
|
||||||
|
# include /var/www/html/ipsupply_prod/nginx.conf.sample;
|
||||||
|
#}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------
|
||||||
|
server {
|
||||||
|
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
# server_name mag1.kentest.xyz;
|
||||||
|
|
||||||
|
#return 301 https://mag1.kentest.xyz$request_uri;
|
||||||
|
server_name gtc.nswteam.net;
|
||||||
|
root /var/www/html/gtc/public; # Path to your Laravel public directory
|
||||||
|
|
||||||
|
index index.php index.html index.htm;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.php?$query_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ \.php$ {
|
||||||
|
try_files $uri /index.php =404;
|
||||||
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||||
|
fastcgi_pass fastcgi_backend; # Adjust the PHP version and socket path as needed
|
||||||
|
fastcgi_index index.php;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ /\.ht {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#server {
|
||||||
|
|
||||||
|
# listen 443 ssl http2;
|
||||||
|
# listen [::]:443 ssl http2;
|
||||||
|
# server_name mag1.kentest.xyz;
|
||||||
|
|
||||||
|
#ssl on;
|
||||||
|
# ssl_certificate /etc/letsencrypt/live/mag1.kentest.xyz/fullchain.pem;
|
||||||
|
# ssl_certificate_key /etc/letsencrypt/live/mag1.kentest.xyz/privkey.pem;
|
||||||
|
##
|
||||||
|
# set $MAGE_ROOT /var/www/html/ipsupply_prod;
|
||||||
|
# include /var/www/html/ipsupply_prod/nginx.conf.sample;
|
||||||
|
##
|
||||||
|
# location / {
|
||||||
|
#try_files $uri $uri/ /index.php$is_args$args;
|
||||||
|
# proxy_pass http://127.0.0.1:80;
|
||||||
|
# proxy_set_header Host $host;
|
||||||
|
# proxy_set_header X-Forwarded-Host $http_host;
|
||||||
|
# proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
# proxy_set_header Ssl-Offloaded "1";
|
||||||
|
# proxy_set_header X-Forwarded-Port 443;
|
||||||
|
# proxy_set_header X-Forwarded-Proto https;
|
||||||
|
# proxy_set_header X-Forwarded-Ssl on;
|
||||||
|
# proxy_buffer_size 128k;
|
||||||
|
# proxy_buffers 4 256k;
|
||||||
|
# proxy_busy_buffers_size 256k;
|
||||||
|
# fastcgi_buffer_size 32k;
|
||||||
|
# fastcgi_buffers 4 32k;
|
||||||
|
# }
|
||||||
|
|
||||||
|
#}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
<VirtualHost *:80>
|
||||||
|
DocumentRoot "/var/www/html/public"
|
||||||
|
<Directory "/var/www/html/public">
|
||||||
|
Options Indexes FollowSymLinks
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
</VirtualHost>
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[docker-compose.yml]
|
||||||
|
indent_size = 4
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
APP_NAME=Payment
|
||||||
|
APP_ENV=production
|
||||||
|
APP_KEY=base64:Tj1+yM1P63LHIkEX0tNUW1wK9ZrGu8uenPhyhP1knBo=
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_URL=https://payment.nswteam.net
|
||||||
|
ADMIN_URL=https://adminpayment.nswteam.net
|
||||||
|
|
||||||
|
LOG_CHANNEL=stack
|
||||||
|
LOG_DEPRECATIONS_CHANNEL=null
|
||||||
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
|
DB_CONNECTION=mysql
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_DATABASE=gtc
|
||||||
|
DB_USERNAME=worm
|
||||||
|
DB_PASSWORD=123456
|
||||||
|
|
||||||
|
BROADCAST_DRIVER=log
|
||||||
|
CACHE_DRIVER=redis
|
||||||
|
FILESYSTEM_DISK=local
|
||||||
|
QUEUE_CONNECTION=sync
|
||||||
|
SESSION_DRIVER=file
|
||||||
|
SESSION_LIFETIME=120
|
||||||
|
|
||||||
|
MEMCACHED_HOST=127.0.0.1
|
||||||
|
|
||||||
|
REDIS_HOST=127.0.0.1
|
||||||
|
REDIS_PASSWORD=null
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
MAIL_MAILER=smtp
|
||||||
|
MAIL_HOST=mailpit
|
||||||
|
MAIL_PORT=1025
|
||||||
|
MAIL_USERNAME=null
|
||||||
|
MAIL_PASSWORD=null
|
||||||
|
MAIL_ENCRYPTION=null
|
||||||
|
MAIL_FROM_ADDRESS="hello@example.com"
|
||||||
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID=
|
||||||
|
AWS_SECRET_ACCESS_KEY=
|
||||||
|
AWS_DEFAULT_REGION=us-east-1
|
||||||
|
AWS_BUCKET=
|
||||||
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||||
|
|
||||||
|
PUSHER_APP_ID=
|
||||||
|
PUSHER_APP_KEY=
|
||||||
|
PUSHER_APP_SECRET=
|
||||||
|
PUSHER_HOST=
|
||||||
|
PUSHER_PORT=443
|
||||||
|
PUSHER_SCHEME=https
|
||||||
|
PUSHER_APP_CLUSTER=mt1
|
||||||
|
|
||||||
|
VITE_APP_NAME="${APP_NAME}"
|
||||||
|
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||||
|
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||||
|
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||||
|
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||||
|
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||||
|
|
||||||
|
# Info PAYAPAL
|
||||||
|
# @auth: Joseph
|
||||||
|
# @since: 26/12/2023
|
||||||
|
#
|
||||||
|
# sandbox personal
|
||||||
|
# EMAIL=sb-krlhv27694898@personal.example.com
|
||||||
|
# PASSWORD=8!P_^{/q
|
||||||
|
#
|
||||||
|
# sandbox business
|
||||||
|
# EMAIL=sb-ufjry27694755@business.example.com
|
||||||
|
# PASSWORD=k"pS1-WE
|
||||||
|
PAYPAL_SANDBOX_CLIENT_ID=Aerhn4xoYaNeoOCUZqHRjOjV1nwpd6YsSItupNNhYEuRF2k_Jm9ID0SfAb4fey-1BFto1Evw2Fzw91SA
|
||||||
|
PAYPAL_SANDBOX_CLIENT_SECRET=EJuwDMec6pMR3ULuSd36lHHw38OlPtjBUEvDUl_uJ6_bWwcvcGvezJp3E6QSmKLlBMoua8GcQiUaqlvx
|
||||||
|
PAYPAL_MODE=sandbox
|
||||||
|
|
||||||
|
SN_SERVER_TOKEN="Work1234"
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
APP_PORT=8000
|
||||||
|
APP_NAME=Laravel
|
||||||
|
APP_ENV=local
|
||||||
|
APP_KEY=
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_URL=http://localhost:${APP_PORT}
|
||||||
|
ADMIN_URL=http://localhost:5173
|
||||||
|
|
||||||
|
LOG_CHANNEL=stack
|
||||||
|
LOG_DEPRECATIONS_CHANNEL=null
|
||||||
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
|
DB_CONNECTION=mysql
|
||||||
|
# localhost for docker
|
||||||
|
DB_HOST=localhost
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_DATABASE=payment
|
||||||
|
DB_USERNAME=laravel
|
||||||
|
DB_PASSWORD=laravel
|
||||||
|
|
||||||
|
BROADCAST_DRIVER=log
|
||||||
|
CACHE_DRIVER=file
|
||||||
|
FILESYSTEM_DISK=local
|
||||||
|
QUEUE_CONNECTION=sync
|
||||||
|
SESSION_DRIVER=file
|
||||||
|
SESSION_LIFETIME=120
|
||||||
|
|
||||||
|
MEMCACHED_HOST=127.0.0.1
|
||||||
|
|
||||||
|
REDIS_HOST=127.0.0.1
|
||||||
|
REDIS_PASSWORD=null
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
MAIL_MAILER=smtp
|
||||||
|
MAIL_HOST=mailhog
|
||||||
|
MAIL_PORT=1025
|
||||||
|
MAIL_USERNAME=null
|
||||||
|
MAIL_PASSWORD=null
|
||||||
|
MAIL_ENCRYPTION=null
|
||||||
|
MAIL_FROM_ADDRESS="naviclound@apachtech.io"
|
||||||
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID=
|
||||||
|
AWS_SECRET_ACCESS_KEY=
|
||||||
|
AWS_DEFAULT_REGION=us-east-1
|
||||||
|
AWS_BUCKET=
|
||||||
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||||
|
|
||||||
|
PUSHER_APP_ID=
|
||||||
|
PUSHER_APP_KEY=
|
||||||
|
PUSHER_APP_SECRET=
|
||||||
|
PUSHER_HOST=
|
||||||
|
PUSHER_PORT=443
|
||||||
|
PUSHER_SCHEME=https
|
||||||
|
PUSHER_APP_CLUSTER=mt1
|
||||||
|
|
||||||
|
VITE_APP_NAME="${APP_NAME}"
|
||||||
|
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||||
|
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||||
|
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||||
|
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||||
|
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||||
|
|
||||||
|
SN_SERVER_TOKEN="Work1234"
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
APP_NAME=Laravel
|
||||||
|
APP_ENV=local
|
||||||
|
APP_KEY=
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_URL=http://localhost:8000
|
||||||
|
ADMIN_URL=http://localhost:5173
|
||||||
|
|
||||||
|
LOG_CHANNEL=stack
|
||||||
|
LOG_DEPRECATIONS_CHANNEL=null
|
||||||
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
|
DB_CONNECTION=mysql
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_DATABASE=laravel
|
||||||
|
DB_USERNAME=root
|
||||||
|
DB_PASSWORD=
|
||||||
|
|
||||||
|
BROADCAST_DRIVER=log
|
||||||
|
CACHE_DRIVER=file
|
||||||
|
FILESYSTEM_DISK=local
|
||||||
|
QUEUE_CONNECTION=sync
|
||||||
|
SESSION_DRIVER=file
|
||||||
|
SESSION_LIFETIME=120
|
||||||
|
|
||||||
|
MEMCACHED_HOST=127.0.0.1
|
||||||
|
|
||||||
|
REDIS_HOST=127.0.0.1
|
||||||
|
REDIS_PASSWORD=null
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
MAIL_MAILER=smtp
|
||||||
|
MAIL_HOST=mailpit
|
||||||
|
MAIL_PORT=1025
|
||||||
|
MAIL_USERNAME=null
|
||||||
|
MAIL_PASSWORD=null
|
||||||
|
MAIL_ENCRYPTION=null
|
||||||
|
MAIL_FROM_ADDRESS="hello@example.com"
|
||||||
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID=
|
||||||
|
AWS_SECRET_ACCESS_KEY=
|
||||||
|
AWS_DEFAULT_REGION=us-east-1
|
||||||
|
AWS_BUCKET=
|
||||||
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||||
|
|
||||||
|
PUSHER_APP_ID=
|
||||||
|
PUSHER_APP_KEY=
|
||||||
|
PUSHER_APP_SECRET=
|
||||||
|
PUSHER_HOST=
|
||||||
|
PUSHER_PORT=443
|
||||||
|
PUSHER_SCHEME=https
|
||||||
|
PUSHER_APP_CLUSTER=mt1
|
||||||
|
|
||||||
|
VITE_APP_NAME="${APP_NAME}"
|
||||||
|
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||||
|
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||||
|
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||||
|
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||||
|
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||||
|
|
||||||
|
SN_SERVER_TOKEN="Work1234"
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
* text=auto eol=lf
|
||||||
|
|
||||||
|
*.blade.php diff=html
|
||||||
|
*.css diff=css
|
||||||
|
*.html diff=html
|
||||||
|
*.md diff=markdown
|
||||||
|
*.php diff=php
|
||||||
|
|
||||||
|
/.github export-ignore
|
||||||
|
CHANGELOG.md export-ignore
|
||||||
|
.styleci.yml export-ignore
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/.phpunit.cache
|
||||||
|
/node_modules
|
||||||
|
/public/build
|
||||||
|
/public/hot
|
||||||
|
/public/storage
|
||||||
|
/storage/*.key
|
||||||
|
/vendor
|
||||||
|
.env
|
||||||
|
.env.backup
|
||||||
|
.env.production
|
||||||
|
.phpunit.result.cache
|
||||||
|
Homestead.json
|
||||||
|
Homestead.yaml
|
||||||
|
auth.json
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
/.fleet
|
||||||
|
/.idea
|
||||||
|
/.vscode
|
||||||
|
/.env
|
||||||
|
/public/medias
|
||||||
|
/public/pdf
|
||||||
|
/public/mp3
|
||||||
|
/public/mp4
|
||||||
|
/server.ini
|
||||||
|
/public/documentFile
|
||||||
|
/public/documentsFile
|
||||||
|
/public/document
|
||||||
|
/public/courseImage
|
||||||
|
/package-lock.json
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
FROM --platform=linux/amd64 alpine:3.19.0
|
||||||
|
|
||||||
|
# Update package
|
||||||
|
RUN apk update --no-cache
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
bash \
|
||||||
|
git \
|
||||||
|
vim \
|
||||||
|
zip
|
||||||
|
|
||||||
|
# APACHE2
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
build-base \
|
||||||
|
autoconf \
|
||||||
|
curl \
|
||||||
|
tar \
|
||||||
|
libtool \
|
||||||
|
pcre-dev \
|
||||||
|
libxml2-dev \
|
||||||
|
openssl \
|
||||||
|
bison \
|
||||||
|
re2c \
|
||||||
|
file \
|
||||||
|
libressl-dev
|
||||||
|
|
||||||
|
# NOTE: APACHE
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
php$phpverx-apache2 \
|
||||||
|
apache2 \
|
||||||
|
apache2-utils \
|
||||||
|
apache2-ssl
|
||||||
|
# config httpd.conf
|
||||||
|
RUN sed -i '/LoadModule rewrite_module/s/^#//g' /etc/apache2/httpd.conf
|
||||||
|
|
||||||
|
# NOTE: PHP
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
composer \
|
||||||
|
php82-common \
|
||||||
|
php82-zip \
|
||||||
|
php82-curl \
|
||||||
|
php82-pdo \
|
||||||
|
php82-pdo_mysql \
|
||||||
|
php82-mysqli \
|
||||||
|
php82-openssl \
|
||||||
|
php82-mbstring \
|
||||||
|
php82-zip \
|
||||||
|
php82-bcmath \
|
||||||
|
php82-ctype \
|
||||||
|
php82-dom \
|
||||||
|
php82-gd \
|
||||||
|
php82-intl \
|
||||||
|
php82-simplexml \
|
||||||
|
php82-soap \
|
||||||
|
php82-sodium \
|
||||||
|
php82-xsl \
|
||||||
|
php82-tokenizer \
|
||||||
|
php82-fileinfo \
|
||||||
|
php82-sockets \
|
||||||
|
php82-xml \
|
||||||
|
php82-xmlwriter \
|
||||||
|
php82-session \
|
||||||
|
php82-apache2
|
||||||
|
# config php.ini
|
||||||
|
RUN sed -i 's/memory_limit = 128M/memory_limit = -1/' /etc/php82/php.ini
|
||||||
|
|
||||||
|
# Working file
|
||||||
|
WORKDIR /var/www/html
|
||||||
|
COPY ./docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
RUN chmod +x /docker-entrypoint.sh
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
# @name login
|
||||||
|
POST http://localhost:8000/api/v1/admin/login
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
{
|
||||||
|
"email": "admin@apactech.io",
|
||||||
|
"password": "Pay@2023"
|
||||||
|
}
|
||||||
|
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/detail
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{login.token}}
|
||||||
|
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/logout
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{login.token}}
|
||||||
|
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/forgot-password?email=admin@apactech.io
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/reset-password
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
{
|
||||||
|
"forgot_code": "RXTrVZBXqrdU9bW7",
|
||||||
|
"new_password": "Change@12345",
|
||||||
|
"confirm_password": "Change@12345"
|
||||||
|
}
|
||||||
|
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/change-password
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{login.token}}
|
||||||
|
{
|
||||||
|
"password": "Pay@2023",
|
||||||
|
"new_password": "Change@12345",
|
||||||
|
"confirm_password": "Change@12345"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAzNjYxNDkxLCJleHAiOjE3MDM3NDc4OTEsIm5iZiI6MTcwMzY2MTQ5MSwianRpIjoiMEJzRnplRnZsbEh2bHhUUiIsInN1YiI6IjEiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0._9GTM3AmCbovzp5Mq-4ZbNYr0z1ncfF9HIeaTRzsrZA
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/banner/create
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
Content-Type: multipart/form-data; boundary=boundary123
|
||||||
|
Accept: Application/json
|
||||||
|
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="title"
|
||||||
|
|
||||||
|
Banner 1
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="link"
|
||||||
|
|
||||||
|
https://google.com
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="is_active"
|
||||||
|
|
||||||
|
false
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="image"; filename="code.png"
|
||||||
|
Content-Type: image/png
|
||||||
|
|
||||||
|
< /mnt/c/Users/Administrator/Pictures/avatar.png
|
||||||
|
# Windows: C:/Users/{Username}/Pictures/logo.png
|
||||||
|
--boundary123--
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAzNjYxNDkxLCJleHAiOjE3MDM3NDc4OTEsIm5iZiI6MTcwMzY2MTQ5MSwianRpIjoiMEJzRnplRnZsbEh2bHhUUiIsInN1YiI6IjEiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0._9GTM3AmCbovzp5Mq-4ZbNYr0z1ncfF9HIeaTRzsrZA
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/banner/update
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
Content-Type: multipart/form-data; boundary=boundary123
|
||||||
|
Accept: Application/json
|
||||||
|
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="id"
|
||||||
|
|
||||||
|
2
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="title"
|
||||||
|
|
||||||
|
Banner 1
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="link"
|
||||||
|
|
||||||
|
https://google.com
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="is_active"
|
||||||
|
|
||||||
|
true
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="image"; filename="code.png"
|
||||||
|
Content-Type: image/png
|
||||||
|
|
||||||
|
< /mnt/c/Users/Administrator/Pictures/code.png
|
||||||
|
# Windows: C:/Users/{Username}/Pictures/logo.png
|
||||||
|
--boundary123--
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAzNjYxNDkxLCJleHAiOjE3MDM3NDc4OTEsIm5iZiI6MTcwMzY2MTQ5MSwianRpIjoiMEJzRnplRnZsbEh2bHhUUiIsInN1YiI6IjEiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0._9GTM3AmCbovzp5Mq-4ZbNYr0z1ncfF9HIeaTRzsrZA
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/banner/all
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/banner/delete?id=1
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/banner/updates
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"banners": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Richmond Okuneva",
|
||||||
|
"phone": "+1-307-367-8793",
|
||||||
|
"company": "Larson Ltd",
|
||||||
|
"country_code": "VN"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/banner/deletes
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"banners": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAzNTc0OTU4LCJleHAiOjE3MDM2NjEzNTgsIm5iZiI6MTcwMzU3NDk1OCwianRpIjoiSnQyZDJBT3lCR3MxV2JpUiIsInN1YiI6IjEiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.x-G1dLHaSkgGlhuhXubnKnnd1HAQ2KPUwPcdkEYe2-A
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/client/create
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
Content-Type: multipart/form-data; boundary=boundary123
|
||||||
|
Accept: Application/json
|
||||||
|
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="name"
|
||||||
|
|
||||||
|
Kai 1
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="password"
|
||||||
|
|
||||||
|
Pay@2023
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="country_code"
|
||||||
|
|
||||||
|
VN
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="email"
|
||||||
|
|
||||||
|
kai.t1@apactech.io
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="phone"
|
||||||
|
|
||||||
|
01234567890
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="avatar"; filename="code.png"
|
||||||
|
Content-Type: image/png
|
||||||
|
|
||||||
|
< /mnt/c/Users/Administrator/Pictures/code.png
|
||||||
|
# Windows: C:/Users/{Username}/Pictures/logo.png
|
||||||
|
--boundary123--
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAzNTUyMjM3LCJleHAiOjE3MDM2Mzg2MzcsIm5iZiI6MTcwMzU1MjIzNywianRpIjoiNjIzWmtUVG1jNnlOZEZ0ZSIsInN1YiI6IjUiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0._NIM-6oICYVbjxRwBTt8rFesXZli2W3bd8XCHFyd5Qw
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/client/update
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
Content-Type: multipart/form-data; boundary=boundary123
|
||||||
|
Accept: Application/json
|
||||||
|
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="id"
|
||||||
|
|
||||||
|
500
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="name"
|
||||||
|
|
||||||
|
Kai 6 edited
|
||||||
|
# --boundary123
|
||||||
|
# Content-Disposition: form-data; name="password"
|
||||||
|
|
||||||
|
# Pay@2023
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="country_code"
|
||||||
|
|
||||||
|
VN
|
||||||
|
# --boundary123
|
||||||
|
# Content-Disposition: form-data; name="email"
|
||||||
|
|
||||||
|
# kai.t6@apactech.io
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="phone"
|
||||||
|
|
||||||
|
01234567890
|
||||||
|
# --boundary123
|
||||||
|
# Content-Disposition: form-data; name="avatar"; filename="code.png"
|
||||||
|
# Content-Type: image/png
|
||||||
|
|
||||||
|
# < /mnt/c/Users/Administrator/Pictures/code.PNG
|
||||||
|
# # Windows: C:/Users/{Username}/Pictures/logo.png
|
||||||
|
--boundary123--
|
||||||
|
|
||||||
|
HTTP/1.1 200 - OK
|
||||||
|
host: localhost:8000
|
||||||
|
date: Wed, 27 Dec 2023 00:50:47 GMT, Wed, 27 Dec 2023 00:50:47 GMT
|
||||||
|
connection: close
|
||||||
|
x-powered-by: PHP/8.2.11
|
||||||
|
cache-control: no-cache, private
|
||||||
|
content-type: application/json
|
||||||
|
x-ratelimit-limit: 60
|
||||||
|
x-ratelimit-remaining: 59
|
||||||
|
access-control-allow-origin: *
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAzNTUyMjM3LCJleHAiOjE3MDM2Mzg2MzcsIm5iZiI6MTcwMzU1MjIzNywianRpIjoiNjIzWmtUVG1jNnlOZEZ0ZSIsInN1YiI6IjUiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0._NIM-6oICYVbjxRwBTt8rFesXZli2W3bd8XCHFyd5Qw
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/client/get
|
||||||
|
?page=1
|
||||||
|
# @eg. 1|0|true|false
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
HTTP/1.1 200 - OK
|
||||||
|
host: localhost:8000
|
||||||
|
date: Tue, 26 Dec 2023 10:27:57 GMT, Tue, 26 Dec 2023 10:27:57 GMT
|
||||||
|
connection: close
|
||||||
|
x-powered-by: PHP/8.2.11
|
||||||
|
cache-control: no-cache, private
|
||||||
|
content-type: application/json
|
||||||
|
x-ratelimit-limit: 60
|
||||||
|
x-ratelimit-remaining: 58
|
||||||
|
phpdebugbar-id: X9ba23f0265242b1d21d1f7aa5735b53c
|
||||||
|
access-control-allow-origin: *
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/client/delete?id=1
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/client/updates
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Richmond Okuneva",
|
||||||
|
"phone": "+1-307-367-8793",
|
||||||
|
"company": "Larson Ltd",
|
||||||
|
"country_code": "VN"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/client/deletes
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAyNTIwNjAyLCJleHAiOjE3MDI2MDcwMDIsIm5iZiI6MTcwMjUyMDYwMiwianRpIjoidHE0VmhZSzhDMGY4cGpLZSIsInN1YiI6IjEiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.9GTTVHlj93B3gXGZ1nmFH6VbwoJT7ll1Ll-TtytpTWMs
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/custom-theme
|
||||||
|
Content-Type: multipart/form-data; boundary=boundary123
|
||||||
|
Accept: Application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/custom-theme
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
Content-Type: multipart/form-data; boundary=boundary123
|
||||||
|
Accept: Application/json
|
||||||
|
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="js"
|
||||||
|
|
||||||
|
console.log('hello')
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="css"
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: red !important
|
||||||
|
}
|
||||||
|
--boundary123--
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vYXBhYy5sb2NhbDo4MDAwL2FwaS92MS9hZG1pbi9sb2dpbiIsImlhdCI6MTcwNjU4MTI2NywiZXhwIjoxNzA2NjY3NjY3LCJuYmYiOjE3MDY1ODEyNjcsImp0aSI6Ik54ZHhveWVnT2sydlVtU2EiLCJzdWIiOiI1IiwicHJ2IjoiZDJmZjI5MzM5YThhM2U4MmMzNTgyYTVhOGU3MzlkZjE3ODliYjEyZiJ9.d-R6ZSXNzUq_AXNZWYMIh3BfHWAtpirdrNyewd-c8As
|
||||||
|
###
|
||||||
|
|
||||||
|
GET http://localhost:8000/api/v1/admin/dashboard/statistics-sn-keywords-by-month
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"month": 1,
|
||||||
|
"year": 2024,
|
||||||
|
"timezone_offset": "+01:00"
|
||||||
|
}
|
||||||
|
|
||||||
|
GET http://localhost:8000/api/v1/admin/dashboard/statistics-revenues-by-month
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"month": 1,
|
||||||
|
"year": 2024,
|
||||||
|
"timezone_offset": "+01:00"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAzNTYzMjk1LCJleHAiOjE3MDM2NDk2OTUsIm5iZiI6MTcwMzU2MzI5NSwianRpIjoicEs0bGJxSEtEMTVwdndVYSIsInN1YiI6IjEiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.VvhrVE8noDywaMJne17XyeDzpnJrQC-bVLHFgkDgAIk
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/discount/get
|
||||||
|
?page=1
|
||||||
|
&from_date=1695307952
|
||||||
|
&to_date=1701635729
|
||||||
|
&order_by_id=desc
|
||||||
|
# &date_used=1702615520
|
||||||
|
# &code=123456
|
||||||
|
# &status=0
|
||||||
|
# @eg. status=0|1
|
||||||
|
# &email=quitz
|
||||||
|
# @eg. email=admin@gmail.com
|
||||||
|
# &value=
|
||||||
|
&discount_type_id=1
|
||||||
|
# @eg. discount_type_id= 1|2 # 1: price, 2: percent
|
||||||
|
# @fetch. "http://localhost:8000/api/v1/admin/discount-type/all"
|
||||||
|
&search=
|
||||||
|
# @eg. search=code|email|value
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/discount/create
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"discount_type_id": 2,
|
||||||
|
"value": "99"
|
||||||
|
}
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/discount/update
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
Accept: application/json
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"date_used": "1702866337"
|
||||||
|
}
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/discount/delete?id=1
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/discount/updates
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"discounts": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"discount_type_id": 1,
|
||||||
|
"value": "100",
|
||||||
|
"status": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/discount/deletes
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"discounts": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAyNTIwNjAyLCJleHAiOjE3MDI2MDcwMDIsIm5iZiI6MTcwMjUyMDYwMiwianRpIjoidHE0VmhZSzhDMGY4cGpLZSIsInN1YiI6IjEiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.9GTTVHlj93B3gXGZ1nmFH6VbwoJT7ll1Ll-TtytpTWM
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/discount-type/all
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAzNTUyMjM3LCJleHAiOjE3MDM2Mzg2MzcsIm5iZiI6MTcwMzU1MjIzNywianRpIjoiNjIzWmtUVG1jNnlOZEZ0ZSIsInN1YiI6IjUiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0._NIM-6oICYVbjxRwBTt8rFesXZli2W3bd8XCHFyd5Qw
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/h-country
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
HTTP/1.1 200 - OK
|
||||||
|
host: localhost:8000
|
||||||
|
date: Tue, 26 Dec 2023 07:31:38 GMT, Tue, 26 Dec 2023 07:31:38 GMT
|
||||||
|
connection: close
|
||||||
|
x-powered-by: PHP/8.2.11
|
||||||
|
cache-control: no-cache, private
|
||||||
|
content-type: application/json
|
||||||
|
x-ratelimit-limit: 60
|
||||||
|
x-ratelimit-remaining: 59
|
||||||
|
phpdebugbar-id: X0745a3d657f1a8203f21d9fa55d07f77
|
||||||
|
access-control-allow-origin: *
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAzNTc0OTU4LCJleHAiOjE3MDM2NjEzNTgsIm5iZiI6MTcwMzU3NDk1OCwianRpIjoiSnQyZDJBT3lCR3MxV2JpUiIsInN1YiI6IjEiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.x-G1dLHaSkgGlhuhXubnKnnd1HAQ2KPUwPcdkEYe2-A
|
||||||
|
###
|
||||||
|
GET http://localhost:8000/api/v1/admin/package/all
|
||||||
|
?order_by_point=desc
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
POST http://localhost:8000/api/v1/admin/package/create
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"point": 1000000000000000000000000000000000,
|
||||||
|
"price": "1000000000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
POST http://localhost:8000/api/v1/admin/package/update
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
Accept: application/json
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"point": 100,
|
||||||
|
"price": 100
|
||||||
|
}
|
||||||
|
GET http://localhost:8000/api/v1/admin/package/delete?id=1
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
POST http://localhost:8000/api/v1/admin/package/updates
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"point": "100",
|
||||||
|
"price": "1000.50",
|
||||||
|
"status": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"status": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
POST http://localhost:8000/api/v1/admin/package/deletes
|
||||||
|
Content-Type: application/json
|
||||||
|
Accept: application/json
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzAyNTIwNjAyLCJleHAiOjE3MDI2MDcwMDIsIm5iZiI6MTcwMjUyMDYwMiwianRpIjoidHE0VmhZSzhDMGY4cGpLZSIsInN1YiI6IjEiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.9GTTVHlj93B3gXGZ1nmFH6VbwoJT7ll1Ll-TtytpTWM
|
||||||
|
###
|
||||||
|
POST http://localhost:8000/api/v1/admin/setting
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
Content-Type: multipart/form-data; boundary=boundary123
|
||||||
|
Accept: Application/json
|
||||||
|
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="page_title"
|
||||||
|
|
||||||
|
Payment
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="email"
|
||||||
|
|
||||||
|
admin@apactech.io
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="phone"
|
||||||
|
|
||||||
|
01234567890
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="meta_title"
|
||||||
|
|
||||||
|
Payment Accumulate
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="meta_description"
|
||||||
|
|
||||||
|
Payment is the voluntary transfer of money,
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="meta_keyword"
|
||||||
|
|
||||||
|
payment accumulate
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="facebook"
|
||||||
|
|
||||||
|
https://facebook.com
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="twitter"
|
||||||
|
|
||||||
|
https://twitter.com
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="linkedin"
|
||||||
|
|
||||||
|
https://lnkedin.com
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="logo"; filename="logo.png"
|
||||||
|
Content-Type: image/png
|
||||||
|
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="address"
|
||||||
|
|
||||||
|
APAC, Hung Loi, Ninh Kieu, Can Tho
|
||||||
|
--boundary123
|
||||||
|
Content-Disposition: form-data; name="favicon"; filename="favicon.png"
|
||||||
|
Content-Type: image/png
|
||||||
|
|
||||||
|
< /mnt/c/Users/Administrator/Pictures/code.png
|
||||||
|
--boundary123--
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Emails;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ForgotPasswordMail extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
protected $email;
|
||||||
|
protected $name;
|
||||||
|
protected $forgot_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forgot send mail
|
||||||
|
*
|
||||||
|
* @param string $email
|
||||||
|
* @param string $name
|
||||||
|
* @param string $forgot_code
|
||||||
|
*/
|
||||||
|
public function __construct($email, $name, $forgot_code)
|
||||||
|
{
|
||||||
|
$this->email = $email;
|
||||||
|
$this->name = $name;
|
||||||
|
$this->forgot_code = $forgot_code;
|
||||||
|
|
||||||
|
$this->to($email);
|
||||||
|
$this->subject('Forgot Password');
|
||||||
|
$this->replyTo(config('mail.from.address'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*/
|
||||||
|
public function build(): self
|
||||||
|
{
|
||||||
|
return $this->view('admin::mails/forgot_password', get_object_vars($this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Emails;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ResetPasswordMail extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
protected $email;
|
||||||
|
protected $name;
|
||||||
|
protected $forgot_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset after change password successfully
|
||||||
|
*
|
||||||
|
* @param string $email
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function __construct($email, $name)
|
||||||
|
{
|
||||||
|
$this->email = $email;
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
$this->to($email);
|
||||||
|
$this->subject('Reset Password Successfully');
|
||||||
|
$this->replyTo(config('mail.from.address'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*/
|
||||||
|
public function build(): self
|
||||||
|
{
|
||||||
|
return $this->view('admin::mails/reset_password_success', get_object_vars($this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Helper\Cache\CustomThemeCacheHelper;
|
||||||
|
use App\Helper\Cache\SettingCacheHelper;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Contact;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Modules\Admin\app\Emails\ForgotPasswordMail;
|
||||||
|
use Modules\Admin\app\Emails\ResetPasswordMail;
|
||||||
|
use Modules\Admin\app\Models\Admin;
|
||||||
|
use Modules\Admin\app\Models\Banner;
|
||||||
|
use Modules\Admin\app\Models\CustomTheme;
|
||||||
|
use Modules\Admin\app\Models\Setting;
|
||||||
|
use Modules\Admin\app\Rules\PasswordRule;
|
||||||
|
use Tymon\JWTAuth\Facades\JWTAuth;
|
||||||
|
|
||||||
|
class AdminController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
Config::set('auth.guards.api.provider', 'admin');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function respondWithToken()
|
||||||
|
{
|
||||||
|
$token = Admin::getTokenByAuth();
|
||||||
|
return response()->json([
|
||||||
|
'expires_in' => JWTAuth::setToken($token)->getPayload()->get('exp'),
|
||||||
|
'token' => $token,
|
||||||
|
'user' => auth('admins')->user(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function login(Request $request)
|
||||||
|
{
|
||||||
|
$email = $request->get('email');
|
||||||
|
$password = $request->get('password');
|
||||||
|
$admin = Admin::where('email', $email)->first();
|
||||||
|
if ($admin && Hash::check($password, $admin->password)) {
|
||||||
|
auth('admins')->login($admin);
|
||||||
|
return $this->respondWithToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Incorrect email or password.',
|
||||||
|
'status' => false
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forgotPassword(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'email' => 'required|email'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$admin = Admin::where('email', $request->get('email'))->first();
|
||||||
|
if ($admin) {
|
||||||
|
$admin->update([
|
||||||
|
'forgot_code' => Str::random()
|
||||||
|
]);
|
||||||
|
|
||||||
|
Mail::send(new ForgotPasswordMail(
|
||||||
|
name: $admin->name,
|
||||||
|
email: $admin->email,
|
||||||
|
forgot_code: $admin->forgot_code
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resetPassword(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'forgot_code' => 'required|exists:admin',
|
||||||
|
'new_password' => new PasswordRule,
|
||||||
|
'confirm_password' => 'same:new_password'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$admin = Admin::where('forgot_code', $request->get('forgot_code'))->first();
|
||||||
|
if ($admin) {
|
||||||
|
$admin->update([
|
||||||
|
'password' => bcrypt($request->get('new_password')),
|
||||||
|
'forgot_code' => null
|
||||||
|
]);
|
||||||
|
|
||||||
|
Mail::send(new ResetPasswordMail(
|
||||||
|
name: $admin->name,
|
||||||
|
email: $admin->email,
|
||||||
|
));
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => false
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function changePassword(Request $request)
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'password' => 'required',
|
||||||
|
'new_password' => new PasswordRule,
|
||||||
|
'confirm_password' => 'same:new_password'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$admin = auth('admins')->user();
|
||||||
|
if (!Hash::check($request->get('password'), $admin->password)) {
|
||||||
|
// Fail check old password
|
||||||
|
return response()->json([
|
||||||
|
'errors' => [
|
||||||
|
'password' => [
|
||||||
|
'The old password is incorrect'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin->update([
|
||||||
|
'password' => bcrypt($request->get('new_password')),
|
||||||
|
'forgot_code' => null
|
||||||
|
]);
|
||||||
|
|
||||||
|
Mail::send(new ResetPasswordMail(
|
||||||
|
name: $admin->name,
|
||||||
|
email: $admin->email,
|
||||||
|
));
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function detail()
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'user' => auth('admins')->user(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout()
|
||||||
|
{
|
||||||
|
$user = auth('admins')->user();
|
||||||
|
auth('admins')->logout();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => true,
|
||||||
|
'user' => $user
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Banner;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Modules\Admin\app\Http\Requests\BannerRequest;
|
||||||
|
|
||||||
|
class BannerController extends Controller
|
||||||
|
{
|
||||||
|
public function all(Request $request)
|
||||||
|
{
|
||||||
|
$package = new Banner;
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $package->get(),
|
||||||
|
'status' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(BannerRequest $request)
|
||||||
|
{
|
||||||
|
$banner = new Banner;
|
||||||
|
|
||||||
|
if ($request->has('title')) {
|
||||||
|
$banner->title = $request->get('title');
|
||||||
|
}
|
||||||
|
if ($request->has('link')) {
|
||||||
|
$banner->link = $request->get('link');
|
||||||
|
}
|
||||||
|
if ($request->has('is_active')) {
|
||||||
|
$banner->is_active = in_array(
|
||||||
|
needle: $request->get('is_active'),
|
||||||
|
haystack: ['false', '0']
|
||||||
|
) ? 0 : 1;
|
||||||
|
}
|
||||||
|
$banner->save();
|
||||||
|
|
||||||
|
if ($request->hasFile('image')) {
|
||||||
|
$file = $request->file('image');
|
||||||
|
$filename = $banner->id . '/' . Str::random(20) . '.' . $file->getClientOriginalExtension();
|
||||||
|
$path = Banner::STORAGE . "/$filename";
|
||||||
|
|
||||||
|
Storage::disk('public')->put(
|
||||||
|
path: $path,
|
||||||
|
contents: $file->get()
|
||||||
|
);
|
||||||
|
|
||||||
|
$banner->image = $path;
|
||||||
|
$banner->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $banner,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(BannerRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
$banner = Banner::find($id);
|
||||||
|
|
||||||
|
if ($request->has('title')) {
|
||||||
|
$banner->title = $request->get('title');
|
||||||
|
}
|
||||||
|
if ($request->has('link')) {
|
||||||
|
$banner->link = $request->get('link');
|
||||||
|
}
|
||||||
|
if ($request->has('is_active')) {
|
||||||
|
$banner->is_active = in_array(
|
||||||
|
needle: $request->get('is_active'),
|
||||||
|
haystack: ['false', '0']
|
||||||
|
) ? 0 : 1;
|
||||||
|
}
|
||||||
|
$banner->save();
|
||||||
|
|
||||||
|
if ($request->hasFile('image')) {
|
||||||
|
$file = $request->file('image');
|
||||||
|
$filename = $banner->id . '/' . Str::random(20) . '.' . $file->getClientOriginalExtension();
|
||||||
|
$path = Banner::STORAGE . "/$filename";
|
||||||
|
|
||||||
|
// delete old file
|
||||||
|
if (Storage::disk('public')->exists($banner->getRawOriginal('image'))) {
|
||||||
|
Storage::disk('public')->delete($banner->getRawOriginal('image'));
|
||||||
|
}
|
||||||
|
// put a new file
|
||||||
|
Storage::disk('public')->put(
|
||||||
|
path: $path,
|
||||||
|
contents: $file->get()
|
||||||
|
);
|
||||||
|
$banner->image = $path;
|
||||||
|
$banner->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $banner,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(BannerRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
Banner::destroy($id);
|
||||||
|
return response()->json([
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete multiple packages
|
||||||
|
public function deletes(BannerRequest $request)
|
||||||
|
{
|
||||||
|
$banners = $request->get('banners');
|
||||||
|
$ids = collect($banners)->pluck('id');
|
||||||
|
Banner::whereIn('id', $ids)->delete();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $ids,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update multiple banners
|
||||||
|
public function updates(BannerRequest $request)
|
||||||
|
{
|
||||||
|
$banners = $request->get('banners');
|
||||||
|
$ids = collect($banners)->pluck('id');
|
||||||
|
|
||||||
|
foreach ($banners as $bannersRequest) {
|
||||||
|
// convert to object|array to array
|
||||||
|
$bannersRequest = collect($bannersRequest)->toArray();
|
||||||
|
// handle array
|
||||||
|
$package = Package::find($bannersRequest['id']);
|
||||||
|
if ($package) {
|
||||||
|
// exclude id field
|
||||||
|
unset($package['id']);
|
||||||
|
$package->update($bannersRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => Package::whereIn('id', $ids)->get(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Client;
|
||||||
|
use App\Traits\HasFilterRequest;
|
||||||
|
use App\Traits\HasOrderByRequest;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Facades\File;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use JsonException;
|
||||||
|
use Modules\Admin\app\Http\Requests\ClientRequest;
|
||||||
|
|
||||||
|
class ClientController extends Controller
|
||||||
|
{
|
||||||
|
use HasOrderByRequest;
|
||||||
|
use HasFilterRequest;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// module check model exist and table
|
||||||
|
if (!class_exists(Client::class)) {
|
||||||
|
throw new JsonException("user table not exist");
|
||||||
|
}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(Request $request)
|
||||||
|
{
|
||||||
|
$client = new Client;
|
||||||
|
|
||||||
|
// Order by
|
||||||
|
$this->orderByRequest($client, $request);
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
$this->filterRequest(
|
||||||
|
builder: $client,
|
||||||
|
request: $request,
|
||||||
|
filterKeys: [
|
||||||
|
'name' => self::F_TEXT,
|
||||||
|
'phone' => self::F_TEXT,
|
||||||
|
'email' => self::F_TEXT,
|
||||||
|
'company' => self::F_TEXT,
|
||||||
|
'status' => self::F_BOOLEAN,
|
||||||
|
'subscribe' => self::F_BOOLEAN,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$responseData = array_merge(
|
||||||
|
$client->paginate($request->get('per_page'))->toArray(),
|
||||||
|
['status' => true]
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json($responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(ClientRequest $request)
|
||||||
|
{
|
||||||
|
$payload = $request->all();
|
||||||
|
|
||||||
|
$client = new Client;
|
||||||
|
|
||||||
|
$client->name = $request->get('name');
|
||||||
|
$client->password = bcrypt($request->get('password', Client::DEFAULT_PASSWORD));
|
||||||
|
$client->email = $request->get('email', '');
|
||||||
|
$client->email_verified_at = now();
|
||||||
|
$client->phone = $request->get('phone', '');
|
||||||
|
$client->country_code = $request->get('country_code', 'AU');
|
||||||
|
$client->company = $request->get('company', '');
|
||||||
|
$client->save();
|
||||||
|
|
||||||
|
if ($request->hasFile('avatar')) {
|
||||||
|
$file = $request->file('avatar');
|
||||||
|
$filename = $client->id . '.' . $file->getClientOriginalExtension();
|
||||||
|
$path = Client::PATH_AVATAR . "/$filename";
|
||||||
|
|
||||||
|
Storage::disk('public')->put($path, $file->get());
|
||||||
|
|
||||||
|
$client->avatar = $path;
|
||||||
|
$client->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $client,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(ClientRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
$client = Client::find($id);
|
||||||
|
|
||||||
|
if ($request->has('name')) {
|
||||||
|
$client->name = $request->get('name');
|
||||||
|
}
|
||||||
|
if ($request->has('password') && !empty($request->get('password'))) {
|
||||||
|
$client->password = bcrypt($request->get('password'));
|
||||||
|
}
|
||||||
|
if ($request->has('email')) {
|
||||||
|
$client->email = $request->get('email');
|
||||||
|
}
|
||||||
|
if ($request->has('phone')) {
|
||||||
|
$client->phone = $request->get('phone');
|
||||||
|
}
|
||||||
|
if ($request->has('company')) {
|
||||||
|
$client->company = $request->get('company');
|
||||||
|
}
|
||||||
|
if ($request->has('country_code')) {
|
||||||
|
$client->country_code = $request->get('country_code');
|
||||||
|
}
|
||||||
|
if ($request->has('status')) {
|
||||||
|
$client->status = ($request->get('status') == 'true' || $request->get('status') == '1') ? 1 : 0;
|
||||||
|
}
|
||||||
|
$client->save();
|
||||||
|
|
||||||
|
if ($request->hasFile('avatar')) {
|
||||||
|
$file = $request->file('avatar');
|
||||||
|
$filename = $client->id . '.' . $file->getClientOriginalExtension();
|
||||||
|
$path = Client::PATH_AVATAR . "/$filename";
|
||||||
|
$avatarOld = Storage::disk('public')->exists($client->avatar);
|
||||||
|
|
||||||
|
if ($avatarOld) {
|
||||||
|
Storage::disk('public')->delete($client->avatar);
|
||||||
|
}
|
||||||
|
|
||||||
|
Storage::disk('public')->put($path, $file->get());
|
||||||
|
$client->update([
|
||||||
|
'avatar' => $path
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $client,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(ClientRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
Client::destroy($id);
|
||||||
|
return response()->json([
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete multiple clients
|
||||||
|
public function deletes(ClientRequest $request)
|
||||||
|
{
|
||||||
|
$clients = $request->get('clients');
|
||||||
|
$ids = collect($clients)->pluck('id');
|
||||||
|
Client::whereIn('id', $ids)->delete();
|
||||||
|
return response()->json([
|
||||||
|
'data' => $ids,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update multiple clients
|
||||||
|
public function updates(ClientRequest $request)
|
||||||
|
{
|
||||||
|
$clients = $request->get('clients');
|
||||||
|
$ids = collect($clients)->pluck('id');
|
||||||
|
|
||||||
|
foreach ($clients as $ClientRequest) {
|
||||||
|
// convert to object|array to array
|
||||||
|
$ClientRequest = collect($ClientRequest)->toArray();
|
||||||
|
// handle array
|
||||||
|
$client = Client::find($ClientRequest['id']);
|
||||||
|
if ($client) {
|
||||||
|
// exclude id field
|
||||||
|
unset($client['id']);
|
||||||
|
|
||||||
|
$client->update($ClientRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response()->json([
|
||||||
|
'data' => Client::whereIn('id', $ids)->get(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Contact;
|
||||||
|
use App\Traits\HasFilterRequest;
|
||||||
|
use App\Traits\HasOrderByRequest;
|
||||||
|
use App\Traits\HasSearchRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Modules\Admin\app\Http\Requests\ContactRequest;
|
||||||
|
|
||||||
|
class ContactController extends Controller
|
||||||
|
{
|
||||||
|
use HasOrderByRequest;
|
||||||
|
use HasFilterRequest;
|
||||||
|
use HasSearchRequest;
|
||||||
|
|
||||||
|
public function get(ContactRequest $request)
|
||||||
|
{
|
||||||
|
$contact = new Contact;
|
||||||
|
|
||||||
|
// Order by
|
||||||
|
$this->orderByRequest($contact, $request);
|
||||||
|
|
||||||
|
$this->searchRequest(
|
||||||
|
builder: $contact,
|
||||||
|
value: $request->get('search'),
|
||||||
|
fields: [
|
||||||
|
'name',
|
||||||
|
'phone',
|
||||||
|
'company',
|
||||||
|
'email',
|
||||||
|
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$responseData = array_merge(
|
||||||
|
$contact->paginate($request->get('per_page'))->toArray(),
|
||||||
|
['status' => true]
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json($responseData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\HCountry;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use JsonException;
|
||||||
|
|
||||||
|
class CountryController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
if (!class_exists(HCountry::class)) {
|
||||||
|
throw new JsonException('Helper table h_country not exist, please check model and table db.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function all()
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'data' => HCountry::getByCache()
|
||||||
|
->map(function($country) {
|
||||||
|
$country->flag = asset(HCountry::PUBLIC_PATH . "/$country->code.svg");
|
||||||
|
return $country;
|
||||||
|
}),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Modules\Admin\app\Http\Requests\CustomThemeRequest;
|
||||||
|
use Modules\Admin\app\Models\CustomTheme;
|
||||||
|
use Tymon\JWTAuth\Claims\Custom;
|
||||||
|
|
||||||
|
class CustomThemeController extends Controller
|
||||||
|
{
|
||||||
|
public function index(CustomThemeRequest $request)
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'data' => CustomTheme::first(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateOrCreate(CustomThemeRequest $request)
|
||||||
|
{
|
||||||
|
CustomTheme::updateOrCreate([
|
||||||
|
'id' => 1
|
||||||
|
], $request->all());
|
||||||
|
return response()->json([
|
||||||
|
'data' => CustomTheme::first(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Contact;
|
||||||
|
use App\Models\Discount;
|
||||||
|
use App\Models\Order;
|
||||||
|
use App\Models\Package;
|
||||||
|
use App\Models\SerialNumberCheck;
|
||||||
|
use App\Models\User;
|
||||||
|
use Modules\Admin\app\Http\Requests\DashboardRequest;
|
||||||
|
|
||||||
|
class DashboardController extends Controller
|
||||||
|
{
|
||||||
|
public function get()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$packageTotal = Package::count();
|
||||||
|
$discountTotal = Discount::count();
|
||||||
|
$orderTotal = Order::count();
|
||||||
|
$clientTotal = User::count();
|
||||||
|
$contactTotal = Contact::count();
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => [
|
||||||
|
"packages" => $packageTotal,
|
||||||
|
"discounts" => $discountTotal,
|
||||||
|
"orders" => $orderTotal,
|
||||||
|
"clients" => $clientTotal,
|
||||||
|
"contacts" => $contactTotal,
|
||||||
|
],
|
||||||
|
'status' => true,
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
'status' => false,
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function statisticSearchSNByMonth(DashboardRequest $request)
|
||||||
|
{
|
||||||
|
$timezoneOffset = $request->input('timezone_offset', '+00:00');
|
||||||
|
$month = $request->input('month', date('M'));
|
||||||
|
$year = $request->input('year', date('Y'));
|
||||||
|
$timezoneOffsetServer = date('P');
|
||||||
|
$selectDateConvert = "CONVERT_TZ(`created_at`, '$timezoneOffsetServer', '$timezoneOffset')";
|
||||||
|
|
||||||
|
$arrCreatedAt = SerialNumberCheck::selectRaw("
|
||||||
|
$selectDateConvert AS date_convert,
|
||||||
|
created_at
|
||||||
|
")->whereRaw("
|
||||||
|
MONTH($selectDateConvert) = $month AND
|
||||||
|
YEAR($selectDateConvert) = $year
|
||||||
|
")->groupBy('date_convert')->pluck('created_at');
|
||||||
|
|
||||||
|
$statistic = SerialNumberCheck::whereIn('created_at', $arrCreatedAt)
|
||||||
|
->orderBy('created_at')
|
||||||
|
->get([
|
||||||
|
'keyword',
|
||||||
|
'status',
|
||||||
|
'created_at',
|
||||||
|
])
|
||||||
|
->groupBy(function ($record) use ($timezoneOffset) {
|
||||||
|
return $record
|
||||||
|
->created_at
|
||||||
|
->setTimezone($timezoneOffset)
|
||||||
|
->toDateString();
|
||||||
|
})
|
||||||
|
->map(function ($records) {
|
||||||
|
$countPending = collect($records)
|
||||||
|
->where('status', SerialNumberCheck::STATUS_PENDING)
|
||||||
|
->count();
|
||||||
|
$countComplete = collect($records)
|
||||||
|
->where('status', SerialNumberCheck::STATUS_COMPLETE)
|
||||||
|
->count();
|
||||||
|
$countFail = collect($records)
|
||||||
|
->where('status', SerialNumberCheck::STATUS_FAIL)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'count' => count($records),
|
||||||
|
'count_pending' => $countPending,
|
||||||
|
'count_complete' => $countComplete,
|
||||||
|
'count_fail' => $countFail,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $statistic,
|
||||||
|
'status' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function statisticRevenuesByMonth(DashboardRequest $request)
|
||||||
|
{
|
||||||
|
$timezoneOffset = $request->input('timezone_offset', '+00:00');
|
||||||
|
$month = $request->input('month', date('M'));
|
||||||
|
$year = $request->input('year', date('Y'));
|
||||||
|
$timezoneOffsetServer = date('P');
|
||||||
|
$selectDateConvert = "CONVERT_TZ(`updated_at`, '$timezoneOffsetServer', '$timezoneOffset')";
|
||||||
|
$statusCompleted = Order::STATUS_COMPLETED;
|
||||||
|
|
||||||
|
$statisticInMonth = Order::selectRaw("
|
||||||
|
DATE_FORMAT($selectDateConvert, '%Y-%m-%d') AS date_convert,
|
||||||
|
SUM(total_price) as total_price,
|
||||||
|
COUNT(*) as count
|
||||||
|
")->whereRaw("
|
||||||
|
MONTH($selectDateConvert) = '$month' AND
|
||||||
|
YEAR($selectDateConvert) = '$year' AND
|
||||||
|
status = '$statusCompleted'
|
||||||
|
")
|
||||||
|
->groupBy('date_convert')
|
||||||
|
->orderBy('updated_at')
|
||||||
|
->get()
|
||||||
|
->groupBy('date_convert')
|
||||||
|
->map(function ($record) {
|
||||||
|
return $record[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $statisticInMonth,
|
||||||
|
'status' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Traits\HasFilterRequest;
|
||||||
|
use App\Traits\HasOrderByRequest;
|
||||||
|
use App\Traits\HasSearchRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Modules\Admin\app\Http\Requests\DiscountRequest;
|
||||||
|
use Modules\Admin\app\Models\Discount;
|
||||||
|
|
||||||
|
class DiscountController extends Controller
|
||||||
|
{
|
||||||
|
use HasOrderByRequest;
|
||||||
|
use HasFilterRequest;
|
||||||
|
use HasSearchRequest;
|
||||||
|
|
||||||
|
public function get(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$discount = new Discount;
|
||||||
|
|
||||||
|
// Order by
|
||||||
|
$this->orderByRequest($discount, $request);
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
$this->filterRequest(
|
||||||
|
builder: $discount,
|
||||||
|
request: $request,
|
||||||
|
filterKeys: [
|
||||||
|
'active_date' => self::F_THAN_EQ_DATETIME,
|
||||||
|
'expiry' => self::F_LESS_EQ_DATETIME,
|
||||||
|
'date_used' => self::F_IN_DATETIME,
|
||||||
|
'code' => self::F_TEXT,
|
||||||
|
'value' => self::F_TEXT,
|
||||||
|
'email' => self::F_TEXT,
|
||||||
|
'discount_type_id' => self::F_NOT_CONTAIN,
|
||||||
|
'status' => self::F_BOOLEAN,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->searchRequest(
|
||||||
|
builder: $discount,
|
||||||
|
value: $request->get('search'),
|
||||||
|
fields: [
|
||||||
|
'code',
|
||||||
|
'email',
|
||||||
|
'value'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$responseData = array_merge(
|
||||||
|
$discount->paginate($request->get('per_page'))->toArray(),
|
||||||
|
['status' => true]
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json($responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$payload = $request->all();
|
||||||
|
|
||||||
|
$discount = Discount::createWithDefault($payload);
|
||||||
|
return response()->json([
|
||||||
|
'data' => $discount,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
$discount = Discount::find($id);
|
||||||
|
$payload = $request->all();
|
||||||
|
|
||||||
|
if ($discount) {
|
||||||
|
$discount->update($payload);
|
||||||
|
}
|
||||||
|
return response()->json([
|
||||||
|
'data' => $discount,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
Discount::destroy($id);
|
||||||
|
return response()->json([
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete multiple discounts
|
||||||
|
public function deletes(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$discounts = $request->get('discounts');
|
||||||
|
$ids = collect($discounts)->pluck('id');
|
||||||
|
Discount::whereIn('id', $ids)->delete();
|
||||||
|
return response()->json([
|
||||||
|
'data' => $ids,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update multiple discounts
|
||||||
|
public function updates(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$discounts = $request->get('discounts');
|
||||||
|
$ids = collect($discounts)->pluck('id');
|
||||||
|
|
||||||
|
foreach ($discounts as $discountRequest) {
|
||||||
|
// convert to object|array to array
|
||||||
|
$discountRequest = collect($discountRequest)->toArray();
|
||||||
|
// handle array
|
||||||
|
$discount = Discount::find($discountRequest['id']);
|
||||||
|
if ($discount) {
|
||||||
|
// exclude id field
|
||||||
|
unset($discount['id']);
|
||||||
|
|
||||||
|
$discount->update($discountRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response()->json([
|
||||||
|
'data' => Discount::whereIn('id', $ids)->get(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Modules\Admin\app\Http\Requests\DiscountTypeRequest;
|
||||||
|
use Modules\Admin\app\Models\DiscountType;
|
||||||
|
|
||||||
|
class DiscountTypeController extends Controller
|
||||||
|
{
|
||||||
|
public function all(DiscountTypeRequest $request)
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'data' => DiscountType::all(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Events\PaymentCanceled;
|
||||||
|
use App\Events\PaymentCompleted;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Client;
|
||||||
|
use App\Models\Order;
|
||||||
|
use App\Models\Package;
|
||||||
|
use App\Traits\HasFilterRequest;
|
||||||
|
use App\Traits\HasOrderByRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use JsonException;
|
||||||
|
use Modules\Admin\app\Http\Requests\OrderRequest;
|
||||||
|
use Modules\Admin\app\Models\Discount;
|
||||||
|
use Modules\Paypal\app\Models\HistoryPayment;
|
||||||
|
|
||||||
|
class OrderController extends Controller
|
||||||
|
{
|
||||||
|
use HasOrderByRequest;
|
||||||
|
use HasFilterRequest;
|
||||||
|
|
||||||
|
const ORDER_STATUS_COMPLETE = 'COMPLETED';
|
||||||
|
const ORDER_STATUS_PENDING = 'PENDING';
|
||||||
|
const ORDER_STATUS_CANCEL = 'CANCELED';
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// module check model exist and table
|
||||||
|
if (!class_exists(Order::class)) {
|
||||||
|
throw new JsonException("Order table not exist" );
|
||||||
|
}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(Request $request)
|
||||||
|
{
|
||||||
|
$order = Order::getOrdersWithDiscountAndPackage();
|
||||||
|
|
||||||
|
// Order by
|
||||||
|
$this->orderByRequest($order, $request);
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
$this->filterRequest(
|
||||||
|
builder: $order,
|
||||||
|
request: $request,
|
||||||
|
filterKeys: [
|
||||||
|
'payment_id' => self::F_TEXT,
|
||||||
|
'discount' => self::F_TEXT,
|
||||||
|
'email' => [
|
||||||
|
'type' => self::F_TEXT,
|
||||||
|
'column' => 'users.email'
|
||||||
|
],
|
||||||
|
'status' => [
|
||||||
|
'type' => self::F_NOT_CONTAIN,
|
||||||
|
'column' => 'orders.status'
|
||||||
|
],
|
||||||
|
'from_date' => [
|
||||||
|
'type' => self::F_THAN_EQ_DATETIME,
|
||||||
|
'column' => 'orders.created_at'
|
||||||
|
],
|
||||||
|
'to_date' => [
|
||||||
|
'type' => self::F_LESS_EQ_DATETIME,
|
||||||
|
'column' => 'orders.created_at'
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$responseData = array_merge(
|
||||||
|
$order->paginate($request->get('per_page'))->toArray(),
|
||||||
|
['status' => true]
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json($responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(OrderRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->input('id');
|
||||||
|
$order = Order::find($id);
|
||||||
|
$client = Client::find($order['user_id']);
|
||||||
|
$package = Package::find($order['package_id']);
|
||||||
|
|
||||||
|
$order['status'] = $request->input('status');
|
||||||
|
|
||||||
|
if ($request->input('status') == self::ORDER_STATUS_COMPLETE) {
|
||||||
|
if ($order['discount']) {
|
||||||
|
// Update discount
|
||||||
|
$discount = Discount::where('code', $order['discount'])->first();
|
||||||
|
if ($discount != null) {
|
||||||
|
$discount['user_id'] = $client->id;
|
||||||
|
$discount['email'] = $client->email;
|
||||||
|
$discount['date_used'] = now();
|
||||||
|
$discount->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update point for client
|
||||||
|
$client->point += (int) $order['point'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = -1;
|
||||||
|
if ($request->input('status') == self::ORDER_STATUS_COMPLETE) {
|
||||||
|
$status = 1;
|
||||||
|
event(
|
||||||
|
new PaymentCompleted(
|
||||||
|
payment_id: $order['payment_id'],
|
||||||
|
email: $client->email,
|
||||||
|
name: $client->name,
|
||||||
|
type: "PAYPAL",
|
||||||
|
product_name: $package->title,
|
||||||
|
point: $order->point,
|
||||||
|
discount_value: view_price((float) $package->price - (float) $order['total_price']),
|
||||||
|
total_price: $package->price
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} elseif ($request->input('status') == self::ORDER_STATUS_CANCEL) {
|
||||||
|
$status = 0;
|
||||||
|
if ($order['discount']) {
|
||||||
|
$discount = Discount::where('code', $order['discount'])->first();
|
||||||
|
$discount['status'] = 1;
|
||||||
|
$discount->save();
|
||||||
|
}
|
||||||
|
event(
|
||||||
|
new PaymentCanceled(
|
||||||
|
payment_id: $order['payment_id'],
|
||||||
|
email: $client->email,
|
||||||
|
name: $client->name
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$status = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create history
|
||||||
|
HistoryPayment::create([
|
||||||
|
'payment_id' => $order['payment_id'],
|
||||||
|
'status' => $status,
|
||||||
|
'payload' => $request->all(),
|
||||||
|
'response' =>
|
||||||
|
[
|
||||||
|
'order' => $order,
|
||||||
|
'client' => $client,
|
||||||
|
'discount' => $discount ?? [],
|
||||||
|
'message' => "Change by Admin"
|
||||||
|
]
|
||||||
|
|
||||||
|
]);
|
||||||
|
|
||||||
|
$order->save();
|
||||||
|
$client->save();
|
||||||
|
return response()->json([
|
||||||
|
'data' => $order,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Helper\Cache\PackagesCacheHelper;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Modules\Admin\app\Http\Requests\PackageRequest;
|
||||||
|
use Modules\Admin\app\Models\Package;
|
||||||
|
|
||||||
|
class PackageController extends Controller
|
||||||
|
{
|
||||||
|
public function all(PackageRequest $request)
|
||||||
|
{
|
||||||
|
$package = new Package;
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => $package->get(),
|
||||||
|
'status' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(PackageRequest $request)
|
||||||
|
{
|
||||||
|
$package = Package::create($request->all());
|
||||||
|
PackagesCacheHelper::cleanCachePackages();
|
||||||
|
return response()->json([
|
||||||
|
'data' => $package,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(PackageRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
$package = Package::find($id);
|
||||||
|
$package->update($request->all());
|
||||||
|
PackagesCacheHelper::cleanCachePackages();
|
||||||
|
return response()->json([
|
||||||
|
'data' => $package,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(PackageRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
Package::destroy($id);
|
||||||
|
PackagesCacheHelper::cleanCachePackages();
|
||||||
|
return response()->json([
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete multiple packages
|
||||||
|
public function deletes(PackageRequest $request)
|
||||||
|
{
|
||||||
|
$packages = $request->get('packages');
|
||||||
|
$ids = collect($packages)->pluck('id');
|
||||||
|
Package::whereIn('id', $ids)->delete();
|
||||||
|
PackagesCacheHelper::cleanCachePackages();
|
||||||
|
return response()->json([
|
||||||
|
'data' => $ids,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update multiple packages
|
||||||
|
public function updates(PackageRequest $request)
|
||||||
|
{
|
||||||
|
$packages = $request->get('packages');
|
||||||
|
$ids = collect($packages)->pluck('id');
|
||||||
|
|
||||||
|
foreach ($packages as $packageRequest) {
|
||||||
|
// convert to object|array to array
|
||||||
|
$packageRequest = collect($packageRequest)->toArray();
|
||||||
|
// handle array
|
||||||
|
$package = Package::find($packageRequest['id']);
|
||||||
|
if ($package) {
|
||||||
|
// exclude id field
|
||||||
|
unset($package['id']);
|
||||||
|
$package->update($packageRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PackagesCacheHelper::cleanCachePackages();
|
||||||
|
return response()->json([
|
||||||
|
'data' => Package::whereIn('id', $ids)->get(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\SerialNumberCheck;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use App\Traits\HasFilterRequest;
|
||||||
|
use App\Traits\HasOrderByRequest;
|
||||||
|
use JsonException;
|
||||||
|
|
||||||
|
class SNCheckController extends Controller
|
||||||
|
{
|
||||||
|
use HasOrderByRequest;
|
||||||
|
use HasFilterRequest;
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// module check model exist and table
|
||||||
|
if (!class_exists(SerialNumberCheck::class)) {
|
||||||
|
throw new JsonException("SerialNumberCheck table not exist");
|
||||||
|
}
|
||||||
|
;
|
||||||
|
}
|
||||||
|
public function get(Request $request)
|
||||||
|
{
|
||||||
|
$history = SerialNumberCheck::getHistoryWithUserInfo();
|
||||||
|
|
||||||
|
// Order by
|
||||||
|
$this->orderByRequest($history, $request);
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
$this->filterRequest(
|
||||||
|
builder: $history,
|
||||||
|
request: $request,
|
||||||
|
filterKeys: [
|
||||||
|
'keyword' => [
|
||||||
|
'type' => self::F_TEXT,
|
||||||
|
'column' => 'serial_number_check.keyword'
|
||||||
|
],
|
||||||
|
'email' => [
|
||||||
|
'type' => self::F_TEXT,
|
||||||
|
'column' => 'users.email'
|
||||||
|
],
|
||||||
|
'status' => [
|
||||||
|
'type' => self::F_NOT_CONTAIN,
|
||||||
|
'column' => 'serial_number_check.status'
|
||||||
|
],
|
||||||
|
'from_date' => [
|
||||||
|
'type' => self::F_THAN_EQ_DATETIME,
|
||||||
|
'column' => 'serial_number_check.created_at'
|
||||||
|
],
|
||||||
|
'to_date' => [
|
||||||
|
'type' => self::F_LESS_EQ_DATETIME,
|
||||||
|
'column' => 'serial_number_check.created_at'
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$responseData = array_merge(
|
||||||
|
$history->paginate($request->get('per_page'))->toArray(),
|
||||||
|
['status' => true]
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json($responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showDetail(Request $request)
|
||||||
|
{
|
||||||
|
$id = $request->input('id');
|
||||||
|
$searchRow = SerialNumberCheck::find($id);
|
||||||
|
if ($searchRow) {
|
||||||
|
$user = $searchRow->user()->get();
|
||||||
|
$tracking = $searchRow->tracking()->get();
|
||||||
|
$trackingDetail = $tracking->map(function ($item) {
|
||||||
|
return [
|
||||||
|
'current_point' => $item->current_point,
|
||||||
|
'use_point' => $item->use_point,
|
||||||
|
'created_at' => $item->created_at
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'data_search' => $searchRow,
|
||||||
|
'user' => $user[0],
|
||||||
|
'tracking' => $trackingDetail
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json(['data' => $response, 'status' => true]);
|
||||||
|
}else{
|
||||||
|
return response()->json(['data' => [], 'status' => false]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request): RedirectResponse
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the specified resource.
|
||||||
|
*/
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
return view('admin::show');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
return view('admin::edit');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(Request $request, $id): RedirectResponse
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Helper\Cache\SettingCacheHelper;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Modules\Admin\app\Http\Requests\SettingRequest;
|
||||||
|
use Modules\Admin\app\Models\Setting;
|
||||||
|
|
||||||
|
class SettingController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'data' => Setting::first(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateOrCreate(SettingRequest $request)
|
||||||
|
{
|
||||||
|
if ($request->has('logo')) {
|
||||||
|
$file = $request->file('logo');
|
||||||
|
$path = 'setting/logo.' . $file->getClientOriginalExtension();
|
||||||
|
// save to local
|
||||||
|
Storage::disk('public')->put(
|
||||||
|
path: $path,
|
||||||
|
contents: $file->getContent()
|
||||||
|
);
|
||||||
|
$request->request->set('logo', $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('favicon')) {
|
||||||
|
$file = $request->file('favicon');
|
||||||
|
$path = 'setting/favicon.' . $file->getClientOriginalExtension();
|
||||||
|
// save to local
|
||||||
|
Storage::disk('public')->put(
|
||||||
|
path: $path,
|
||||||
|
contents: $file->getContent()
|
||||||
|
);
|
||||||
|
$request->request->set('favicon', $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Only 1 row
|
||||||
|
Setting::updateOrCreate([
|
||||||
|
'id' => 1
|
||||||
|
], $request->request->all());
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => Setting::first(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'code' => $e->getCode(),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'status' => false
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clearCache()
|
||||||
|
{
|
||||||
|
Artisan::call('key:generate');
|
||||||
|
Artisan::call('cache:clear');
|
||||||
|
return response()->json([
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Traits\HasFilterRequest;
|
||||||
|
use App\Traits\HasOrderByRequest;
|
||||||
|
use App\Traits\HasSearchRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Modules\Admin\app\Http\Requests\DiscountRequest;
|
||||||
|
use Modules\Admin\app\Models\Admin;
|
||||||
|
use Modules\Admin\app\Models\Discount;
|
||||||
|
use Modules\Admin\app\Models\Tracking;
|
||||||
|
|
||||||
|
class TrackingController extends Controller
|
||||||
|
{
|
||||||
|
use HasOrderByRequest;
|
||||||
|
use HasFilterRequest;
|
||||||
|
use HasSearchRequest;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
// Bỏ qua middleware 'checkApiToken' cho hàm 'myFunction'
|
||||||
|
$this->middleware('api')->except('create');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(Request $request)
|
||||||
|
{
|
||||||
|
$tracking = new Tracking;
|
||||||
|
|
||||||
|
// Order by
|
||||||
|
$this->orderByRequest($tracking, $request);
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
$this->filterRequest(
|
||||||
|
builder: $tracking,
|
||||||
|
request: $request,
|
||||||
|
filterKeys: [
|
||||||
|
'created_at' => self::F_IN_DATETIME,
|
||||||
|
'time_string' => self::F_TEXT,
|
||||||
|
'name' => self::F_TEXT,
|
||||||
|
'status' => self::F_TEXT
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->searchRequest(
|
||||||
|
builder: $tracking,
|
||||||
|
value: $request->get('search'),
|
||||||
|
fields: [
|
||||||
|
'name',
|
||||||
|
'time_string',
|
||||||
|
'status'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$responseData = array_merge(
|
||||||
|
$tracking->paginate($request->get('per_page'))->toArray(),
|
||||||
|
['status' => true]
|
||||||
|
);
|
||||||
|
|
||||||
|
return response()->json($responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(Request $request)
|
||||||
|
{
|
||||||
|
$payload = $request->only(['name', 'time_string', 'status']);
|
||||||
|
$user = Admin::where('name', $payload['name'])->first();
|
||||||
|
if($user){
|
||||||
|
$payload['user_id'] = $user->id;
|
||||||
|
$tracking = Tracking::create($payload);
|
||||||
|
return response()->json([
|
||||||
|
'data' => $tracking,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'data' => "USER NOT EXIST",
|
||||||
|
'status' => false
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
$discount = Discount::find($id);
|
||||||
|
$payload = $request->all();
|
||||||
|
|
||||||
|
if ($discount) {
|
||||||
|
$discount->update($payload);
|
||||||
|
}
|
||||||
|
return response()->json([
|
||||||
|
'data' => $discount,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$id = $request->get('id');
|
||||||
|
|
||||||
|
Discount::destroy($id);
|
||||||
|
return response()->json([
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete multiple discounts
|
||||||
|
public function deletes(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$discounts = $request->get('discounts');
|
||||||
|
$ids = collect($discounts)->pluck('id');
|
||||||
|
Discount::whereIn('id', $ids)->delete();
|
||||||
|
return response()->json([
|
||||||
|
'data' => $ids,
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update multiple discounts
|
||||||
|
public function updates(DiscountRequest $request)
|
||||||
|
{
|
||||||
|
$discounts = $request->get('discounts');
|
||||||
|
$ids = collect($discounts)->pluck('id');
|
||||||
|
|
||||||
|
foreach ($discounts as $discountRequest) {
|
||||||
|
// convert to object|array to array
|
||||||
|
$discountRequest = collect($discountRequest)->toArray();
|
||||||
|
// handle array
|
||||||
|
$discount = Discount::find($discountRequest['id']);
|
||||||
|
if ($discount) {
|
||||||
|
// exclude id field
|
||||||
|
unset($discount['id']);
|
||||||
|
|
||||||
|
$discount->update($discountRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response()->json([
|
||||||
|
'data' => Discount::whereIn('id', $ids)->get(),
|
||||||
|
'status' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Auth\Middleware\Authenticate as MiddlewareAuthenticate;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
|
use Modules\Admin\app\Models\Admin;
|
||||||
|
use Tymon\JWTAuth\Facades\JWTAuth;
|
||||||
|
use Tymon\JWTAuth\JWTAuth as JWTAuthJWTAuth;
|
||||||
|
|
||||||
|
class AdminMiddleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @param \Closure $next
|
||||||
|
*/
|
||||||
|
public function handle($request, Closure $next, ...$guards)
|
||||||
|
{
|
||||||
|
if (auth('admins')->check()) {
|
||||||
|
return $next($request);
|
||||||
|
} else {
|
||||||
|
return response()->json([
|
||||||
|
'Unauthenticated.'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class BannerRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$actionMethod = $this->route()->getActionMethod();
|
||||||
|
|
||||||
|
$rules = [
|
||||||
|
'title' => 'max:255',
|
||||||
|
'link' => 'nullable|max:255',
|
||||||
|
'image' => 'file|mimes:jpeg,jpg,png,gif|max:2048',
|
||||||
|
'is_active' => 'in:true,false',
|
||||||
|
];
|
||||||
|
|
||||||
|
// single
|
||||||
|
if ($actionMethod === 'create') {
|
||||||
|
$rules['title'] = 'required|' . $rules['title'];
|
||||||
|
}
|
||||||
|
if ($actionMethod === 'update') {
|
||||||
|
$rules['id'] = 'required|exists:banner,id';
|
||||||
|
$rules['title'] = 'required|' . $rules['title'];
|
||||||
|
}
|
||||||
|
if ($actionMethod === 'delete') {
|
||||||
|
$rules['id'] = 'required|exists:banner,id';
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiple
|
||||||
|
if ($actionMethod === 'creates') {
|
||||||
|
$rules = [
|
||||||
|
'banners.*.id' => 'required|exists:banner,id',
|
||||||
|
'banners.*.title' => $rules['title'],
|
||||||
|
'banners.*.link' => $rules['link'],
|
||||||
|
'banners.*.image' => $rules['image'],
|
||||||
|
'banners.*.is_active' => $rules['is_active'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if ($actionMethod === 'updates') {
|
||||||
|
$rules = [
|
||||||
|
'banners.*.title' => $rules['title'],
|
||||||
|
'banners.*.link' => $rules['link'],
|
||||||
|
'banners.*.image' => $rules['image'],
|
||||||
|
'banners.*.is_active' => $rules['is_active'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if ($actionMethod === 'deletes') {
|
||||||
|
$rules = [
|
||||||
|
'banners.*.id' => 'required|exists:banner,id'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use App\Models\Client;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Modules\Admin\app\Rules\PasswordRule;
|
||||||
|
use Modules\Admin\app\Rules\PointRule;
|
||||||
|
|
||||||
|
class ClientRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$actionMethod = $this->route()->getActionMethod();
|
||||||
|
$rules = [
|
||||||
|
'id' => [
|
||||||
|
'exists' => 'exists:' . (new Client)->getTable() . ',id'
|
||||||
|
],
|
||||||
|
'password' => ['nullable', new PasswordRule],
|
||||||
|
'name' => 'min:5|max:100',
|
||||||
|
'email' => 'email|nullable|unique:' . (new Client)->getTable(),
|
||||||
|
'phone' => 'max:50|nullable',
|
||||||
|
'company' => 'max:100|nullable',
|
||||||
|
'point' => [
|
||||||
|
new PointRule,
|
||||||
|
'nullable'
|
||||||
|
],
|
||||||
|
'avatar' => 'file|mimes:jpeg,jpg,png|nullable',
|
||||||
|
'country_code' => 'exists:h_country,code|max:2',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($actionMethod === 'create') {
|
||||||
|
$rules = array_merge($rules, [
|
||||||
|
'name' => 'required|' . $rules['name']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($actionMethod === 'update') {
|
||||||
|
unset($rules['email'], $rules['avatar']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($actionMethod === 'deletes') {
|
||||||
|
$rules = array_merge($rules, [
|
||||||
|
'clients.*.id' => 'required|' . $rules['id']['exists'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($actionMethod === 'updates') {
|
||||||
|
$rules = array_merge($rules, [
|
||||||
|
'clients.*.id' => 'required|' . $rules['id']['exists'],
|
||||||
|
'clients.*.password' => $rules['password'],
|
||||||
|
'clients.*.name' => $rules['name'],
|
||||||
|
'clients.*.email' => $rules['email'],
|
||||||
|
'clients.*.phone' => $rules['phone'],
|
||||||
|
'clients.*.company' => $rules['company'],
|
||||||
|
'clients.*.point' => $rules['point'],
|
||||||
|
'clients.*.avatar' => $rules['avatar'],
|
||||||
|
'clients.*.country_code' => $rules['country_code'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($actionMethod === 'creates') {
|
||||||
|
$rules = array_merge($rules, [
|
||||||
|
'clients.*.name' => 'required|' . $rules['name'],
|
||||||
|
'clients.*.email' => 'required|' . $rules['email'],
|
||||||
|
'clients.*.password' => $rules['password'],
|
||||||
|
'clients.*.phone' => $rules['phone'],
|
||||||
|
'clients.*.company' => $rules['company'],
|
||||||
|
'clients.*.point' => $rules['point'],
|
||||||
|
'clients.*.avatar' => $rules['avatar'],
|
||||||
|
'clients.*.country_code' => $rules['country_code'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class ContactRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class CustomThemeRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Modules\Admin\app\Rules\TimezoneOffsetRule;
|
||||||
|
|
||||||
|
class DashboardRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$actionMethod = $this->route()->getActionMethod();
|
||||||
|
$rules = array();
|
||||||
|
|
||||||
|
if (in_array($actionMethod, [
|
||||||
|
'statisticKeywordsByMonth',
|
||||||
|
'statisticRevenuesByMonth'
|
||||||
|
])) {
|
||||||
|
$rules = [
|
||||||
|
'timezone_offset' => [
|
||||||
|
'required',
|
||||||
|
new TimezoneOffsetRule,
|
||||||
|
],
|
||||||
|
'month' => [
|
||||||
|
'integer',
|
||||||
|
'between:1,12',
|
||||||
|
],
|
||||||
|
'year' => [
|
||||||
|
'integer'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Modules\Admin\app\Models\Discount;
|
||||||
|
use Modules\Admin\app\Models\DiscountType;
|
||||||
|
use Modules\Admin\app\Rules\PercentRule;
|
||||||
|
use Modules\Admin\app\Rules\PriceRule;
|
||||||
|
|
||||||
|
class DiscountRequest extends FormRequest
|
||||||
|
{
|
||||||
|
protected function checkValue(string $attribute, $value, Closure $fail)
|
||||||
|
{
|
||||||
|
function checkPrice(string $attribute, $value, $fail)
|
||||||
|
{
|
||||||
|
if (!PriceRule::check($value)) {
|
||||||
|
$fail(PriceRule::message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function checkPercent(string $attribute, $value, $fail)
|
||||||
|
{
|
||||||
|
if (!PercentRule::check($value)) {
|
||||||
|
$fail(PercentRule::message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->has('discounts')) {
|
||||||
|
foreach ($this->get('discounts') as $discountRequest) {
|
||||||
|
if ($discountRequest['discount_type_id'] === 1) {
|
||||||
|
checkPrice($attribute, $value, $fail);
|
||||||
|
} else if ($discountRequest['discount_type_id'] === 2) {
|
||||||
|
checkPercent($attribute, $value, $fail);
|
||||||
|
} else {
|
||||||
|
$fail("The {$attribute} is invalid.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($this->get('discount_type_id') === 1) {
|
||||||
|
checkPrice($attribute, $value, $fail);
|
||||||
|
} else if ($this->get('discount_type_id') === 2) {
|
||||||
|
checkPercent($attribute, $value, $fail);
|
||||||
|
} else {
|
||||||
|
$fail("The {$attribute} is invalid.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$actionMethod = $this->route()->getActionMethod();
|
||||||
|
$rules = [];
|
||||||
|
|
||||||
|
// update single
|
||||||
|
if ($actionMethod == 'update') {
|
||||||
|
$rules = [
|
||||||
|
'id' => 'required|exists:' . (new Discount())->getTable(),
|
||||||
|
'discount_type_id' => 'exists:' . (new DiscountType)->getTable() . ',id',
|
||||||
|
'value' => function (string $attribute, $value, Closure $fail) {
|
||||||
|
$this->checkValue($attribute, $value, $fail);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if ($actionMethod == 'create') {
|
||||||
|
$rules = [
|
||||||
|
'discount_type_id' => 'exists:' . (new DiscountType)->getTable() . ',id',
|
||||||
|
'value' => function (string $attribute, $value, Closure $fail) {
|
||||||
|
$this->checkValue($attribute, $value, $fail);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiple
|
||||||
|
if ($actionMethod == 'updates') {
|
||||||
|
$rules = [
|
||||||
|
'discounts.*.id' => 'required|exists:' . (new Discount())->getTable(),
|
||||||
|
'discounts.*.discount_type_id' => 'exists:' . (new DiscountType)->getTable() . ',id',
|
||||||
|
'discounts.*.value' => function (string $attribute, $value, Closure $fail) {
|
||||||
|
$this->checkValue($attribute, $value, $fail);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if ($actionMethod == 'creates') {
|
||||||
|
$rules = [
|
||||||
|
'discounts.*.id' => 'required|exists:' . (new Discount())->getTable(),
|
||||||
|
'discounts.*.discount_type_id' => 'exists:' . (new DiscountType)->getTable() . ',id',
|
||||||
|
'discounts.*.value' => function (string $attribute, $value, Closure $fail) {
|
||||||
|
$this->checkValue($attribute, $value, $fail);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// single
|
||||||
|
if ($actionMethod == 'delete') {
|
||||||
|
$rules = [
|
||||||
|
'id' => 'required|exists:' . (new Discount())->getTable()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiple
|
||||||
|
if ($actionMethod == 'deletes') {
|
||||||
|
$rules = [
|
||||||
|
'discounts.*.id' => 'required|exists:' . (new Discount())->getTable()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_merge([
|
||||||
|
'status' => 'in:0,1,true,false',
|
||||||
|
'active_date' => 'size:10', // as timestamp unix
|
||||||
|
'expiry' => 'size:10', // as timestamp unix
|
||||||
|
'date_used' => 'size:10', // as timestamp unix
|
||||||
|
'discounts.*.status' => 'in:0,1,true,false',
|
||||||
|
], $rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Modules\Admin\app\Models\DiscountType;
|
||||||
|
|
||||||
|
class DiscountTypeRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class OrderRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => 'required',
|
||||||
|
'status' => 'max:20|required',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Modules\Admin\app\Models\Package;
|
||||||
|
use Modules\Admin\app\Rules\PointRule;
|
||||||
|
use Modules\Admin\app\Rules\PriceRule;
|
||||||
|
|
||||||
|
class PackageRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$actionMethod = $this->route()->getActionMethod();
|
||||||
|
$rules = [];
|
||||||
|
|
||||||
|
// single
|
||||||
|
if ($actionMethod == 'update') {
|
||||||
|
$rules = [
|
||||||
|
'id' => 'required|exists:' . (new Package())->getTable(),
|
||||||
|
'point' => new PointRule,
|
||||||
|
'price' => new PriceRule,
|
||||||
|
'title' => 'max:127', // from paypal
|
||||||
|
'description' => 'max:127'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($actionMethod == 'create') {
|
||||||
|
$rules = [
|
||||||
|
'point' => new PointRule,
|
||||||
|
'price' => new PriceRule
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiple
|
||||||
|
if ($actionMethod == 'updates') {
|
||||||
|
$rules = [
|
||||||
|
'packages.*.id' => 'required|exists:' . (new Package())->getTable(),
|
||||||
|
'packages.*.point' => new PointRule,
|
||||||
|
'packages.*.price' => new PriceRule,
|
||||||
|
'packages.*.title' => 'max:127',
|
||||||
|
'packages.*.description' => 'max:127',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// single
|
||||||
|
if ($actionMethod == 'delete') {
|
||||||
|
$rules = [
|
||||||
|
'id' => 'required|exists:' . (new Package())->getTable()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiple
|
||||||
|
if ($actionMethod == 'deletes') {
|
||||||
|
$rules = [
|
||||||
|
'packages.*.id' => 'required|exists:' . (new Package())->getTable()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_merge([
|
||||||
|
'status' => 'in:0,1',
|
||||||
|
'packages.*.status' => 'in:0,1',
|
||||||
|
], $rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class SettingRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'page_title' => 'max:255',
|
||||||
|
'email' => 'max:100',
|
||||||
|
'phone' => 'max:20',
|
||||||
|
'meta_title' => 'max:255',
|
||||||
|
'meta_description' => 'max:255',
|
||||||
|
'meta_keyword' => 'max:255',
|
||||||
|
'facebook' => 'max:255',
|
||||||
|
'twitter' => 'max:255',
|
||||||
|
'linkedin' => 'max:255',
|
||||||
|
'license' => 'max:255',
|
||||||
|
'address' => 'max:255',
|
||||||
|
'favicon' => 'file|mimes:jpeg,jpg,png,gif',
|
||||||
|
'logo' => 'file|mimes:jpeg,jpg,png,gif'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
use Illuminate\Support\Facades\Config;
|
||||||
|
use Laravel\Sanctum\HasApiTokens;
|
||||||
|
use Spatie\Permission\Traits\HasRoles;
|
||||||
|
use Tymon\JWTAuth\Contracts\JWTSubject;
|
||||||
|
use Tymon\JWTAuth\Facades\JWTAuth;
|
||||||
|
|
||||||
|
class Admin extends Authenticatable implements JWTSubject
|
||||||
|
{
|
||||||
|
use HasApiTokens, HasFactory, Notifiable;
|
||||||
|
use HasRoles;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->table = 'admin';
|
||||||
|
$this->guarded = [];
|
||||||
|
$this->hidden = [
|
||||||
|
'password',
|
||||||
|
'forgot_code',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getTokenByAuth(): string|null
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$id = auth('admins')->user()->id;
|
||||||
|
return JWTAuth::fromUser(self::find($id));
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the identifier that will be stored in the subject claim of the JWT.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getJWTIdentifier()
|
||||||
|
{
|
||||||
|
return $this->getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a key value array, containing any custom claims to be added to the JWT.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getJWTCustomClaims()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Models;
|
||||||
|
|
||||||
|
use App\Traits\HasCacheModel;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Modules\Admin\Database\factories\CustomThemeFactory;
|
||||||
|
|
||||||
|
class CustomTheme extends Model
|
||||||
|
{
|
||||||
|
// use HasFactory;
|
||||||
|
use HasFactory;
|
||||||
|
use HasCacheModel;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->table = 'custom_theme';
|
||||||
|
$this->guarded = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Dashboard extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Models;
|
||||||
|
|
||||||
|
use App\Helper\Constant\RequestConstant;
|
||||||
|
use App\Traits\HasCacheModel;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Modules\Admin\Database\factories\DiscountFactory;
|
||||||
|
|
||||||
|
class Discount extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use HasCacheModel;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->table = 'discount';
|
||||||
|
$this->guarded = [];
|
||||||
|
$this->appends = [
|
||||||
|
'discount_type',
|
||||||
|
'discount_unit',
|
||||||
|
];
|
||||||
|
$this->casts = [
|
||||||
|
'active_date' => 'datetime',
|
||||||
|
'expiry' => 'datetime',
|
||||||
|
'date_used' => 'datetime',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createWithDefault(array $data): Discount
|
||||||
|
{
|
||||||
|
$discount = new self;
|
||||||
|
|
||||||
|
$discount = $discount->create(array_merge([
|
||||||
|
'active_date' => now(),
|
||||||
|
'code' => Discount::generateCode()
|
||||||
|
], $data));
|
||||||
|
|
||||||
|
return $discount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function generateCode()
|
||||||
|
{
|
||||||
|
$code = Str::random(6);
|
||||||
|
if (self::where('code', $code)->count()) {
|
||||||
|
return static::generateCode();
|
||||||
|
}
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom display get{field_name}Attribute
|
||||||
|
public function getDiscountTypeAttribute()
|
||||||
|
{
|
||||||
|
return DiscountType::getByCache()
|
||||||
|
->where('id', $this->discount_type_id)
|
||||||
|
->value('name');
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom display get{field_name}Attribute
|
||||||
|
public function getDiscountUnitAttribute()
|
||||||
|
{
|
||||||
|
return DiscountType::getByCache()
|
||||||
|
->where('id', $this->discount_type_id)
|
||||||
|
->value('unit');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function discountType(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(DiscountType::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Models;
|
||||||
|
|
||||||
|
use App\Traits\HasCacheModel;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Modules\Admin\Database\factories\DiscountTypeFactory;
|
||||||
|
|
||||||
|
class DiscountType extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use HasCacheModel;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->table = 'discount_type';
|
||||||
|
$this->guarded = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use App\Traits\HasCacheModel;
|
||||||
|
|
||||||
|
class Package extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use HasCacheModel;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->table = 'package';
|
||||||
|
$this->guarded = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Models;
|
||||||
|
|
||||||
|
use App\Traits\HasCacheModel;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Modules\Admin\Database\factories\SettingFactory;
|
||||||
|
|
||||||
|
class Setting extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use HasCacheModel;
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->table = 'setting';
|
||||||
|
$this->guarded = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function _getKey()
|
||||||
|
{
|
||||||
|
$keyLength = strlen(env('APP_KEY'));
|
||||||
|
return substr(env('APP_KEY'), round($keyLength / 2), $keyLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom display get{file_name}Attribute()
|
||||||
|
public function getFaviconAttribute($value)
|
||||||
|
{
|
||||||
|
if ($value) {
|
||||||
|
return asset("/storage/$value?key=" . $this->_getKey());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom display get{file_name}Attribute()
|
||||||
|
public function getLogoAttribute($value)
|
||||||
|
{
|
||||||
|
if ($value) {
|
||||||
|
return asset("/storage/$value?key=" . $this->_getKey());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use App\Traits\HasCacheModel;
|
||||||
|
|
||||||
|
class Tracking extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
use HasCacheModel;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->table = 'tracking';
|
||||||
|
$this->guarded = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Blade;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
class AdminServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
protected string $moduleName = 'Admin';
|
||||||
|
|
||||||
|
protected string $moduleNameLower = 'admin';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boot the application events.
|
||||||
|
*/
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
$this->registerCommands();
|
||||||
|
$this->registerCommandSchedules();
|
||||||
|
$this->registerTranslations();
|
||||||
|
$this->registerConfig();
|
||||||
|
$this->registerViews();
|
||||||
|
$this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the service provider.
|
||||||
|
*/
|
||||||
|
public function register(): void
|
||||||
|
{
|
||||||
|
$this->app->register(RouteServiceProvider::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register commands in the format of Command::class
|
||||||
|
*/
|
||||||
|
protected function registerCommands(): void
|
||||||
|
{
|
||||||
|
// $this->commands([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register command Schedules.
|
||||||
|
*/
|
||||||
|
protected function registerCommandSchedules(): void
|
||||||
|
{
|
||||||
|
// $this->app->booted(function () {
|
||||||
|
// $schedule = $this->app->make(Schedule::class);
|
||||||
|
// $schedule->command('inspire')->hourly();
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register translations.
|
||||||
|
*/
|
||||||
|
public function registerTranslations(): void
|
||||||
|
{
|
||||||
|
$langPath = resource_path('lang/modules/'.$this->moduleNameLower);
|
||||||
|
|
||||||
|
if (is_dir($langPath)) {
|
||||||
|
$this->loadTranslationsFrom($langPath, $this->moduleNameLower);
|
||||||
|
$this->loadJsonTranslationsFrom($langPath);
|
||||||
|
} else {
|
||||||
|
$this->loadTranslationsFrom(module_path($this->moduleName, 'lang'), $this->moduleNameLower);
|
||||||
|
$this->loadJsonTranslationsFrom(module_path($this->moduleName, 'lang'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register config.
|
||||||
|
*/
|
||||||
|
protected function registerConfig(): void
|
||||||
|
{
|
||||||
|
$this->publishes([module_path($this->moduleName, 'config/config.php') => config_path($this->moduleNameLower.'.php')], 'config');
|
||||||
|
$this->mergeConfigFrom(module_path($this->moduleName, 'config/config.php'), $this->moduleNameLower);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register views.
|
||||||
|
*/
|
||||||
|
public function registerViews(): void
|
||||||
|
{
|
||||||
|
$viewPath = resource_path('views/modules/'.$this->moduleNameLower);
|
||||||
|
$sourcePath = module_path($this->moduleName, 'resources/views');
|
||||||
|
|
||||||
|
$this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower.'-module-views']);
|
||||||
|
|
||||||
|
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower);
|
||||||
|
|
||||||
|
$componentNamespace = str_replace('/', '\\', config('modules.namespace').'\\'.$this->moduleName.'\\'.config('modules.paths.generator.component-class.path'));
|
||||||
|
Blade::componentNamespace($componentNamespace, $this->moduleNameLower);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the services provided by the provider.
|
||||||
|
*/
|
||||||
|
public function provides(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPublishableViewPaths(): array
|
||||||
|
{
|
||||||
|
$paths = [];
|
||||||
|
foreach (config('view.paths') as $path) {
|
||||||
|
if (is_dir($path.'/modules/'.$this->moduleNameLower)) {
|
||||||
|
$paths[] = $path.'/modules/'.$this->moduleNameLower;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||||
|
|
||||||
|
class RouteServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The module namespace to assume when generating URLs to actions.
|
||||||
|
*/
|
||||||
|
protected string $moduleNamespace = 'Modules\Admin\app\Http\Controllers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before routes are registered.
|
||||||
|
*
|
||||||
|
* Register any model bindings or pattern based filters.
|
||||||
|
*/
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
parent::boot();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the routes for the application.
|
||||||
|
*/
|
||||||
|
public function map(): void
|
||||||
|
{
|
||||||
|
$this->mapApiRoutes();
|
||||||
|
|
||||||
|
$this->mapWebRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the "web" routes for the application.
|
||||||
|
*
|
||||||
|
* These routes all receive session state, CSRF protection, etc.
|
||||||
|
*/
|
||||||
|
protected function mapWebRoutes(): void
|
||||||
|
{
|
||||||
|
Route::middleware('web')
|
||||||
|
->namespace($this->moduleNamespace)
|
||||||
|
->group(module_path('Admin', '/routes/web.php'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the "api" routes for the application.
|
||||||
|
*
|
||||||
|
* These routes are typically stateless.
|
||||||
|
*/
|
||||||
|
protected function mapApiRoutes(): void
|
||||||
|
{
|
||||||
|
Route::prefix('api')
|
||||||
|
->middleware('api')
|
||||||
|
->namespace($this->moduleNamespace)
|
||||||
|
->group(module_path('Admin', '/routes/api.php'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Rules;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Validation\Rules\Password;
|
||||||
|
|
||||||
|
class PasswordRule implements ValidationRule
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the validation rule.
|
||||||
|
*/
|
||||||
|
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||||
|
{
|
||||||
|
$isLength = strlen($value) >= 8;
|
||||||
|
$isUppercase = preg_match('/[A-Z]/', $value);
|
||||||
|
$isNumber = preg_match('/[0-9]/', $value);
|
||||||
|
$isSymbol = preg_match('/\!|\@|\#|\$|\%|\^|\&|\*|\-/', $value);
|
||||||
|
if (!$isLength) {
|
||||||
|
$fail('Password must be at least 8 characters large.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$isUppercase) {
|
||||||
|
$fail('Password must have capital letters.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$isNumber) {
|
||||||
|
$fail('Password must have number.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$isSymbol) {
|
||||||
|
$fail('Password must have symbol ! @ # $ % ^ & * -');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Rules;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
|
|
||||||
|
class PercentRule implements ValidationRule
|
||||||
|
{
|
||||||
|
static public function check($value): bool
|
||||||
|
{
|
||||||
|
$percent = (float) $value;
|
||||||
|
|
||||||
|
return ((1 <= $percent) && ($percent <= 99));
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function message(): string
|
||||||
|
{
|
||||||
|
return 'The percent must be from 1% to 100%.';
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Run the validation rule.
|
||||||
|
*/
|
||||||
|
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||||
|
{
|
||||||
|
if (!$this->check($value)) {
|
||||||
|
$fail($this->message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Rules;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
|
|
||||||
|
class PointRule implements ValidationRule
|
||||||
|
{
|
||||||
|
static public function check($value): bool
|
||||||
|
{
|
||||||
|
$point = (int) $value;
|
||||||
|
|
||||||
|
return ((0 <= $point) && ($point <= 1000000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function message(): string
|
||||||
|
{
|
||||||
|
return 'The point must be from 0 to 1,000,000,000';
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Run the validation rule.
|
||||||
|
*/
|
||||||
|
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||||
|
{
|
||||||
|
if (!$this->check($value)) {
|
||||||
|
$fail($this->message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Rules;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
|
|
||||||
|
class PriceRule implements ValidationRule
|
||||||
|
{
|
||||||
|
static public function check($value): bool
|
||||||
|
{
|
||||||
|
$price = (float) $value;
|
||||||
|
|
||||||
|
return ((1 <= $price) && ($price <= 1000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function message(): string
|
||||||
|
{
|
||||||
|
return 'The price must be from 1$ to 1,000,000$.';
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Run the validation rule.
|
||||||
|
*/
|
||||||
|
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||||
|
{
|
||||||
|
if (!$this->check($value)) {
|
||||||
|
$fail($this->message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Admin\app\Rules;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
|
|
||||||
|
class TimezoneOffsetRule implements ValidationRule
|
||||||
|
{
|
||||||
|
public static function check($value)
|
||||||
|
{
|
||||||
|
$pattern = '/^[+-]\d{2}:\d{2}$/';
|
||||||
|
return preg_match($pattern, $value) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function message(): string
|
||||||
|
{
|
||||||
|
return "Your timezone offset is incorrectly transmitted. Please format as follows: '+00:00', '+11:00'!";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the validation rule.
|
||||||
|
*/
|
||||||
|
public function validate(string $attribute, mixed $value, Closure $fail): void
|
||||||
|
{
|
||||||
|
if (!$this->check($value)) {
|
||||||
|
$fail($this->message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "nwidart/admin",
|
||||||
|
"description": "",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Widart",
|
||||||
|
"email": "n.widart@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [],
|
||||||
|
"aliases": {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Modules\\Admin\\": "",
|
||||||
|
"Modules\\Admin\\App\\": "app/",
|
||||||
|
"Modules\\Admin\\Database\\Factories\\": "database/factories/",
|
||||||
|
"Modules\\Admin\\Database\\Seeders\\": "database/seeders/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"Modules\\Admin\\Tests\\": "tests/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'name' => 'Admin',
|
||||||
|
];
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('admin', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('email')->unique();
|
||||||
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
|
$table->string('forgot_code')->nullable();
|
||||||
|
$table->string('password');
|
||||||
|
$table->rememberToken();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
|
||||||
|
DB::table('admin')->insert([
|
||||||
|
[
|
||||||
|
'name' => 'Kai',
|
||||||
|
'email' => 'kai.t@apactech.io',
|
||||||
|
'password' => bcrypt('Pay@2023'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Joseph',
|
||||||
|
'email' => 'joseph.le@apactech.io',
|
||||||
|
'password' => bcrypt('Pay@2023'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Rose',
|
||||||
|
'email' => 'rose.h@apactech.io',
|
||||||
|
'password' => bcrypt('Pay@2023'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Huynh',
|
||||||
|
'email' => 'huynh220592@gmail.com',
|
||||||
|
'password' => bcrypt('Pay@2023'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Admin',
|
||||||
|
'email' => 'admin@apactech.io',
|
||||||
|
'password' => bcrypt('Pay@2023'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Thuan',
|
||||||
|
'email' => 'alan.ha@apactech.io',
|
||||||
|
'password' => bcrypt('Pay@2023'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'Jason',
|
||||||
|
'email' => 'jason@apactech.io',
|
||||||
|
'password' => bcrypt('Pay@2023'),
|
||||||
|
],
|
||||||
|
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('admin');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('setting', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('page_title')->nullable();
|
||||||
|
$table->string('email', 100)->nullable();
|
||||||
|
$table->string('phone', 20)->nullable();
|
||||||
|
$table->string('meta_title')->nullable();
|
||||||
|
$table->string('meta_description')->nullable();
|
||||||
|
$table->string('meta_keyword')->nullable();
|
||||||
|
$table->string('facebook')->nullable();
|
||||||
|
$table->string('twitter')->nullable();
|
||||||
|
$table->string('linkedin')->nullable();
|
||||||
|
$table->string('license')->nullable();
|
||||||
|
$table->string('address')->nullable();
|
||||||
|
$table->string('favicon')->nullable();
|
||||||
|
$table->string('logo')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('setting');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('custom_theme', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->longText('css')->nullable();
|
||||||
|
$table->longText('js')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('custom_theme');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"name": "Admin",
|
||||||
|
"alias": "admin",
|
||||||
|
"description": "",
|
||||||
|
"keywords": [],
|
||||||
|
"priority": 0,
|
||||||
|
"providers": [
|
||||||
|
"Modules\\Admin\\app\\Providers\\AdminServiceProvider"
|
||||||
|
],
|
||||||
|
"files": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"axios": "^1.1.2",
|
||||||
|
"laravel-vite-plugin": "^0.7.5",
|
||||||
|
"sass": "^1.69.5",
|
||||||
|
"postcss": "^8.3.7",
|
||||||
|
"vite": "^4.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
@extends('admin::layouts.master')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<h1>Hello World</h1>
|
||||||
|
|
||||||
|
<p>Module: {!! config('admin.name') !!}</p>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
|
||||||
|
<title>Admin Module - {{ config('app.name', 'Laravel') }}</title>
|
||||||
|
|
||||||
|
<meta name="description" content="{{ $description ?? '' }}">
|
||||||
|
<meta name="keywords" content="{{ $keywords ?? '' }}">
|
||||||
|
<meta name="author" content="{{ $author ?? '' }}">
|
||||||
|
|
||||||
|
<!-- Fonts -->
|
||||||
|
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||||
|
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
|
||||||
|
|
||||||
|
{{-- Vite CSS --}}
|
||||||
|
{{-- {{ module_vite('build-admin', 'resources/assets/sass/app.scss') }} --}}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
@yield('content')
|
||||||
|
|
||||||
|
{{-- Vite JS --}}
|
||||||
|
{{-- {{ module_vite('build-admin', 'resources/assets/js/app.js') }} --}}
|
||||||
|
</body>
|
||||||
|
|
@ -0,0 +1,249 @@
|
||||||
|
@php
|
||||||
|
$data = [
|
||||||
|
'title' => 'Forgot Your Password',
|
||||||
|
'name' => $name,
|
||||||
|
'body' => "Not to worry, we got you! Let's get you new a password.",
|
||||||
|
'footer_detail' => "This email was sent $email.",
|
||||||
|
'url_reset' => env('ADMIN_URL') . "/forgot/reset-password?code=$forgot_code&email=$email"
|
||||||
|
];
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
|
<title>{{ $data['title'] }}</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style type="text/css">
|
||||||
|
/**
|
||||||
|
* Google webfonts. Recommended to include the .woff version for cross-client compatibility.
|
||||||
|
*/
|
||||||
|
@media screen {
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Source Sans Pro';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(https://fonts.gstatic.com/s/sourcesanspro/v10/ODelI1aHBYDBqgeIAH2zlBM0YzuT7MdOe03otPbuUS0.woff) format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Source Sans Pro';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(https://fonts.gstatic.com/s/sourcesanspro/v10/toadOcfmlt9b38dHJxOBGFkQc6VGVFSmCnC_l7QZG60.woff) format('woff');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Avoid browser level font resizing.
|
||||||
|
* 1. Windows Mobile
|
||||||
|
* 2. iOS / OSX
|
||||||
|
*/
|
||||||
|
body,
|
||||||
|
table,
|
||||||
|
td,
|
||||||
|
a {
|
||||||
|
-ms-text-size-adjust: 100%; /* 1 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Remove extra space added to tables and cells in Outlook.
|
||||||
|
*/
|
||||||
|
table,
|
||||||
|
td {
|
||||||
|
mso-table-rspace: 0pt;
|
||||||
|
mso-table-lspace: 0pt;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Better fluid images in Internet Explorer.
|
||||||
|
*/
|
||||||
|
img {
|
||||||
|
-ms-interpolation-mode: bicubic;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Remove blue links for iOS devices.
|
||||||
|
*/
|
||||||
|
a[x-apple-data-detectors] {
|
||||||
|
font-family: inherit !important;
|
||||||
|
font-size: inherit !important;
|
||||||
|
font-weight: inherit !important;
|
||||||
|
line-height: inherit !important;
|
||||||
|
color: inherit !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fix centering issues in Android 4.4.
|
||||||
|
*/
|
||||||
|
div[style*="margin: 16px 0;"] {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Collapse table borders to avoid space between cells.
|
||||||
|
*/
|
||||||
|
table {
|
||||||
|
border-collapse: collapse !important;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #1a82e2;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
height: auto;
|
||||||
|
line-height: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
border: 0;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body style="background-color: #e9ecef;">
|
||||||
|
|
||||||
|
<!-- start body -->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
|
||||||
|
<!-- start logo -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef">
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="600">
|
||||||
|
<![endif]-->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" style="padding: 36px 24px;">
|
||||||
|
<a href="{{env('ADMIN_URL')}}" target="_blank" style="display: inline-block;">
|
||||||
|
<img src="{{asset(\App\Models\Setting::getByCache()->value('logo'))}}" alt="Logo" border="0" width="100" style="display: block; width: 100px; max-width: 100px; min-width: 48px;">
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end logo -->
|
||||||
|
|
||||||
|
<!-- start hero -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef">
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="600">
|
||||||
|
<![endif]-->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
|
||||||
|
<tr>
|
||||||
|
<td align="left" bgcolor="#ffffff" style="padding: 36px 24px 0; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; border-top: 3px solid #d4dadf;">
|
||||||
|
<h1 style="margin: 0; font-size: 32px; font-weight: 700; letter-spacing: -1px; line-height: 48px;">{{ $data['title'] }}</h1>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end hero -->
|
||||||
|
|
||||||
|
<!-- start copy block -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef">
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="600">
|
||||||
|
<![endif]-->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
|
||||||
|
|
||||||
|
<!-- start copy -->
|
||||||
|
<tr>
|
||||||
|
<td align="left" bgcolor="#ffffff" style="padding: 24px; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 24px;">
|
||||||
|
<p style="margin: 0;">{{ $data['body'] }}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end copy -->
|
||||||
|
|
||||||
|
<!-- start button -->
|
||||||
|
<tr>
|
||||||
|
<td align="left" bgcolor="#ffffff">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#ffffff" style="padding: 12px;">
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#1a82e2" style="border-radius: 6px;">
|
||||||
|
<a href="{{ $data['url_reset'] }}" target="_blank" style="display: inline-block; padding: 16px 36px; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; font-size: 16px; color: #ffffff; text-decoration: none; border-radius: 6px;">Reset Password</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end button -->
|
||||||
|
|
||||||
|
<!-- start copy -->
|
||||||
|
<tr>
|
||||||
|
<td align="left" bgcolor="#ffffff" style="padding: 24px; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 24px; border-bottom: 3px solid #d4dadf">
|
||||||
|
<p style="margin: 0;">Cheers,<br> {{ $data['name'] }}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end copy -->
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end copy block -->
|
||||||
|
|
||||||
|
<!-- start footer -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef" style="padding: 24px;">
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="600">
|
||||||
|
<![endif]-->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
|
||||||
|
|
||||||
|
<!-- start unsubscribe -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef" style="padding: 12px 24px; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; color: #666;">
|
||||||
|
<p style="margin: 0;">{{ $data['footer_detail'] }}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end unsubscribe -->
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end footer -->
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<!-- end body -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,230 @@
|
||||||
|
@php
|
||||||
|
$setting = \Modules\Admin\app\Models\Setting::first();
|
||||||
|
$data = [
|
||||||
|
'title' => 'Reset Password Successfully',
|
||||||
|
'name' => $name,
|
||||||
|
'body' => "We wanted to let you know that your password has been successfully reset. Your account is now secured with a new password. <hr>
|
||||||
|
If you did not initiate this password reset or have any concerns about your account security, please contact our support team immediately at " . config('mail.from.address') . " or reply to this email.",
|
||||||
|
'footer_detail' => "This email was sent $email.",
|
||||||
|
];
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
|
<title>{{ $data['title'] }}</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style type="text/css">
|
||||||
|
/**
|
||||||
|
* Google webfonts. Recommended to include the .woff version for cross-client compatibility.
|
||||||
|
*/
|
||||||
|
@media screen {
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Source Sans Pro';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), url(https://fonts.gstatic.com/s/sourcesanspro/v10/ODelI1aHBYDBqgeIAH2zlBM0YzuT7MdOe03otPbuUS0.woff) format('woff');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Source Sans Pro';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(https://fonts.gstatic.com/s/sourcesanspro/v10/toadOcfmlt9b38dHJxOBGFkQc6VGVFSmCnC_l7QZG60.woff) format('woff');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Avoid browser level font resizing.
|
||||||
|
* 1. Windows Mobile
|
||||||
|
* 2. iOS / OSX
|
||||||
|
*/
|
||||||
|
body,
|
||||||
|
table,
|
||||||
|
td,
|
||||||
|
a {
|
||||||
|
-ms-text-size-adjust: 100%; /* 1 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Remove extra space added to tables and cells in Outlook.
|
||||||
|
*/
|
||||||
|
table,
|
||||||
|
td {
|
||||||
|
mso-table-rspace: 0pt;
|
||||||
|
mso-table-lspace: 0pt;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Better fluid images in Internet Explorer.
|
||||||
|
*/
|
||||||
|
img {
|
||||||
|
-ms-interpolation-mode: bicubic;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Remove blue links for iOS devices.
|
||||||
|
*/
|
||||||
|
a[x-apple-data-detectors] {
|
||||||
|
font-family: inherit !important;
|
||||||
|
font-size: inherit !important;
|
||||||
|
font-weight: inherit !important;
|
||||||
|
line-height: inherit !important;
|
||||||
|
color: inherit !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fix centering issues in Android 4.4.
|
||||||
|
*/
|
||||||
|
div[style*="margin: 16px 0;"] {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Collapse table borders to avoid space between cells.
|
||||||
|
*/
|
||||||
|
table {
|
||||||
|
border-collapse: collapse !important;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #1a82e2;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
height: auto;
|
||||||
|
line-height: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
border: 0;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body style="background-color: #e9ecef;">
|
||||||
|
|
||||||
|
<!-- start body -->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
|
||||||
|
<!-- start logo -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef">
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="600">
|
||||||
|
<![endif]-->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" style="padding: 36px 24px;">
|
||||||
|
<a href="{{env('ADMIN_URL')}}" target="_blank" style="display: inline-block;">
|
||||||
|
<img src="{{asset(\App\Models\Setting::getByCache()->value('logo'))}}" alt="Logo" border="0" width="100" style="display: block; width: 100px; max-width: 100px; min-width: 48px;">
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end logo -->
|
||||||
|
|
||||||
|
<!-- start hero -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef">
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="600">
|
||||||
|
<![endif]-->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
|
||||||
|
<tr>
|
||||||
|
<td align="left" bgcolor="#ffffff" style="padding: 36px 24px 0; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; border-top: 3px solid #d4dadf;">
|
||||||
|
<h1 style="margin: 0; font-size: 32px; font-weight: 700; letter-spacing: -1px; line-height: 48px;">{{ $data['title'] }}</h1>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end hero -->
|
||||||
|
|
||||||
|
<!-- start copy block -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef">
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="600">
|
||||||
|
<![endif]-->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
|
||||||
|
|
||||||
|
<!-- start copy -->
|
||||||
|
<tr>
|
||||||
|
<td align="left" bgcolor="#ffffff" style="padding: 24px; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 24px;">
|
||||||
|
<p style="margin: 0;">{!! $data['body'] !!}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end copy -->
|
||||||
|
|
||||||
|
<!-- start copy -->
|
||||||
|
<tr>
|
||||||
|
<td align="left" bgcolor="#ffffff" style="padding: 24px; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 24px; border-bottom: 3px solid #d4dadf">
|
||||||
|
<p style="margin: 0;">Cheers,<br> {{ $data['name'] }}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end copy -->
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end copy block -->
|
||||||
|
|
||||||
|
<!-- start footer -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef" style="padding: 24px;">
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" width="600">
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="600">
|
||||||
|
<![endif]-->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 600px;">
|
||||||
|
|
||||||
|
<!-- start unsubscribe -->
|
||||||
|
<tr>
|
||||||
|
<td align="center" bgcolor="#e9ecef" style="padding: 12px 24px; font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; color: #666;">
|
||||||
|
<p style="margin: 0;">{{ $data['footer_detail'] }}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end unsubscribe -->
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!-- end footer -->
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<!-- end body -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Modules\Admin\app\Http\Controllers\AdminController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\BannerController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\ClientController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\ContactController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\CountryController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\CustomThemeController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\DashboardController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\DiscountController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\DiscountTypeController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\OrderController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\PackageController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\SNCheckController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\SettingController;
|
||||||
|
use Modules\Admin\app\Http\Controllers\TrackingController;
|
||||||
|
use Modules\Admin\app\Http\Middleware\AdminMiddleware;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| API Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here is where you can register API routes for your application. These
|
||||||
|
| routes are loaded by the RouteServiceProvider within a group which
|
||||||
|
| is assigned the "api" middleware group. Enjoy building your API!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Route::middleware('api')
|
||||||
|
->prefix('v1/admin')
|
||||||
|
->group(function () {
|
||||||
|
// NOTE not login
|
||||||
|
Route::group([], function () {
|
||||||
|
Route::post('login', [AdminController::class, 'login']);
|
||||||
|
Route::post('reset-password', [AdminController::class, 'resetPassword']);
|
||||||
|
Route::get('forgot-password', [AdminController::class, 'forgotPassword']);
|
||||||
|
});
|
||||||
|
|
||||||
|
// NOTE after login
|
||||||
|
Route::group([
|
||||||
|
'middleware' => AdminMiddleware::class,
|
||||||
|
], function () {
|
||||||
|
Route::get('logout', [AdminController::class, 'logout']);
|
||||||
|
Route::get('detail', [AdminController::class, 'detail']);
|
||||||
|
Route::post('change-password', [AdminController::class, 'changePassword']);
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'setting',
|
||||||
|
], function () {
|
||||||
|
Route::get('/', [SettingController::class, 'index']);
|
||||||
|
Route::post('/', [SettingController::class, 'updateOrCreate']);
|
||||||
|
Route::get('/clear-cache', [SettingController::class, 'clearCache']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'package',
|
||||||
|
], function () {
|
||||||
|
Route::get('/all', [PackageController::class, 'all']);
|
||||||
|
Route::post('/create', [PackageController::class, 'create']);
|
||||||
|
Route::post('/update', [PackageController::class, 'update']);
|
||||||
|
Route::get('/delete', [PackageController::class, 'delete']);
|
||||||
|
Route::post('/updates', [PackageController::class, 'updates']);
|
||||||
|
Route::post('/deletes', [PackageController::class, 'deletes']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'discount',
|
||||||
|
], function () {
|
||||||
|
Route::get('/get', [DiscountController::class, 'get']);
|
||||||
|
Route::post('/create', [DiscountController::class, 'create']);
|
||||||
|
Route::post('/update', [DiscountController::class, 'update']);
|
||||||
|
Route::get('/delete', [DiscountController::class, 'delete']);
|
||||||
|
Route::post('/updates', [DiscountController::class, 'updates']);
|
||||||
|
Route::post('/deletes', [DiscountController::class, 'deletes']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'client',
|
||||||
|
], function () {
|
||||||
|
Route::get('/get', [ClientController::class, 'get']);
|
||||||
|
Route::post('/create', [ClientController::class, 'create']);
|
||||||
|
Route::post('/update', [ClientController::class, 'update']);
|
||||||
|
Route::get('/delete', [ClientController::class, 'delete']);
|
||||||
|
Route::post('/updates', [ClientController::class, 'updates']);
|
||||||
|
Route::post('/deletes', [ClientController::class, 'deletes']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'banner',
|
||||||
|
], function () {
|
||||||
|
Route::get('/all', [BannerController::class, 'all']);
|
||||||
|
Route::post('/create', [BannerController::class, 'create']);
|
||||||
|
Route::post('/update', [BannerController::class, 'update']);
|
||||||
|
Route::get('/delete', [BannerController::class, 'delete']);
|
||||||
|
Route::post('/updates', [BannerController::class, 'updates']);
|
||||||
|
Route::post('/deletes', [BannerController::class, 'deletes']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'order',
|
||||||
|
], function () {
|
||||||
|
Route::get('/get', [OrderController::class, 'get']);
|
||||||
|
Route::post('/update', [OrderController::class, 'update']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'sn-check-history',
|
||||||
|
], function () {
|
||||||
|
Route::get('/get', [SNCheckController::class, 'get']);
|
||||||
|
Route::get('/show-detail', [SNCheckController::class, 'showDetail']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'discount-type',
|
||||||
|
], function () {
|
||||||
|
Route::get('/all', [DiscountTypeController::class, 'all']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'custom-theme',
|
||||||
|
], function () {
|
||||||
|
Route::get('/', [CustomThemeController::class, 'index']);
|
||||||
|
Route::post('/', [CustomThemeController::class, 'updateOrCreate']);
|
||||||
|
});
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'h-country',
|
||||||
|
], function () {
|
||||||
|
Route::get('/', [CountryController::class, 'all']);
|
||||||
|
});
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'contact',
|
||||||
|
], function () {
|
||||||
|
Route::get('/get', [ContactController::class, 'get']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'dashboard',
|
||||||
|
], function () {
|
||||||
|
Route::get('/get', [DashboardController::class, 'get']);
|
||||||
|
Route::get('/statistics-search-sn-by-month', [DashboardController::class, 'statisticSearchSNByMonth']);
|
||||||
|
Route::get('/statistics-revenues-by-month', [DashboardController::class, 'statisticRevenuesByMonth']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'prefix' => 'v1/admin/tracking',
|
||||||
|
], function () {
|
||||||
|
Route::get('/', [TrackingController::class, 'get']);
|
||||||
|
Route::post('/scan-create', [TrackingController::class, 'create']);
|
||||||
|
// Route::get('/clear-cache', [SettingController::class, 'clearCache']);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Modules\Admin\app\Http\Controllers\AdminController;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Web Routes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here is where you can register web routes for your application. These
|
||||||
|
| routes are loaded by the RouteServiceProvider within a group which
|
||||||
|
| contains the "web" middleware group. Now create something great!
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Route::group([], function () {
|
||||||
|
Route::resource('admin', AdminController::class)->names('admin');
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import laravel from 'laravel-vite-plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
build: {
|
||||||
|
outDir: '../../public/build-admin',
|
||||||
|
emptyOutDir: true,
|
||||||
|
manifest: true,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
laravel({
|
||||||
|
publicDirectory: '../../public',
|
||||||
|
buildDirectory: 'build-admin',
|
||||||
|
input: [
|
||||||
|
__dirname + '/resources/assets/sass/app.scss',
|
||||||
|
__dirname + '/resources/assets/js/app.js'
|
||||||
|
],
|
||||||
|
refresh: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
//export const paths = [
|
||||||
|
// 'Modules/$STUDLY_NAME$/resources/assets/sass/app.scss',
|
||||||
|
// 'Modules/$STUDLY_NAME$/resources/assets/js/app.js',
|
||||||
|
//];
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
# API version V1
|
||||||
|
|
||||||
|
> [Base URL: http://localhost:8000/api/v1/*]
|
||||||
|
|
||||||
|
Purpose to handle authentication with [JWT](https://jwt-auth.readthedocs.io/en/develop/quick-start/)
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
## Response
|
||||||
|
### 200
|
||||||
|
Success:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"data": [] | {},
|
||||||
|
"status": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Fail:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"data": [] | {},
|
||||||
|
"status": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 203
|
||||||
|
* On/Off for button switch:
|
||||||
|
* Success/Fail:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
// no content
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 400
|
||||||
|
* Validate fail.
|
||||||
|
* Fail:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"attribute": [
|
||||||
|
"The :attribute field is required.",
|
||||||
|
...
|
||||||
|
]
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 401
|
||||||
|
* Unauthentication, not login.
|
||||||
|
* Fail:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"message": "Token has expired"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 403
|
||||||
|
* Permission denied.
|
||||||
|
* Fail:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"message": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 404
|
||||||
|
* Page not found.
|
||||||
|
* Fail:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"message": "The route {path} could not be found."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 500
|
||||||
|
* Server error.
|
||||||
|
* Fail:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"message": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 503
|
||||||
|
* Server maintain.
|
||||||
|
* Fail:
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
"message": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
@url=http://localhost:8000
|
||||||
|
@token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2xvZ2luIiwiaWF0IjoxNzAwMTIyNzkwLCJleHAiOjE3MDAxMjYzOTAsIm5iZiI6MTcwMDEyMjc5MCwianRpIjoiT1FyWW9mazkwWXJSTnlyWSIsInN1YiI6IjEiLCJwcnYiOiI5Yjk4MmUxNDA4MzM2MmVjMmViZjE4MDQxM2NmNGVlMGFjM2VkY2U4In0.VT1-FwvSdMsbHiJ6-dQfoH3LfF2_14GxzgYbQWdRATc
|
||||||
|
|
||||||
|
{{
|
||||||
|
exports.defaultHeaders = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
###
|
||||||
|
# @name logout
|
||||||
|
POST {{url}}/api/v1/logout
|
||||||
|
...defaultHeaders
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
HTTP/1.1 200 - OK
|
||||||
|
host: localhost:8000
|
||||||
|
date: Thu, 16 Nov 2023 08:20:13 GMT, Thu, 16 Nov 2023 08:20:13 GMT
|
||||||
|
connection: close
|
||||||
|
x-powered-by: PHP/8.2.11
|
||||||
|
cache-control: no-cache, private
|
||||||
|
content-type: application/json
|
||||||
|
x-ratelimit-limit: 60
|
||||||
|
x-ratelimit-remaining: 57
|
||||||
|
phpdebugbar-id: X29245e892030a261594af408e13086a3
|
||||||
|
access-control-allow-origin: *
|
||||||
|
###
|
||||||
|
# @name login
|
||||||
|
POST {{url}}/api/v1/login
|
||||||
|
...defaultHeaders
|
||||||
|
{
|
||||||
|
"email": "admin@apactech.io",
|
||||||
|
"password": "admin123"
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTP/1.1 200 - OK
|
||||||
|
date: Wed, 15 Nov 2023 07:53:31 GMT
|
||||||
|
server: Apache/2.4.58 (Unix)
|
||||||
|
x-powered-by: PHP/8.1.25
|
||||||
|
cache-control: no-cache, private
|
||||||
|
x-ratelimit-limit: 60
|
||||||
|
x-ratelimit-remaining: 59
|
||||||
|
phpdebugbar-id: Xf53438d0027647cec2211e26f376006b
|
||||||
|
access-control-allow-origin: *
|
||||||
|
connection: close
|
||||||
|
transfer-encoding: chunked
|
||||||
|
content-type: application/json
|
||||||
|
###
|
||||||
|
# @name register
|
||||||
|
POST {{url}}/api/v1/register
|
||||||
|
...defaultHeaders
|
||||||
|
{
|
||||||
|
"name": "kai.t",
|
||||||
|
"email": "kai.t@apachtech.io",
|
||||||
|
"password": "kai.t123"
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTP/1.1 400 - Bad Request
|
||||||
|
date: Wed, 15 Nov 2023 08:15:31 GMT
|
||||||
|
server: Apache/2.4.58 (Unix)
|
||||||
|
x-powered-by: PHP/8.1.25
|
||||||
|
cache-control: no-cache, private
|
||||||
|
x-ratelimit-limit: 60
|
||||||
|
x-ratelimit-remaining: 59
|
||||||
|
phpdebugbar-id: X740ed6622628ede300ed7be424860462
|
||||||
|
access-control-allow-origin: *
|
||||||
|
connection: close
|
||||||
|
transfer-encoding: chunked
|
||||||
|
content-type: application/json; charset=utf-8
|
||||||
|
###
|
||||||
|
# @name get-users
|
||||||
|
GET {{url}}/api/v1/users
|
||||||
|
...defaultHeaders
|
||||||
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
|
HTTP/1.1 401 - Unauthorized
|
||||||
|
date: Wed, 15 Nov 2023 08:15:35 GMT
|
||||||
|
server: Apache/2.4.58 (Unix)
|
||||||
|
vary: Authorization
|
||||||
|
x-powered-by: PHP/8.1.25
|
||||||
|
www-authenticate: jwt-auth
|
||||||
|
cache-control: no-cache, private
|
||||||
|
x-ratelimit-limit: 60
|
||||||
|
x-ratelimit-remaining: 58
|
||||||
|
phpdebugbar-id: X9d6118350a6e5a23aea55d495a056cc6
|
||||||
|
access-control-allow-origin: *
|
||||||
|
connection: close
|
||||||
|
transfer-encoding: chunked
|
||||||
|
content-type: application/json
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Auth\app\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
|
class AuthController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('auth::index');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('auth::create');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request): RedirectResponse
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the specified resource.
|
||||||
|
*/
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
return view('auth::show');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*/
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
return view('auth::edit');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function updatePassword(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
$messages = array(
|
||||||
|
'email.required' => 'Email là bắt buộc.',
|
||||||
|
'email.email' => 'Email không đúng định dạng.',
|
||||||
|
'password.required' => 'Mật khẩu là bắt buộc.',
|
||||||
|
'current_password.required' => 'Mật khẩu là bắt buộc.',
|
||||||
|
'current_password.min' => 'Mật khẩu phải có ít nhất 6 ký tự.',
|
||||||
|
'password.min' => 'Mật khẩu phải có ít nhất 6 ký tự.',
|
||||||
|
'password.confirmed' => 'Mật khẩu không trùng khớp.',
|
||||||
|
'password_confirmation.required' => 'Mật khẩu xác thực là bắt buộc.',
|
||||||
|
);
|
||||||
|
|
||||||
|
$validateData = [
|
||||||
|
'email' => 'required|email',
|
||||||
|
'current_password' => 'required|min:6',
|
||||||
|
'password' => 'required|min:6|confirmed',
|
||||||
|
'password_confirmation' => 'required'
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
$request->validate($validateData, $messages);
|
||||||
|
|
||||||
|
$user = User::where('email', $request->email)->first();
|
||||||
|
|
||||||
|
if (Hash::check($request->current_password, $user->password) && $user !== null) {
|
||||||
|
$user->password = bcrypt($request->password);
|
||||||
|
$user->save();
|
||||||
|
return response()->json(['status' => true, 'mess' => 'Change password success!'], Response::HTTP_OK);
|
||||||
|
}else{
|
||||||
|
return response()->json(['status' => false, 'mess' => 'Current password incorrect'], Response::HTTP_OK);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue