Merge branch 'InvoiceShelf:master' into master

This commit is contained in:
mchev
2026-04-02 16:42:13 +02:00
committed by GitHub
141 changed files with 1286 additions and 1923 deletions

View File

@@ -3,28 +3,41 @@ name: Check
# Run this workflow every time a new commit pushed to your repository
on:
push:
paths-ignore:
- '.github/**/*'
- '**/*.md'
- 'public/build/*.js'
- 'public/build/**/*.js'
- 'docker/**/*'
- 'resources/scripts/**/*'
tags-ignore:
- "*"
branches-ignore:
- 'translations'
pull_request:
paths-ignore:
- '**/*.md'
- 'public/build/*.js'
- 'public/build/**/*.js'
branches-ignore:
- 'translations'
# Allow manually triggering the workflow.
workflow_dispatch:
jobs:
changes:
name: 🔍 Detect changes
runs-on: ubuntu-latest
outputs:
php: ${{ steps.filter.outputs.php }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Check for file changes
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
php:
- 'app/**'
- 'config/**'
- 'database/**'
- 'routes/**'
- 'tests/**'
- 'composer.json'
- 'composer.lock'
- 'phpunit.xml'
kill_previous:
name: 0️⃣ Kill previous runs
runs-on: ubuntu-latest
@@ -41,6 +54,8 @@ jobs:
runs-on: ubuntu-latest
needs:
- kill_previous
- changes
if: needs.changes.outputs.php == 'true'
steps:
- name: Set up PHP
uses: shivammathur/setup-php@v2
@@ -60,6 +75,8 @@ jobs:
name: 2️⃣ PHP ${{ matrix.php-version }} Tests
needs:
- php_syntax_errors
- changes
if: needs.changes.outputs.php == 'true'
runs-on: ubuntu-latest
strategy:
matrix:

80
CLAUDE.md Normal file
View File

@@ -0,0 +1,80 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
InvoiceShelf is an open-source invoicing and expense tracking application built with Laravel 13 (PHP 8.4) and Vue 3. It supports multi-company tenancy, customer portals, recurring invoices, and PDF generation.
## Common Commands
### Development
```bash
composer run dev # Starts PHP server, queue listener, log tail, and Vite dev server concurrently
npm run dev # Vite dev server only
npm run build # Production frontend build
```
### Testing
```bash
php artisan test --compact # Run all tests
php artisan test --compact --filter=testName # Run specific test
./vendor/bin/pest --stop-on-failure # Run via Pest directly
make test # Makefile shortcut
```
Tests use SQLite in-memory DB, configured in `phpunit.xml`. Tests seed via `DatabaseSeeder` + `DemoSeeder` in `beforeEach`. Authenticate with `Sanctum::actingAs()` and set the `company` header.
### Code Style
```bash
vendor/bin/pint --dirty --format agent # Fix style on modified PHP files
vendor/bin/pint --test # Check style without fixing (CI uses this)
```
### Artisan Generators
Always use `php artisan make:*` with `--no-interaction` to create new files (models, controllers, migrations, tests, etc.).
## Architecture
### Multi-Tenancy
Every major model has a `company_id` foreign key. The `CompanyMiddleware` sets the active company from the `company` request header. Bouncer authorization is scoped to the company level via `DefaultScope` (`app/Bouncer/Scopes/DefaultScope.php`).
### Authentication
Three guards: `web` (session), `api` (Sanctum tokens for `/api/v1/`), `customer` (session for customer portal). API routes use `auth:sanctum` middleware; customer portal uses `auth:customer`.
### Routing
- **API**: All endpoints under `/api/v1/` in `routes/api.php`, grouped with `auth:sanctum`, `company`, and `bouncer` middleware
- **Web**: `routes/web.php` serves PDF endpoints, auth pages, and catch-all SPA routes (`/admin/{vue?}`, `/{company:slug}/customer/{vue?}`)
### Frontend
- Entry point: `resources/scripts/main.js`
- Vue Router: `resources/scripts/admin/admin-router.js` (admin), `resources/scripts/customer/customer-router.js` (customer portal)
- State: Pinia stores in `resources/scripts/admin/stores/`
- Path aliases: `@` = `resources/`, `$fonts`, `$images` for static assets
- Vite dev server expects `invoiceshelf.test` hostname
### Backend Patterns
- **Authorization**: Silber/Bouncer with policies in `app/Policies/`. Controllers use `$this->authorize()`.
- **Validation**: Form Request classes, never inline validation
- **API responses**: Eloquent API Resources in `app/Http/Resources/`
- **PDF generation**: DomPDF (`GeneratesPdfTrait`) or Gotenberg
- **Email**: Mailable classes with `EmailLog` tracking
- **File storage**: Spatie MediaLibrary, supports local/S3/Dropbox
- **Serial numbers**: `SerialNumberFormatter` service
- **Company settings**: `CompanySetting` model (key-value per company)
### Database
Supports MySQL, PostgreSQL, and SQLite. Prefer Eloquent over raw queries. Use `Model::query()` instead of `DB::`. Use eager loading to prevent N+1 queries.
## Code Conventions
- PHP: snake_case, constructor property promotion, explicit return types, PHPDoc blocks over inline comments
- JS: camelCase
- Always check sibling files for patterns before creating new ones
- Use `config()` helper, never `env()` outside config files
- Every change must have tests (feature tests preferred over unit tests)
- Run `vendor/bin/pint --dirty --format agent` after modifying PHP files
## CI Pipeline
GitHub Actions (`check.yaml`): runs Pint style check, then builds frontend and runs Pest tests on PHP 8.4.

View File

@@ -24,7 +24,7 @@ class ResetApp extends Command
*
* @var string
*/
protected $description = 'Clean database, database_created and public/storage folder';
protected $description = 'Clean database and public/storage folder';
/**
* Create a new command instance.

View File

@@ -165,11 +165,11 @@ class MailConfigurationController extends Controller
switch ($driver) {
case 'smtp':
$MailData = array_merge($MailData, [
'mail_host' => $mailSettings['mail_host'] ?? '',
'mail_port' => $mailSettings['mail_port'] ?? '',
'mail_username' => $mailSettings['mail_username'] ?? '',
'mail_password' => $mailSettings['mail_password'] ?? '',
'mail_encryption' => $mailSettings['mail_encryption'] ?? 'none',
'mail_host' => $mailSettings['mail_host'] ?? config('mail.mailers.smtp.host', ''),
'mail_port' => $mailSettings['mail_port'] ?? config('mail.mailers.smtp.port', ''),
'mail_username' => $mailSettings['mail_username'] ?? config('mail.mailers.smtp.username', ''),
'mail_password' => $mailSettings['mail_password'] ?? config('mail.mailers.smtp.password', ''),
'mail_encryption' => $mailSettings['mail_encryption'] ?? config('mail.mailers.smtp.encryption', 'none'),
'mail_scheme' => $mailSettings['mail_scheme'] ?? '',
'mail_url' => $mailSettings['mail_url'] ?? '',
'mail_timeout' => $mailSettings['mail_timeout'] ?? '',

View File

@@ -48,8 +48,9 @@ class DatabaseConfigurationController extends Controller
public function getDatabaseEnvironment(Request $request)
{
$databaseData = [];
$connection = $request->connection ?? config('database.default');
switch ($request->connection) {
switch ($connection) {
case 'sqlite':
$databaseData = [
'database_connection' => 'sqlite',

View File

@@ -3,7 +3,6 @@
namespace App\Http\Controllers\V1\Installation;
use App\Http\Controllers\Controller;
use App\Space\InstallUtils;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -16,10 +15,6 @@ class FinishController extends Controller
*/
public function __invoke(Request $request)
{
if (! InstallUtils::createDbMarker()) {
\Log::error('Install: Unable to create db marker.');
}
return response()->json(['success' => true]);
}
}

View File

@@ -17,7 +17,7 @@ class OnboardingWizardController extends Controller
*/
public function getStep(Request $request)
{
if (! InstallUtils::dbMarkerExists()) {
if (! InstallUtils::isDbCreated()) {
return response()->json([
'profile_complete' => 0,
'profile_language' => 'en',

View File

@@ -17,7 +17,11 @@ class InstallationMiddleware
*/
public function handle(Request $request, Closure $next): Response
{
if (! InstallUtils::isDbCreated() || Setting::getSetting('profile_complete') !== 'COMPLETED') {
try {
if (! InstallUtils::isDbCreated() || Setting::getSetting('profile_complete') !== 'COMPLETED') {
return redirect('/installation');
}
} catch (\Exception $e) {
return redirect('/installation');
}

View File

@@ -17,9 +17,13 @@ class RedirectIfInstalled
*/
public function handle(Request $request, Closure $next): Response
{
if (InstallUtils::dbMarkerExists()) {
if (Setting::getSetting('profile_complete') === 'COMPLETED') {
return redirect('login');
if (InstallUtils::isDbCreated()) {
try {
if (Setting::getSetting('profile_complete') === 'COMPLETED') {
return redirect('login');
}
} catch (\Exception $e) {
// Settings table may not exist yet during installation
}
}

View File

@@ -5,8 +5,6 @@ namespace App\Space;
use App\Models\Setting;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use League\Flysystem\FilesystemException;
class InstallUtils
{
@@ -17,7 +15,7 @@ class InstallUtils
*/
public static function isDbCreated()
{
return self::dbMarkerExists() && self::tableExists('users');
return self::tableExists('users');
}
/**
@@ -44,54 +42,6 @@ class InstallUtils
return $cache[$table];
}
/**
* Check if database created marker exists
*
* @return bool
*/
public static function dbMarkerExists()
{
try {
return \Storage::disk('local')->has('database_created');
} catch (FilesystemException $e) {
Log::error('Unable to verify db marker: '.$e->getMessage());
}
return false;
}
/**
* Creates the database marker
*
* @return bool
*/
public static function createDbMarker()
{
try {
return \Storage::disk('local')->put('database_created', time());
} catch (\Exception $e) {
Log::error('Unable to create db marker: '.$e->getMessage());
}
return false;
}
/**
* Deletes the database marker
*
* @return bool
*/
public static function deleteDbMarker()
{
try {
return \Storage::disk('local')->delete('database_created');
} catch (\Exception $e) {
Log::error('Unable to delete db marker: '.$e->getMessage());
}
return false;
}
/**
* Set the app version
*

View File

@@ -8,7 +8,6 @@ use App\Models\CompanySetting;
use App\Models\Customer;
use App\Models\Setting;
use App\Models\User;
use App\Space\InstallUtils;
use Illuminate\Database\Seeder;
use Silber\Bouncer\BouncerFacade;
@@ -71,8 +70,5 @@ class DemoSeeder extends Seeder
// Mark profile setup as complete
Setting::setSetting('profile_complete', 'COMPLETED');
// Create installation marker
InstallUtils::createDbMarker();
}
}

View File

@@ -9,56 +9,50 @@
"test": "eslint ./resources/scripts --ext .js,.vue"
},
"devDependencies": {
"@rvxlab/tailwind-plugin-ios-full-height": "^1.1.0",
"@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16",
"@vitejs/plugin-vue": "^5.2.1",
"@tailwindcss/vite": "^4.0.0",
"@vitejs/plugin-vue": "^6.0.0",
"@vue/compiler-sfc": "^3.5.13",
"autoprefixer": "^10.4.20",
"cross-env": "^7.0.3",
"eslint": "^9.18.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-vue": "^9.32.0",
"postcss": "^8.4.49",
"prettier": "^3.4.2",
"sass": "^1.83.1",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.17"
"tailwind-scrollbar": "^4.0.0",
"tailwindcss": "^4.0.0"
},
"dependencies": {
"@headlessui/vue": "^1.7.23",
"@heroicons/vue": "^2.2.0",
"@popperjs/core": "^2.11.8",
"@stripe/stripe-js": "^2.4.0",
"@tiptap/core": "^2.11.2",
"@tiptap/extension-link": "^2.11.2",
"@tiptap/extension-text-align": "^2.11.2",
"@tiptap/pm": "^2.11.2",
"@tiptap/starter-kit": "^2.11.2",
"@tiptap/vue-3": "^2.11.2",
"@tiptap/core": "^3.0.0",
"@tiptap/extension-text-align": "^3.0.0",
"@tiptap/pm": "^3.0.0",
"@tiptap/starter-kit": "^3.0.0",
"@tiptap/vue-3": "^3.0.0",
"@types/node": "^20.11.9",
"@vuelidate/components": "^1.2.6",
"@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4",
"@vueuse/core": "^12.4.0",
"axios": "0.30.0",
"axios": "1.14.0",
"chart.js": "^2.9.4",
"guid": "^0.0.12",
"laravel-vite-plugin": "^1.1.1",
"laravel-vite-plugin": "^3.0.0",
"lodash": "^4.17.21",
"maska": "^3.0.4",
"mini-svg-data-uri": "^1.4.4",
"moment": "^2.30.1",
"path": "^0.12.7",
"pinia": "^2.3.0",
"pinia": "^3.0.0",
"v-money3": "^3.24.1",
"v-tooltip": "^4.0.0-beta.17",
"vite": "^6.0.7",
"vite": "^8.0.0",
"vue": "^3.5",
"vue-flatpickr-component": "^11.0.5",
"vue-i18n": "^11.0.1",
"vue-router": "^4.5.0",
"vuedraggable": "^4.1.0"
}
}
}

View File

@@ -1,7 +0,0 @@
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -0,0 +1,56 @@
.pace {
-webkit-pointer-events: none;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.pace-inactive {
display: none;
}
.pace .pace-progress {
background: #3f39ad;
position: fixed;
z-index: 2000;
top: 0;
right: 100%;
width: 100%;
height: 2px;
}
.pace .pace-progress-inner {
display: block;
position: absolute;
right: 0px;
width: 100px;
height: 100%;
box-shadow: 0 0 10px #5851d8, 0 0 5px #5851d8;
opacity: 1;
transform: rotate(3deg) translate(0px, -4px);
}
.pace .pace-activity {
display: block;
position: fixed;
z-index: 2000;
top: 15px;
right: 15px;
width: 14px;
height: 14px;
border: solid 2px transparent;
border-top-color: #5851d8;
border-left-color: #5851d8;
border-radius: 10px;
animation: pace-spinner 400ms linear infinite;
}
@keyframes pace-spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@@ -80,18 +80,16 @@
}
&.popover {
$color: #f9f9f9;
.popover-inner {
background: $color;
background: #f9f9f9;
color: black;
padding: 24px;
border-radius: 5px;
box-shadow: 0 5px 30px rgba(black, .1);
box-shadow: 0 5px 30px rgba(0, 0, 0, 0.1);
}
.popover-arrow {
border-color: $color;
border-color: #f9f9f9;
}
}

98
resources/css/invoiceshelf.css vendored Normal file
View File

@@ -0,0 +1,98 @@
@import "tailwindcss";
@import "./themes.css";
@import "./components/animation.css";
@import "./components/pace-loader.css";
@import "./components/v-tooltips.css";
@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/typography";
@plugin "tailwind-scrollbar";
@source "../scripts/**/*.vue";
@source "../scripts/**/*.js";
@source "../../resources/views/**/*.php";
@theme inline {
--color-primary-50: var(--color-primary-50);
--color-primary-100: var(--color-primary-100);
--color-primary-200: var(--color-primary-200);
--color-primary-300: var(--color-primary-300);
--color-primary-400: var(--color-primary-400);
--color-primary-500: var(--color-primary-500);
--color-primary-600: var(--color-primary-600);
--color-primary-700: var(--color-primary-700);
--color-primary-800: var(--color-primary-800);
--color-primary-900: var(--color-primary-900);
--color-primary-950: var(--color-primary-950);
--color-black: #040405;
}
@theme {
--spacing-88: 22rem;
--font-base: Poppins, sans-serif;
}
@utility bg-multiselect-caret {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='h-5 w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z' clip-rule='evenodd'/%3E%3C/svg%3E");
}
@utility bg-multiselect-spinner {
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' fill='%234a3dff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M456.433 371.72l-27.79-16.045c-7.192-4.152-10.052-13.136-6.487-20.636 25.82-54.328 23.566-118.602-6.768-171.03-30.265-52.529-84.802-86.621-144.76-91.424C262.35 71.922 256 64.953 256 56.649V24.56c0-9.31 7.916-16.609 17.204-15.96 81.795 5.717 156.412 51.902 197.611 123.408 41.301 71.385 43.99 159.096 8.042 232.792-4.082 8.369-14.361 11.575-22.424 6.92z'/%3E%3C/svg%3E");
}
@utility bg-multiselect-remove {
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 320 512' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z'/%3E%3C/svg%3E");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("$fonts/Poppins-Black.ttf") format("truetype");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 300;
font-display: swap;
src: url("$fonts/Poppins-Light.ttf") format("truetype");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("$fonts/Poppins-Medium.ttf") format("truetype");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("$fonts/Poppins-Regular.ttf") format("truetype");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("$fonts/Poppins-SemiBold.ttf") format("truetype");
}
body {
min-height: 100vh;
min-height: -webkit-fill-available;
}
html {
height: -webkit-fill-available;
}
.h-screen-ios {
height: -webkit-fill-available;
}

13
resources/css/themes.css vendored Normal file
View File

@@ -0,0 +1,13 @@
:root {
--color-primary-50: rgb(241, 243, 255);
--color-primary-100: rgb(229, 231, 255);
--color-primary-200: rgb(206, 209, 255);
--color-primary-300: rgb(167, 170, 255);
--color-primary-400: rgb(118, 117, 255);
--color-primary-500: rgb(74, 61, 255);
--color-primary-600: rgb(51, 22, 255);
--color-primary-700: rgb(33, 4, 253);
--color-primary-800: rgb(27, 3, 211);
--color-primary-900: rgb(25, 5, 173);
--color-primary-950: rgb(9, 0, 118);
}

View File

@@ -1,112 +0,0 @@
$pace-loader-color: #5851d8;
.pace {
-webkit-pointer-events: none;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.pace-inactive {
display: none;
}
.pace .pace-progress {
background: darken($pace-loader-color, 10%);
position: fixed;
z-index: 2000;
top: 0;
right: 100%;
width: 100%;
height: 2px;
}
.pace .pace-progress-inner {
display: block;
position: absolute;
right: 0px;
width: 100px;
height: 100%;
box-shadow: 0 0 10px $pace-loader-color, 0 0 5px $pace-loader-color;
opacity: 1;
-webkit-transform: rotate(3deg) translate(0px, -4px);
-moz-transform: rotate(3deg) translate(0px, -4px);
-ms-transform: rotate(3deg) translate(0px, -4px);
-o-transform: rotate(3deg) translate(0px, -4px);
transform: rotate(3deg) translate(0px, -4px);
}
.pace .pace-activity {
display: block;
position: fixed;
z-index: 2000;
top: 15px;
right: 15px;
width: 14px;
height: 14px;
border: solid 2px transparent;
border-top-color: $pace-loader-color;
border-left-color: $pace-loader-color;
border-radius: 10px;
-webkit-animation: pace-spinner 400ms linear infinite;
-moz-animation: pace-spinner 400ms linear infinite;
-ms-animation: pace-spinner 400ms linear infinite;
-o-animation: pace-spinner 400ms linear infinite;
animation: pace-spinner 400ms linear infinite;
}
@-webkit-keyframes pace-spinner {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-moz-keyframes pace-spinner {
0% {
-moz-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-moz-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-o-keyframes pace-spinner {
0% {
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-ms-keyframes pace-spinner {
0% {
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes pace-spinner {
0% {
transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
transform: rotate(360deg);
}
}

View File

@@ -1,61 +0,0 @@
@use "themes.scss";
@use "components/animation.scss";
@tailwind base;
@tailwind components;
@tailwind utilities;
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("$fonts/Poppins-Black.ttf") format("truetype");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 300;
font-display: swap;
src: url("$fonts/Poppins-Light.ttf") format("truetype");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("$fonts/Poppins-Medium.ttf") format("truetype");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("$fonts/Poppins-Regular.ttf") format("truetype");
}
@font-face {
font-family: "Poppins";
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("$fonts/Poppins-SemiBold.ttf") format("truetype");
}
body {
min-height: 100vh;
min-height: -webkit-fill-available;
}
html {
height: -webkit-fill-available;
}
.h-screen-ios {
height: -webkit-fill-available;
}

View File

@@ -1,13 +0,0 @@
:root {
--color-primary-50: 241, 243, 255;
--color-primary-100: 229, 231, 255;
--color-primary-200: 206, 209, 255;
--color-primary-300: 167, 170, 255;
--color-primary-400: 118, 117, 255;
--color-primary-500: 74, 61, 255;
--color-primary-600: 51, 22, 255;
--color-primary-700: 33, 4, 253;
--color-primary-800: 27, 3, 211;
--color-primary-900: 25, 5, 173;
--color-primary-950: 9, 0, 118;
}

View File

@@ -6,7 +6,7 @@
px-4
py-2
rounded-lg
bg-opacity-40 bg-gray-300
bg-gray-300/40
whitespace-nowrap
flex-col
mt-1
@@ -33,7 +33,7 @@
h-full
inset-y-0
cursor-pointer
focus:outline-none
focus:outline-hidden
text-primary-500
"
width="37"

View File

@@ -4,14 +4,14 @@
<Popover v-slot="{ isOpen }">
<PopoverButton
v-if="userStore.hasAbilities(abilities.VIEW_NOTE)"
:class="isOpen ? '' : 'text-opacity-90'"
:class="isOpen ? '' : ''"
class="
flex
items-center
z-10
font-medium
text-primary-400
focus:outline-none focus:border-none
focus:outline-hidden focus:border-none
"
@click="fetchInitialData"
>
@@ -50,7 +50,7 @@
overflow-hidden
rounded-md
shadow-lg
ring-1 ring-black ring-opacity-5
ring-1 ring-black/5
"
>
<div class="relative grid bg-white">
@@ -117,7 +117,7 @@
py-3
bg-gray-200
border-none
outline-none
outline-hidden
"
@click="openNoteModal"
>

View File

@@ -58,7 +58,7 @@
justify-end
mt-4
pt-4
border-t border-gray-200 border-solid border-modal-bg
border-t border-gray-200 border-solid
"
>
<BaseButton :loading="isSaving" variant="primary" type="submit">

View File

@@ -143,7 +143,7 @@
<BaseContentPlaceholders v-if="loading">
<BaseContentPlaceholdersText
:lines="1"
class="w-24 h-8 border rounded-md"
class="w-24 h-8 border border-gray-200 rounded-md"
/>
</BaseContentPlaceholders>

View File

@@ -42,7 +42,7 @@
<template v-if="userStore.hasAbilities(ability)" #action>
<button
type="button"
class="flex items-center justify-center w-full px-2 py-2 bg-gray-200 border-none outline-none cursor-pointer "
class="flex items-center justify-center w-full px-2 py-2 bg-gray-200 border-none outline-hidden cursor-pointer "
@click="openTaxModal"
>
<BaseIcon name="CheckCircleIcon" class="h-5 text-primary-400" />

View File

@@ -100,7 +100,7 @@
<BaseContentPlaceholders v-if="isLoading">
<BaseContentPlaceholdersText
:lines="1"
class="w-24 h-8 border rounded-md"
class="w-24 h-8 border border-gray-200 rounded-md"
/>
</BaseContentPlaceholders>
<div v-else class="flex" style="width: 140px" role="group">

View File

@@ -11,7 +11,7 @@
<BaseIcon
v-tooltip="{ content: 'Fetch Latest Exchange rate' }"
name="ArrowPathIcon"
:class="`h-4 w-4 text-primary-500 cursor-pointer outline-none ${
:class="`h-4 w-4 text-primary-500 cursor-pointer outline-hidden ${
isFetching
? ' animate-spin rotate-180 cursor-not-allowed pointer-events-none '
: ''

View File

@@ -2,14 +2,14 @@
<div class="w-full mt-4 tax-select">
<Popover v-slot="{ isOpen }" class="relative">
<PopoverButton
:class="isOpen ? '' : 'text-opacity-90'"
:class="isOpen ? '' : ''"
class="
flex
items-center
text-sm
font-medium
text-primary-400
focus:outline-none focus:border-none
focus:outline-hidden focus:border-none
"
>
<BaseIcon
@@ -39,7 +39,7 @@
overflow-hidden
rounded-md
shadow-lg
ring-1 ring-black ring-opacity-5
ring-1 ring-black/5
"
>
<!-- Tax Search Input -->
@@ -142,7 +142,7 @@
py-3
bg-gray-200
border-none
outline-none
outline-hidden
"
@click="openTaxTypeModal"
>

View File

@@ -53,7 +53,7 @@
flex
justify-end
p-4
border-t border-gray-200 border-solid border-modal-bg
border-t border-gray-200 border-solid
"
>
<BaseButton

View File

@@ -98,7 +98,7 @@
</BaseInputGrid>
</div>
<div class="z-0 flex justify-end p-4 bg-gray-50 border-modal-bg">
<div class="z-0 flex justify-end p-4 bg-gray-50 border-t border-gray-200">
<BaseButton
class="mr-3 text-sm"
variant="primary-outline"

View File

@@ -38,7 +38,7 @@
</BaseInputGroup>
</div>
<div class="z-0 flex justify-end p-4 bg-gray-50 border-modal-bg">
<div class="z-0 flex justify-end p-4 bg-gray-50 border-t border-gray-200">
<BaseButton
class="mr-3 text-sm"
variant="primary-outline"

View File

@@ -21,7 +21,7 @@
>
<template #default="slotProps">
<div
class="z-0 flex justify-end p-4 border-t border-solid border-gray-light"
class="z-0 flex justify-end p-4 border-t border-solid border-gray-200"
>
<BaseButton
class="mr-3 text-sm"

View File

@@ -37,7 +37,7 @@
flex
justify-end
p-4
border-t border-gray-200 border-solid border-modal-bg
border-t border-gray-200 border-solid
"
>
<BaseButton

View File

@@ -75,7 +75,7 @@ _ />
justify-end
px-4
py-4
border-t border-solid border-gray-light
border-t border-solid border-gray-200
"
>
<BaseButton
@@ -280,7 +280,7 @@ function closeNoteModal() {
}
</script>
<style lang="scss">
<style>
.note-modal {
.header-editior .editor-menu-bar {
margin-left: 0.5px;

View File

@@ -122,7 +122,7 @@
flex
justify-end
p-4
border-t border-solid border--200 border-modal-bg
border-t border-solid border-gray-200
"
>
<BaseButton

View File

@@ -106,7 +106,7 @@
flex
justify-end
p-4
border-t border-solid border--200 border-modal-bg
border-t border-solid border-gray-200
"
>
<BaseButton

View File

@@ -116,7 +116,6 @@
<script setup>
import { computed, onMounted, reactive, ref } from 'vue'
import axios from 'axios'
import { useModalStore } from '@/scripts/stores/modal'
import { useTaxTypeStore } from '@/scripts/admin/stores/tax-type'
import { useGlobalStore } from '@/scripts/admin/stores/global'

View File

@@ -179,7 +179,7 @@
flex
justify-end
p-4
border-t border-solid border-gray-light border-modal-bg
border-t border-solid border-gray-200
"
>
<BaseButton

View File

@@ -168,5 +168,5 @@ const loginPageLogo = computed(() => {
})
</script>
<style lang="scss" scoped>
<style scoped>
</style>

View File

@@ -12,7 +12,7 @@
px-4
py-3
md:h-16 md:px-8
bg-gradient-to-r
bg-linear-to-r
from-primary-500
to-primary-400
"

View File

@@ -15,7 +15,7 @@
leave-from="opacity-100"
leave-to="opacity-0"
>
<DialogOverlay class="fixed inset-0 bg-gray-600 bg-opacity-75" />
<DialogOverlay class="fixed inset-0 bg-gray-600/75" />
</TransitionChild>
<TransitionChild
@@ -47,7 +47,7 @@
h-10
ml-1
rounded-full
focus:outline-none
focus:outline-hidden
focus:ring-2
focus:ring-inset
focus:ring-white
@@ -82,9 +82,9 @@
:to="item.link"
:class="[
hasActiveUrl(item.link)
? 'text-primary-500 border-primary-500 bg-gray-100 '
: 'text-black',
'cursor-pointer px-0 pl-4 py-3 border-transparent flex items-center border-l-4 border-solid text-sm not-italic font-medium',
? 'text-primary-500 border-l-primary-500 bg-gray-100 '
: 'text-black border-l-transparent',
'cursor-pointer px-0 pl-4 py-3 flex items-center border-l-4 border-solid text-sm not-italic font-medium',
]"
@click="globalStore.setSidebarVisibility(false)"
>
@@ -136,8 +136,8 @@
:to="item.link"
:class="[
hasActiveUrl(item.link)
? 'text-primary-500 border-primary-500 bg-gray-100 '
: 'text-black',
? 'text-primary-500 border-l-primary-500 bg-gray-100 '
: 'text-black border-l-transparent',
'cursor-pointer px-0 pl-6 hover:bg-gray-50 py-3 group flex items-center border-l-4 border-solid text-sm not-italic font-medium',
]"
>

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,8 +7,7 @@ export const useAuthStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'auth',
return defineStoreFunc('auth', {
state: () => ({
status: '',
@@ -22,9 +21,9 @@ export const useAuthStore = (useWindow = false) => {
actions: {
login(data) {
return new Promise((resolve, reject) => {
axios.get('/sanctum/csrf-cookie').then((response) => {
http.get('/sanctum/csrf-cookie').then((response) => {
if (response) {
axios
http
.post('/login', data)
.then((response) => {
resolve(response)
@@ -45,7 +44,7 @@ export const useAuthStore = (useWindow = false) => {
logout() {
return new Promise((resolve, reject) => {
axios
http
.post('/auth/logout')
.then((response) => {
const notificationStore = useNotificationStore()

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,9 +7,7 @@ export const useBackupStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'backup',
return defineStoreFunc('backup', {
state: () => ({
backups: [],
currentBackupData: {
@@ -21,7 +19,7 @@ export const useBackupStore = (useWindow = false) => {
actions: {
fetchBackups(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/backups`, { params })
.then((response) => {
this.backups = response.data.data
@@ -36,7 +34,7 @@ export const useBackupStore = (useWindow = false) => {
createBackup(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/backups`, data)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -55,7 +53,7 @@ export const useBackupStore = (useWindow = false) => {
removeBackup(params) {
return new Promise((resolve, reject) => {
axios
http
.delete(`/api/v1/backups/${params.disk}`, { params })
.then((response) => {
const notificationStore = useNotificationStore()

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,9 +7,7 @@ export const useCategoryStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'category',
return defineStoreFunc('category', {
state: () => ({
categories: [],
currentCategory: {
@@ -27,7 +25,7 @@ export const useCategoryStore = (useWindow = false) => {
actions: {
fetchCategories(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/categories`, { params })
.then((response) => {
this.categories = response.data.data
@@ -42,7 +40,7 @@ export const useCategoryStore = (useWindow = false) => {
fetchCategory(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/categories/${id}`)
.then((response) => {
this.currentCategory = response.data.data
@@ -57,7 +55,7 @@ export const useCategoryStore = (useWindow = false) => {
addCategory(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/categories', data)
.then((response) => {
this.categories.push(response.data.data)
@@ -77,7 +75,7 @@ export const useCategoryStore = (useWindow = false) => {
updateCategory(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/categories/${data.id}`, data)
.then((response) => {
if (response.data) {
@@ -104,7 +102,7 @@ export const useCategoryStore = (useWindow = false) => {
deleteCategory(id) {
return new Promise((resolve) => {
axios
http
.delete(`/api/v1/categories/${id}`)
.then((response) => {
let index = this.categories.findIndex(

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -8,9 +8,7 @@ export const useCompanyStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'company',
return defineStoreFunc('company', {
state: () => ({
companies: [],
selectedCompany: null,
@@ -26,7 +24,7 @@ export const useCompanyStore = (useWindow = false) => {
fetchBasicMailConfig() {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/company/mail/config')
.then((response) => {
resolve(response)
@@ -40,7 +38,7 @@ export const useCompanyStore = (useWindow = false) => {
updateCompany(data) {
return new Promise((resolve, reject) => {
axios
http
.put('/api/v1/company', data)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -66,7 +64,7 @@ export const useCompanyStore = (useWindow = false) => {
updateCompanyLogo(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/company/upload-logo', data)
.then((response) => {
resolve(response)
@@ -80,7 +78,7 @@ export const useCompanyStore = (useWindow = false) => {
addNewCompany(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/companies', data)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -99,7 +97,7 @@ export const useCompanyStore = (useWindow = false) => {
fetchCompany(params) {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/current-company', params)
.then((response) => {
Object.assign(this.companyForm, response.data.data.address)
@@ -115,7 +113,7 @@ export const useCompanyStore = (useWindow = false) => {
fetchUserCompanies() {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/companies')
.then((response) => {
resolve(response)
@@ -129,7 +127,7 @@ export const useCompanyStore = (useWindow = false) => {
fetchCompanySettings(settings) {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/company/settings', {
params: {
settings,
@@ -147,7 +145,7 @@ export const useCompanyStore = (useWindow = false) => {
updateCompanySettings({ data, message }) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/company/settings', data)
.then((response) => {
Object.assign(this.selectedCompanySettings, data.settings)
@@ -172,7 +170,7 @@ export const useCompanyStore = (useWindow = false) => {
deleteCompany(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/companies/delete`, data)
.then((response) => {
resolve(response)

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import customFieldStub from '@/scripts/admin/stub/custom-field'
@@ -10,9 +10,7 @@ export const useCustomFieldStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'custom-field',
return defineStoreFunc('custom-field', {
state: () => ({
customFields: [],
isRequestOngoing: false,
@@ -41,7 +39,7 @@ export const useCustomFieldStore = (useWindow = false) => {
fetchCustomFields(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/custom-fields`, { params })
.then((response) => {
this.customFields = response.data.data
@@ -63,7 +61,7 @@ export const useCustomFieldStore = (useWindow = false) => {
this.isRequestOngoing = true
axios
http
.get(`/api/v1/custom-fields`, { params })
.then((response) => {
this.customFields = response.data.data
@@ -80,7 +78,7 @@ export const useCustomFieldStore = (useWindow = false) => {
fetchCustomField(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/custom-fields/${id}`)
.then((response) => {
this.currentCustomField = response.data.data
@@ -107,7 +105,7 @@ export const useCustomFieldStore = (useWindow = false) => {
addCustomField(params) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/custom-fields`, params)
.then((response) => {
let data = {
@@ -139,7 +137,7 @@ export const useCustomFieldStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/custom-fields/${params.id}`, params)
.then((response) => {
let data = {
@@ -174,7 +172,7 @@ export const useCustomFieldStore = (useWindow = false) => {
deleteCustomFields(id) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.delete(`/api/v1/custom-fields/${id}`)
.then((response) => {
let index = this.customFields.findIndex(

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useRoute } from 'vue-router'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -12,8 +12,7 @@ export const useCustomerStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'customer',
return defineStoreFunc('customer', {
state: () => ({
customers: [],
totalCustomers: 0,
@@ -75,7 +74,7 @@ export const useCustomerStore = (useWindow = false) => {
fetchCustomers(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/customers`, { params })
.then((response) => {
this.customers = response.data.data
@@ -92,7 +91,7 @@ export const useCustomerStore = (useWindow = false) => {
fetchViewCustomer(params) {
return new Promise((resolve, reject) => {
this.isFetchingViewData = true
axios
http
.get(`/api/v1/customers/${params.id}/stats`, { params })
.then((response) => {
@@ -112,7 +111,7 @@ export const useCustomerStore = (useWindow = false) => {
fetchCustomer(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/customers/${id}`)
.then((response) => {
Object.assign(this.currentCustomer, response.data.data)
@@ -129,7 +128,7 @@ export const useCustomerStore = (useWindow = false) => {
addCustomer(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/customers', data)
.then((response) => {
this.customers.push(response.data.data)
@@ -151,7 +150,7 @@ export const useCustomerStore = (useWindow = false) => {
updateCustomer(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/customers/${data.id}`, data)
.then((response) => {
if (response.data) {
@@ -177,7 +176,7 @@ export const useCustomerStore = (useWindow = false) => {
deleteCustomer(id) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/customers/delete`, id)
.then((response) => {
let index = this.customers.findIndex(
@@ -201,7 +200,7 @@ export const useCustomerStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/customers/delete`, { ids: this.selectedCustomers })
.then((response) => {
this.selectedCustomers.forEach((customer) => {

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useGlobalStore } from '@/scripts/admin/stores/global'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,9 +7,7 @@ export const useDashboardStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'dashboard',
return defineStoreFunc('dashboard', {
state: () => ({
stats: {
totalAmountDue: 0,
@@ -40,7 +38,7 @@ export const useDashboardStore = (useWindow = false) => {
actions: {
loadData(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/dashboard`, { params })
.then((response) => {
// Stats

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,9 +7,7 @@ export const useDiskStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'disk',
return defineStoreFunc('disk', {
state: () => ({
disks: [],
diskDrivers: [],
@@ -71,7 +69,7 @@ export const useDiskStore = (useWindow = false) => {
actions: {
fetchDiskEnv(data) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/disks/${data.disk}`)
.then((response) => {
resolve(response)
@@ -85,7 +83,7 @@ export const useDiskStore = (useWindow = false) => {
fetchDisks(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/disks`, { params })
.then((response) => {
this.disks = response.data.data
@@ -100,7 +98,7 @@ export const useDiskStore = (useWindow = false) => {
fetchDiskDrivers() {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/disk/drivers`)
.then((response) => {
this.diskConfigData = response.data
@@ -116,7 +114,7 @@ export const useDiskStore = (useWindow = false) => {
deleteFileDisk(id) {
return new Promise((resolve, reject) => {
axios
http
.delete(`/api/v1/disks/${id}`)
.then((response) => {
if (response.data.success) {
@@ -141,7 +139,7 @@ export const useDiskStore = (useWindow = false) => {
updateDisk(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/disks/${data.id}`, data)
.then((response) => {
if (response.data) {
@@ -166,7 +164,7 @@ export const useDiskStore = (useWindow = false) => {
createDisk(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/disks`, data)
.then((response) => {
if (response.data) {

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import moment from 'moment'
import Guid from 'guid'
import _ from 'lodash'
@@ -20,9 +20,7 @@ export const useEstimateStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'estimate',
return defineStoreFunc('estimate', {
state: () => ({
templates: [],
@@ -100,7 +98,7 @@ export const useEstimateStore = (useWindow = false) => {
previewEstimate(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/estimates/${params.id}/send/preview`, { params })
.then((response) => {
resolve(response)
@@ -114,7 +112,7 @@ export const useEstimateStore = (useWindow = false) => {
fetchEstimates(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/estimates`, { params })
.then((response) => {
this.estimates = response.data.data
@@ -130,7 +128,7 @@ export const useEstimateStore = (useWindow = false) => {
getNextNumber(params, setState = false) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/next-number?key=estimate`, { params })
.then((response) => {
if (setState) {
@@ -147,7 +145,7 @@ export const useEstimateStore = (useWindow = false) => {
fetchEstimate(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/estimates/${id}`)
.then((response) => {
this.setEstimateData(response.data.data)
@@ -222,7 +220,7 @@ export const useEstimateStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/estimates/${data.id}/send`, data)
.then((response) => {
if (!data.is_preview) {
@@ -242,7 +240,7 @@ export const useEstimateStore = (useWindow = false) => {
addEstimate(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/estimates', data)
.then((response) => {
this.estimates = [...this.estimates, response.data.estimate]
@@ -266,7 +264,7 @@ export const useEstimateStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/estimates/delete`, id)
.then((response) => {
let index = this.estimates.findIndex(
@@ -292,7 +290,7 @@ export const useEstimateStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/estimates/delete`, { ids: this.selectedEstimates })
.then((response) => {
this.selectedEstimates.forEach((estimate) => {
@@ -318,7 +316,7 @@ export const useEstimateStore = (useWindow = false) => {
updateEstimate(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/estimates/${data.id}`, data)
.then((response) => {
let pos = this.estimates.findIndex(
@@ -341,7 +339,7 @@ export const useEstimateStore = (useWindow = false) => {
cloneEstimate(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/estimates/${data.id}/clone`, data)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -360,7 +358,7 @@ export const useEstimateStore = (useWindow = false) => {
markAsAccepted(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/estimates/${data.id}/status`, data)
.then((response) => {
let pos = this.estimates.findIndex(
@@ -387,7 +385,7 @@ export const useEstimateStore = (useWindow = false) => {
markAsRejected(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/estimates/${data.id}/status`, data)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -407,7 +405,7 @@ export const useEstimateStore = (useWindow = false) => {
markAsSent(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/estimates/${data.id}/status`, data)
.then((response) => {
let pos = this.estimates.findIndex(
@@ -435,7 +433,7 @@ export const useEstimateStore = (useWindow = false) => {
convertToInvoice(id) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/estimates/${id}/convert-to-invoice`)
.then((response) => {
notificationStore.showNotification({
@@ -453,7 +451,7 @@ export const useEstimateStore = (useWindow = false) => {
searchEstimate(data) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/estimates?${data}`)
.then((response) => {
resolve(response)
@@ -487,7 +485,7 @@ export const useEstimateStore = (useWindow = false) => {
selectCustomer(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/customers/${id}`)
.then((response) => {
this.newEstimate.customer = response.data.data
@@ -502,7 +500,7 @@ export const useEstimateStore = (useWindow = false) => {
},
fetchEstimateTemplates(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/estimates/templates`, { params })
.then((response) => {
this.templates = response.data.estimateTemplates

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -8,9 +8,7 @@ export const useExchangeRateStore = (useWindow = false) => {
const { global } = window.i18n
const notificationStore = useNotificationStore()
return defineStoreFunc({
id: 'exchange-rate',
return defineStoreFunc('exchange-rate', {
state: () => ({
supportedCurrencies: [],
drivers: [],
@@ -37,7 +35,7 @@ export const useExchangeRateStore = (useWindow = false) => {
actions: {
fetchProviders(params) {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/exchange-rate-providers', { params })
.then((response) => {
this.providers = response.data.data
@@ -52,7 +50,7 @@ export const useExchangeRateStore = (useWindow = false) => {
fetchDefaultProviders() {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/config?key=exchange_rate_drivers`)
.then((response) => {
this.drivers = response.data.exchange_rate_drivers
@@ -68,7 +66,7 @@ export const useExchangeRateStore = (useWindow = false) => {
fetchProvider(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/exchange-rate-providers/${id}`)
.then((response) => {
this.currentExchangeRate = response.data.data
@@ -84,7 +82,7 @@ export const useExchangeRateStore = (useWindow = false) => {
addProvider(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/exchange-rate-providers', data)
.then((response) => {
notificationStore.showNotification({
@@ -104,7 +102,7 @@ export const useExchangeRateStore = (useWindow = false) => {
updateProvider(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/exchange-rate-providers/${data.id}`, data)
.then((response) => {
notificationStore.showNotification({
@@ -122,7 +120,7 @@ export const useExchangeRateStore = (useWindow = false) => {
deleteExchangeRate(id) {
return new Promise((resolve, reject) => {
axios
http
.delete(`/api/v1/exchange-rate-providers/${id}`)
.then((response) => {
let index = this.drivers.findIndex((driver) => driver.id === id)
@@ -148,7 +146,7 @@ export const useExchangeRateStore = (useWindow = false) => {
},
fetchCurrencies(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/supported-currencies`, { params })
.then((response) => {
this.supportedCurrencies = response.data.supportedCurrencies
@@ -163,7 +161,7 @@ export const useExchangeRateStore = (useWindow = false) => {
},
fetchActiveCurrency(params) {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/used-currencies', { params })
.then((response) => {
this.activeUsedCurrencies = response.data.activeUsedCurrencies
@@ -178,7 +176,7 @@ export const useExchangeRateStore = (useWindow = false) => {
},
fetchBulkCurrencies() {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/currencies/used')
.then((response) => {
this.bulkCurrencies = response.data.currencies.map((_m) => {
@@ -196,7 +194,7 @@ export const useExchangeRateStore = (useWindow = false) => {
},
updateBulkExchangeRate(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/currencies/bulk-update-exchange-rate', data)
.then((response) => {
resolve(response)
@@ -209,7 +207,7 @@ export const useExchangeRateStore = (useWindow = false) => {
},
getCurrentExchangeRate(currencyId) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/currencies/${currencyId}/exchange-rate`)
.then((response) => {
resolve(response)
@@ -221,7 +219,7 @@ export const useExchangeRateStore = (useWindow = false) => {
},
getCurrencyConverterServers() {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/config?key=currency_converter_servers')
.then((response) => {
resolve(response)
@@ -234,7 +232,7 @@ export const useExchangeRateStore = (useWindow = false) => {
},
checkForActiveProvider(currency_id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/currencies/${currency_id}/active-provider`)
.then((response) => {
resolve(response)

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { handleError } from '@/scripts/helpers/error-handling'
import { useNotificationStore } from '@/scripts/stores/notification'
@@ -9,9 +9,7 @@ export const useExpenseStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'expense',
return defineStoreFunc('expense', {
state: () => ({
expenses: [],
totalExpenses: 0,
@@ -38,7 +36,7 @@ export const useExpenseStore = (useWindow = false) => {
fetchExpenses(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/expenses`, { params })
.then((response) => {
this.expenses = response.data.data
@@ -54,7 +52,7 @@ export const useExpenseStore = (useWindow = false) => {
fetchExpense(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/expenses/${id}`)
.then((response) => {
if (response.data) {
@@ -97,7 +95,7 @@ export const useExpenseStore = (useWindow = false) => {
const formData = utils.toFormData(data)
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/expenses', formData)
.then((response) => {
this.expenses.push(response.data)
@@ -127,7 +125,7 @@ export const useExpenseStore = (useWindow = false) => {
formData.append('is_attachment_receipt_removed', isAttachmentReceiptRemoved)
return new Promise((resolve) => {
axios.post(`/api/v1/expenses/${id}`, formData).then((response) => {
http.post(`/api/v1/expenses/${id}`, formData).then((response) => {
let pos = this.expenses.findIndex(
(expense) => expense.id === response.data.id
)
@@ -175,7 +173,7 @@ export const useExpenseStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/expenses/delete`, id)
.then((response) => {
let index = this.expenses.findIndex(
@@ -200,7 +198,7 @@ export const useExpenseStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/expenses/delete`, { ids: this.selectedExpenses })
.then((response) => {
this.selectedExpenses.forEach((expense) => {
@@ -223,7 +221,7 @@ export const useExpenseStore = (useWindow = false) => {
},
fetchPaymentModes(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/payment-methods`, { params })
.then((response) => {
this.paymentModes = response.data.data

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useCompanyStore } from './company'
import { useUserStore } from './user'
@@ -11,8 +11,7 @@ export const useGlobalStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'global',
return defineStoreFunc('global', {
state: () => ({
// Global Configuration
config: null,
@@ -48,7 +47,7 @@ export const useGlobalStore = (useWindow = false) => {
actions: {
bootstrap() {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/bootstrap')
.then(async (response) => {
const companyStore = useCompanyStore()
@@ -123,7 +122,7 @@ export const useGlobalStore = (useWindow = false) => {
resolve(this.currencies)
} else {
this.areCurrenciesLoading = true
axios
http
.get('/api/v1/currencies')
.then((response) => {
this.currencies = response.data.data.filter((currency) => {
@@ -143,7 +142,7 @@ export const useGlobalStore = (useWindow = false) => {
fetchConfig(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/config`, { params })
.then((response) => {
if (response.data.languages) {
@@ -165,7 +164,7 @@ export const useGlobalStore = (useWindow = false) => {
if (this.dateFormats.length) {
resolve(this.dateFormats)
} else {
axios
http
.get('/api/v1/date/formats')
.then((response) => {
this.dateFormats = response.data.date_formats
@@ -184,7 +183,7 @@ export const useGlobalStore = (useWindow = false) => {
if (this.timeFormats.length) {
resolve(this.timeFormats)
} else {
axios
http
.get('/api/v1/time/formats')
.then((response) => {
this.timeFormats = response.data.time_formats
@@ -203,7 +202,7 @@ export const useGlobalStore = (useWindow = false) => {
if (this.timeZones.length) {
resolve(this.timeZones)
} else {
axios
http
.get('/api/v1/timezones')
.then((response) => {
this.timeZones = response.data.time_zones
@@ -222,7 +221,7 @@ export const useGlobalStore = (useWindow = false) => {
if (this.countries.length) {
resolve(this.countries)
} else {
axios
http
.get('/api/v1/countries')
.then((response) => {
this.countries = response.data.data
@@ -238,7 +237,7 @@ export const useGlobalStore = (useWindow = false) => {
fetchPlaceholders(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/number-placeholders`, { params })
.then((response) => {
resolve(response)
@@ -260,7 +259,7 @@ export const useGlobalStore = (useWindow = false) => {
updateGlobalSettings({ data, message }) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/settings', data)
.then((response) => {
Object.assign(this.globalSettings, data.settings)

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useCompanyStore } from './company'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -8,9 +8,7 @@ export const useInstallationStore = (useWindow = false) => {
const { global } = window.i18n
const companyStore = useCompanyStore()
return defineStoreFunc({
id: 'installation',
return defineStoreFunc('installation', {
state: () => ({
currentDataBaseData: {
database_connection: 'mysql',
@@ -28,7 +26,7 @@ export const useInstallationStore = (useWindow = false) => {
actions: {
fetchInstallationLanguages() {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/installation/languages`)
.then((response) => {
resolve(response)
@@ -42,7 +40,7 @@ export const useInstallationStore = (useWindow = false) => {
fetchInstallationRequirements() {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/installation/requirements`)
.then((response) => {
resolve(response)
@@ -56,7 +54,7 @@ export const useInstallationStore = (useWindow = false) => {
fetchInstallationStep() {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/installation/wizard-step`)
.then((response) => {
resolve(response)
@@ -70,7 +68,7 @@ export const useInstallationStore = (useWindow = false) => {
addInstallationStep(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/installation/wizard-step`, data)
.then((response) => {
resolve(response)
@@ -84,7 +82,7 @@ export const useInstallationStore = (useWindow = false) => {
addInstallationLanguage(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/installation/wizard-language`, data)
.then((response) => {
resolve(response)
@@ -98,7 +96,7 @@ export const useInstallationStore = (useWindow = false) => {
fetchInstallationPermissions() {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/installation/permissions`)
.then((response) => {
resolve(response)
@@ -112,7 +110,7 @@ export const useInstallationStore = (useWindow = false) => {
fetchInstallationDatabase(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/installation/database/config`, { params })
.then((response) => {
resolve(response)
@@ -126,7 +124,7 @@ export const useInstallationStore = (useWindow = false) => {
addInstallationDatabase(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/installation/database/config`, data)
.then((response) => {
resolve(response)
@@ -140,7 +138,7 @@ export const useInstallationStore = (useWindow = false) => {
addInstallationFinish() {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/installation/finish`)
.then((response) => {
resolve(response)
@@ -154,7 +152,7 @@ export const useInstallationStore = (useWindow = false) => {
setInstallationDomain(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/installation/set-domain`, data)
.then((response) => {
resolve(response)
@@ -168,9 +166,9 @@ export const useInstallationStore = (useWindow = false) => {
installationLogin() {
return new Promise((resolve, reject) => {
axios.get('/sanctum/csrf-cookie').then((response) => {
http.get('/sanctum/csrf-cookie').then((response) => {
if (response) {
axios
http
.post('/api/v1/installation/login')
.then((response) => {
companyStore.setSelectedCompany(response.data.company)
@@ -187,7 +185,7 @@ export const useInstallationStore = (useWindow = false) => {
checkAuthenticated() {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/auth/check`)
.then((response) => {
resolve(response)

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import moment from 'moment'
import Guid from 'guid'
import _ from 'lodash'
@@ -22,8 +22,7 @@ export const useInvoiceStore = (useWindow = false) => {
const { global } = window.i18n
const notificationStore = useNotificationStore()
return defineStoreFunc({
id: 'invoice',
return defineStoreFunc('invoice', {
state: () => ({
templates: [],
invoices: [],
@@ -108,7 +107,7 @@ export const useInvoiceStore = (useWindow = false) => {
previewInvoice(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/invoices/${params.id}/send/preview`, { params })
.then((response) => {
resolve(response)
@@ -122,7 +121,7 @@ export const useInvoiceStore = (useWindow = false) => {
fetchInvoices(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/invoices`, { params })
.then((response) => {
this.invoices = response.data.data
@@ -138,7 +137,7 @@ export const useInvoiceStore = (useWindow = false) => {
fetchInvoice(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/invoices/${id}`)
.then((response) => {
this.setInvoiceData(response.data.data)
@@ -204,7 +203,7 @@ export const useInvoiceStore = (useWindow = false) => {
sendInvoice(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/invoices/${data.id}/send`, data)
.then((response) => {
notificationStore.showNotification({
@@ -222,7 +221,7 @@ export const useInvoiceStore = (useWindow = false) => {
addInvoice(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/invoices', data)
.then((response) => {
this.invoices = [...this.invoices, response.data.invoice]
@@ -243,7 +242,7 @@ export const useInvoiceStore = (useWindow = false) => {
deleteInvoice(id) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/invoices/delete`, id)
.then((response) => {
let index = this.invoices.findIndex(
@@ -266,7 +265,7 @@ export const useInvoiceStore = (useWindow = false) => {
deleteMultipleInvoices(id) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/invoices/delete`, { ids: this.selectedInvoices })
.then((response) => {
this.selectedInvoices.forEach((invoice) => {
@@ -292,7 +291,7 @@ export const useInvoiceStore = (useWindow = false) => {
updateInvoice(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/invoices/${data.id}`, data)
.then((response) => {
let pos = this.invoices.findIndex(
@@ -316,7 +315,7 @@ export const useInvoiceStore = (useWindow = false) => {
cloneInvoice(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/invoices/${data.id}/clone`, data)
.then((response) => {
notificationStore.showNotification({
@@ -334,7 +333,7 @@ export const useInvoiceStore = (useWindow = false) => {
markAsSent(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/invoices/${data.id}/status`, data)
.then((response) => {
let pos = this.invoices.findIndex(
@@ -360,7 +359,7 @@ export const useInvoiceStore = (useWindow = false) => {
getNextNumber(params, setState = false) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/next-number?key=invoice`, { params })
.then((response) => {
if (setState) {
@@ -377,7 +376,7 @@ export const useInvoiceStore = (useWindow = false) => {
searchInvoice(data) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/invoices?${data}`)
.then((response) => {
resolve(response)
@@ -411,7 +410,7 @@ export const useInvoiceStore = (useWindow = false) => {
selectCustomer(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/customers/${id}`)
.then((response) => {
this.newInvoice.customer = response.data.data
@@ -427,7 +426,7 @@ export const useInvoiceStore = (useWindow = false) => {
fetchInvoiceTemplates(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/invoices/templates`, { params })
.then((response) => {
this.templates = response.data.invoiceTemplates

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,8 +7,7 @@ export const useItemStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'item',
return defineStoreFunc('item', {
state: () => ({
items: [],
totalItems: 0,
@@ -45,7 +44,7 @@ export const useItemStore = (useWindow = false) => {
},
fetchItems(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/items`, { params })
.then((response) => {
this.items = response.data.data
@@ -62,7 +61,7 @@ export const useItemStore = (useWindow = false) => {
fetchItem(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/items/${id}`)
.then((response) => {
if (response.data) {
@@ -79,7 +78,7 @@ export const useItemStore = (useWindow = false) => {
addItem(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/items', data)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -102,7 +101,7 @@ export const useItemStore = (useWindow = false) => {
updateItem(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/items/${data.id}`, data)
.then((response) => {
if (response.data) {
@@ -133,7 +132,7 @@ export const useItemStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/items/delete`, id)
.then((response) => {
let index = this.items.findIndex((item) => item.id === id)
@@ -157,7 +156,7 @@ export const useItemStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/items/delete`, { ids: this.selectedItems })
.then((response) => {
this.selectedItems.forEach((item) => {
@@ -205,7 +204,7 @@ export const useItemStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/units`, data)
.then((response) => {
this.itemUnits.push(response.data.data)
@@ -239,7 +238,7 @@ export const useItemStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/units/${data.id}`, data)
.then((response) => {
let pos = this.itemUnits.findIndex(
@@ -274,7 +273,7 @@ export const useItemStore = (useWindow = false) => {
fetchItemUnits(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/units`, { params })
.then((response) => {
this.itemUnits = response.data.data
@@ -289,7 +288,7 @@ export const useItemStore = (useWindow = false) => {
fetchItemUnit(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/units/${id}`)
.then((response) => {
this.currentItemUnit = response.data.data
@@ -306,7 +305,7 @@ export const useItemStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.delete(`/api/v1/units/${id}`)
.then((response) => {
if (!response.data.error) {

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,9 +7,7 @@ export const useMailDriverStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'mail-driver',
return defineStoreFunc('mail-driver', {
state: () => ({
mailConfigData: null,
mail_driver: 'smtp',
@@ -57,7 +55,7 @@ export const useMailDriverStore = (useWindow = false) => {
actions: {
fetchMailDrivers() {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/mail/drivers')
.then((response) => {
if (response.data) {
@@ -74,7 +72,7 @@ export const useMailDriverStore = (useWindow = false) => {
fetchMailConfig() {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/mail/config')
.then((response) => {
if (response.data) {
@@ -92,7 +90,7 @@ export const useMailDriverStore = (useWindow = false) => {
updateMailConfig(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/mail/config', data)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -118,7 +116,7 @@ export const useMailDriverStore = (useWindow = false) => {
sendTestMail(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/mail/test', data)
.then((response) => {
const notificationStore = useNotificationStore()

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { handleError } from '@/scripts/helpers/error-handling'
import { useNotificationStore } from '@/scripts/stores/notification'
@@ -7,9 +7,7 @@ export const useModuleStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'modules',
return defineStoreFunc('modules', {
state: () => ({
currentModule: {},
modules: [],
@@ -27,7 +25,7 @@ export const useModuleStore = (useWindow = false) => {
actions: {
fetchModules(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/modules`)
.then((response) => {
this.modules = response.data.data
@@ -43,7 +41,7 @@ export const useModuleStore = (useWindow = false) => {
fetchModule(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/modules/${id}`)
.then((response) => {
if (response.data.error === 'invalid_token') {
@@ -67,7 +65,7 @@ export const useModuleStore = (useWindow = false) => {
checkApiToken(token) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/modules/check?api_token=${token}`)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -88,7 +86,7 @@ export const useModuleStore = (useWindow = false) => {
disableModule(module) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/modules/${module}/disable`)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -109,7 +107,7 @@ export const useModuleStore = (useWindow = false) => {
enableModule(module) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/modules/${module}/enable`)
.then((response) => {
const notificationStore = useNotificationStore()

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -6,9 +6,7 @@ export const useNotesStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'notes',
return defineStoreFunc('notes', {
state: () => ({
notes: [],
currentNote: {
@@ -40,7 +38,7 @@ export const useNotesStore = (useWindow = false) => {
fetchNotes(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/notes`, { params })
.then((response) => {
this.notes = response.data.data
@@ -55,7 +53,7 @@ export const useNotesStore = (useWindow = false) => {
fetchNote(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/notes/${id}`)
.then((response) => {
this.currentNote = response.data.data
@@ -70,7 +68,7 @@ export const useNotesStore = (useWindow = false) => {
addNote(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/notes', data)
.then((response) => {
this.notes.push(response.data)
@@ -85,7 +83,7 @@ export const useNotesStore = (useWindow = false) => {
updateNote(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/notes/${data.id}`, data)
.then((response) => {
if (response.data) {
@@ -105,7 +103,7 @@ export const useNotesStore = (useWindow = false) => {
deleteNote(id) {
return new Promise((resolve, reject) => {
axios
http
.delete(`/api/v1/notes/${id}`)
.then((response) => {
let index = this.notes.findIndex((note) => note.id === id)

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import moment from 'moment'
import { defineStore } from 'pinia'
import { useRoute } from 'vue-router'
@@ -12,9 +12,7 @@ export const usePaymentStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'payment',
return defineStoreFunc('payment', {
state: () => ({
payments: [],
paymentTotalCount: 0,
@@ -99,7 +97,7 @@ export const usePaymentStore = (useWindow = false) => {
fetchPayments(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/payments`, { params })
.then((response) => {
this.payments = response.data.data
@@ -115,7 +113,7 @@ export const usePaymentStore = (useWindow = false) => {
fetchPayment(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/payments/${id}`)
.then((response) => {
Object.assign(this.currentPayment, response.data.data)
@@ -130,7 +128,7 @@ export const usePaymentStore = (useWindow = false) => {
addPayment(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/payments', data)
.then((response) => {
this.payments.push(response.data)
@@ -150,7 +148,7 @@ export const usePaymentStore = (useWindow = false) => {
updatePayment(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/payments/${data.id}`, data)
.then((response) => {
if (response.data) {
@@ -179,7 +177,7 @@ export const usePaymentStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/payments/delete`, id)
.then((response) => {
let index = this.payments.findIndex(
@@ -203,7 +201,7 @@ export const usePaymentStore = (useWindow = false) => {
deleteMultiplePayments() {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/payments/delete`, { ids: this.selectedPayments })
.then((response) => {
this.selectedPayments.forEach((payment) => {
@@ -260,7 +258,7 @@ export const usePaymentStore = (useWindow = false) => {
searchPayment(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/payments`, { params })
.then((response) => {
this.payments = response.data
@@ -275,7 +273,7 @@ export const usePaymentStore = (useWindow = false) => {
previewPayment(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/payments/${params.id}/send/preview`, { params })
.then((response) => {
resolve(response)
@@ -289,7 +287,7 @@ export const usePaymentStore = (useWindow = false) => {
sendEmail(data) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/payments/${data.id}/send`, data)
.then((response) => {
const notificationStore = useNotificationStore()
@@ -308,7 +306,7 @@ export const usePaymentStore = (useWindow = false) => {
getNextNumber(params, setState = false) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/next-number?key=payment`, { params })
.then((response) => {
if (setState) {
@@ -331,7 +329,7 @@ export const usePaymentStore = (useWindow = false) => {
fetchPaymentModes(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/payment-methods`, { params })
.then((response) => {
this.paymentModes = response.data.data
@@ -346,7 +344,7 @@ export const usePaymentStore = (useWindow = false) => {
fetchPaymentMode(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/payment-methods/${id}`)
.then((response) => {
this.currentPaymentMode = response.data.data
@@ -362,7 +360,7 @@ export const usePaymentStore = (useWindow = false) => {
addPaymentMode(data) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/payment-methods`, data)
.then((response) => {
this.paymentModes.push(response.data.data)
@@ -382,7 +380,7 @@ export const usePaymentStore = (useWindow = false) => {
updatePaymentMode(data) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/payment-methods/${data.id}`, data)
.then((response) => {
if (response.data) {
@@ -410,7 +408,7 @@ export const usePaymentStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.delete(`/api/v1/payment-methods/${id}`)
.then((response) => {
let index = this.paymentModes.findIndex(

View File

@@ -1,15 +1,13 @@
const { defineStore } = window.pinia
import { handleError } from '@/scripts/helpers/error-handling'
import { useNotificationStore } from '@/scripts/stores/notification'
import axios from 'axios'
import http from '@/scripts/http'
export const usePDFDriverStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'pdf-driver',
return defineStoreFunc('pdf-driver', {
state: () => ({
pdfDriverConfig: null,
pdf_driver: 'dompdf',
@@ -28,7 +26,7 @@ export const usePDFDriverStore = (useWindow = false) => {
actions: {
async fetchDrivers() {
try {
const response = await axios.get('/api/v1/pdf/drivers')
const response = await http.get('/api/v1/pdf/drivers')
this.pdf_drivers = response.data
} catch (err) {
handleError(err)
@@ -37,7 +35,7 @@ export const usePDFDriverStore = (useWindow = false) => {
},
async fetchConfig() {
try {
const response = await axios.get('/api/v1/pdf/config')
const response = await http.get('/api/v1/pdf/config')
this.pdfDriverConfig = response.data
this.pdf_driver = response.data.pdf_driver
} catch (err) {
@@ -47,7 +45,7 @@ export const usePDFDriverStore = (useWindow = false) => {
},
async updateConfig(data) {
try {
const response = await axios.post('/api/v1/pdf/config', data)
const response = await http.post('/api/v1/pdf/config', data)
const notificationStore = useNotificationStore()
if (response.data.success) {
notificationStore.showNotification({

View File

@@ -1,5 +1,5 @@
import { defineStore } from 'pinia'
import axios from 'axios'
import http from '@/scripts/http'
import recurringInvoiceStub from '@/scripts/admin/stub/recurring-invoice'
import recurringInvoiceItemStub from '@/scripts/admin/stub/recurring-invoice-item'
import TaxStub from '../stub/tax'
@@ -20,9 +20,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'recurring-invoice',
return defineStoreFunc('recurring-invoice', {
state: () => ({
templates: [],
recurringInvoices: [],
@@ -162,7 +160,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
addRecurringInvoice(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/recurring-invoices', data)
.then((response) => {
this.recurringInvoices = [
@@ -187,7 +185,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
fetchRecurringInvoice(id) {
return new Promise((resolve, reject) => {
this.isFetchingViewData = true
axios
http
.get(`/api/v1/recurring-invoices/${id}`)
.then((response) => {
Object.assign(this.newRecurringInvoice, response.data.data)
@@ -207,7 +205,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
updateRecurringInvoice(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/recurring-invoices/${data.id}`, data)
.then((response) => {
resolve(response)
@@ -234,7 +232,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
selectCustomer(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/customers/${id}`)
.then((response) => {
this.newRecurringInvoice.customer = response.data.data
@@ -250,7 +248,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
searchRecurringInvoice(data) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/recurring-invoices?${data}`)
.then((response) => {
resolve(response)
@@ -264,7 +262,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
fetchRecurringInvoices(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/recurring-invoices`, { params })
.then((response) => {
this.recurringInvoices = response.data.data
@@ -282,7 +280,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
deleteRecurringInvoice(id) {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/recurring-invoices/delete`, id)
.then((response) => {
let index = this.recurringInvoices.findIndex(
@@ -304,7 +302,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
if (id) {
ids = [id]
}
axios
http
.post(`/api/v1/recurring-invoices/delete`, {
ids: ids,
})
@@ -492,7 +490,7 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
fetchRecurringInvoiceFrequencyDate(params) {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/recurring-invoice-frequency', { params })
.then((response) => {
this.newRecurringInvoice.next_invoice_at =

View File

@@ -1,4 +1,3 @@
import axios from 'axios'
import { defineStore } from 'pinia'
import { useBackupStore } from './backup'
import { useCategoryStore } from './category'
@@ -30,8 +29,7 @@ export const useResetStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'reset',
return defineStoreFunc('reset', {
actions: {
clearPinia() {
const backupStore = useBackupStore()

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import _ from 'lodash'
@@ -8,8 +8,7 @@ export const useRoleStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'role',
return defineStoreFunc('role', {
state: () => ({
roles: [],
allAbilities: [],
@@ -38,7 +37,7 @@ export const useRoleStore = (useWindow = false) => {
actions: {
fetchRoles(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/roles`, { params })
.then((response) => {
this.roles = response.data.data
@@ -53,7 +52,7 @@ export const useRoleStore = (useWindow = false) => {
fetchRole(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/roles/${id}`)
.then((response) => {
this.currentRole.name = response.data.data.name
@@ -81,7 +80,7 @@ export const useRoleStore = (useWindow = false) => {
addRole(data) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/roles', data)
.then((response) => {
this.roles.push(response.data.role)
@@ -101,7 +100,7 @@ export const useRoleStore = (useWindow = false) => {
updateRole(data) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/roles/${data.id}`, data)
.then((response) => {
if (response.data) {
@@ -128,7 +127,7 @@ export const useRoleStore = (useWindow = false) => {
if (this.allAbilities.length) {
resolve(this.allAbilities)
} else {
axios
http
.get(`/api/v1/abilities`, { params })
.then((response) => {
this.allAbilities = response.data.abilities
@@ -146,7 +145,7 @@ export const useRoleStore = (useWindow = false) => {
deleteRole(id) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.delete(`/api/v1/roles/${id}`)
.then((response) => {
let index = this.roles.findIndex((role) => role.id === id)

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,9 +7,7 @@ export const useTaxTypeStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'taxType',
return defineStoreFunc('taxType', {
state: () => ({
taxTypes: [],
currentTaxType: {
@@ -44,7 +42,7 @@ export const useTaxTypeStore = (useWindow = false) => {
fetchTaxTypes(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/tax-types`, { params })
.then((response) => {
this.taxTypes = response.data.data
@@ -59,7 +57,7 @@ export const useTaxTypeStore = (useWindow = false) => {
fetchTaxType(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/tax-types/${id}`)
.then((response) => {
this.currentTaxType = response.data.data
@@ -75,7 +73,7 @@ export const useTaxTypeStore = (useWindow = false) => {
addTaxType(data) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/tax-types', data)
.then((response) => {
this.taxTypes.push(response.data.data)
@@ -95,7 +93,7 @@ export const useTaxTypeStore = (useWindow = false) => {
updateTaxType(data) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/tax-types/${data.id}`, data)
.then((response) => {
if (response.data) {
@@ -119,7 +117,7 @@ export const useTaxTypeStore = (useWindow = false) => {
fetchSalesTax(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/m/sales-tax-us/current-tax', data)
.then((response) => {
if (response.data) {
@@ -141,7 +139,7 @@ export const useTaxTypeStore = (useWindow = false) => {
deleteTaxType(id) {
return new Promise((resolve, reject) => {
axios
http
.delete(`/api/v1/tax-types/${id}`)
.then((response) => {
if (response.data.success) {

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,9 +7,7 @@ export const useUserStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'user',
return defineStoreFunc('user', {
state: () => ({
currentUser: null,
currentAbilities: [],
@@ -31,7 +29,7 @@ export const useUserStore = (useWindow = false) => {
actions: {
updateCurrentUser(data) {
return new Promise((resolve, reject) => {
axios
http
.put('/api/v1/me', data)
.then((response) => {
this.currentUser = response.data.data
@@ -52,7 +50,7 @@ export const useUserStore = (useWindow = false) => {
fetchCurrentUser(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/me`, params)
.then((response) => {
this.currentUser = response.data.data
@@ -68,7 +66,7 @@ export const useUserStore = (useWindow = false) => {
uploadAvatar(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/me/upload-avatar', data)
.then((response) => {
this.currentUser.avatar = response.data.data.avatar
@@ -83,7 +81,7 @@ export const useUserStore = (useWindow = false) => {
fetchUserSettings(settings) {
return new Promise((resolve, reject) => {
axios
http
.get('/api/v1/me/settings', {
params: {
settings,
@@ -101,7 +99,7 @@ export const useUserStore = (useWindow = false) => {
updateUserSettings(data) {
return new Promise((resolve, reject) => {
axios
http
.put('/api/v1/me/settings', data)
.then((response) => {
if (data.settings.language) {

View File

@@ -1,4 +1,4 @@
import axios from 'axios'
import http from '@/scripts/http'
import { defineStore } from 'pinia'
import { useNotificationStore } from '@/scripts/stores/notification'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -7,8 +7,7 @@ export const useUsersStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'users',
return defineStoreFunc('users', {
state: () => ({
roles: [],
users: [],
@@ -42,7 +41,7 @@ export const useUsersStore = (useWindow = false) => {
fetchUsers(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/users`, { params })
.then((response) => {
this.users = response.data.data
@@ -58,7 +57,7 @@ export const useUsersStore = (useWindow = false) => {
fetchUser(id) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/users/${id}`)
.then((response) => {
this.userData = response.data.data
@@ -82,7 +81,7 @@ export const useUsersStore = (useWindow = false) => {
fetchRoles(state) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/roles`)
.then((response) => {
this.roles = response.data.data
@@ -97,7 +96,7 @@ export const useUsersStore = (useWindow = false) => {
addUser(data) {
return new Promise((resolve, reject) => {
axios
http
.post('/api/v1/users', data)
.then((response) => {
this.users.push(response.data)
@@ -118,7 +117,7 @@ export const useUsersStore = (useWindow = false) => {
updateUser(data) {
return new Promise((resolve, reject) => {
axios
http
.put(`/api/v1/users/${data.id}`, data)
.then((response) => {
if (response) {
@@ -145,7 +144,7 @@ export const useUsersStore = (useWindow = false) => {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/users/delete`, { users: id.ids })
.then((response) => {
let index = this.users.findIndex((user) => user.id === id)
@@ -165,7 +164,7 @@ export const useUsersStore = (useWindow = false) => {
deleteMultipleUsers() {
return new Promise((resolve, reject) => {
axios
http
.post(`/api/v1/users/delete`, { users: this.selectedUsers })
.then((response) => {
this.selectedUsers.forEach((user) => {
@@ -190,7 +189,7 @@ export const useUsersStore = (useWindow = false) => {
searchUsers(params) {
return new Promise((resolve, reject) => {
axios
http
.get(`/api/v1/search`, { params })
.then((response) => {
this.userList = response.data.users.data

View File

@@ -41,7 +41,7 @@
</template>
<script type="text/babel" setup>
import axios from 'axios'
import http from '@/scripts/http'
import { reactive, ref, computed } from 'vue'
import { required, email, helpers } from '@vuelidate/validators'
import { useVuelidate } from '@vuelidate/core'
@@ -74,7 +74,7 @@ async function onSubmit(e) {
if (!v$.value.$invalid) {
try {
isLoading.value = true
let res = await axios.post('/api/v1/auth/password/email', formData)
let res = await http.post('/api/v1/auth/password/email', formData)
if (res.data) {
notificationStore.showNotification({
type: 'success',

View File

@@ -56,7 +56,7 @@
</template>
<script setup>
import axios from 'axios'
import http from '@/scripts/http'
import { ref, computed, onMounted } from 'vue'
import { useNotificationStore } from '@/scripts/stores/notification'
import { useRouter } from 'vue-router'
@@ -96,8 +96,6 @@ const getInputType = computed(() => {
})
async function onSubmit() {
axios.defaults.withCredentials = true
v$.value.$touch()
if (v$.value.$invalid) {

View File

@@ -58,7 +58,7 @@ import useVuelidate from '@vuelidate/core'
import { required, email, minLength, sameAs } from '@vuelidate/validators'
import { useNotificationStore } from '@/scripts/stores/notification'
import { useRoute, useRouter } from 'vue-router'
import axios from 'axios'
import http from '@/scripts/http'
import { useI18n } from 'vue-i18n'
import { handleError } from '@/scripts/helpers/error-handling'
@@ -141,7 +141,7 @@ async function onSubmit(e) {
token: route.params.token,
}
isLoading.value = true
let res = await axios.post('/api/v1/auth/reset/password', data)
let res = await http.post('/api/v1/auth/reset/password', data)
isLoading.value = false
if (res.data) {
notificationStore.showNotification({

View File

@@ -122,9 +122,9 @@
:id="'customer-' + customer.id"
:to="`/admin/customers/${customer.id}/view`"
:class="[
'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-transparent',
'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-l-transparent',
{
'bg-gray-100 border-l-4 border-primary-500 border-solid':
'bg-gray-100 border-l-4 border-l-primary-500 border-solid':
hasActiveUrl(customer.id),
},
]"

View File

@@ -169,9 +169,9 @@
:id="'estimate-' + estimate.id"
:to="`/admin/estimates/${estimate.id}/view`"
:class="[
'flex justify-between side-estimate p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-transparent',
'flex justify-between side-estimate p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-l-transparent',
{
'bg-gray-100 border-l-4 border-primary-500 border-solid':
'bg-gray-100 border-l-4 border-l-primary-500 border-solid':
hasActiveUrl(estimate.id),
},
]"

View File

@@ -15,7 +15,7 @@
</template>
<script>
import { ref, computed } from 'vue'
import { ref, computed, onMounted } from 'vue'
import Mysql from './database/MysqlDatabase.vue'
import Pgsql from './database/PgsqlDatabase.vue'
import Sqlite from './database/SqliteDatabase.vue'
@@ -47,8 +47,9 @@ export default {
})
async function getDatabaseConfig(connection) {
let params = {
connection,
let params = {}
if (connection) {
params.connection = connection
}
const res = await installationStore.fetchInstallationDatabase(params)
@@ -58,10 +59,16 @@ export default {
res.data.config.database_connection
}
if (connection === 'sqlite') {
if (res.data.config.database_connection === 'sqlite') {
databaseData.value.database_name = res.data.config.database_name
} else {
databaseData.value.database_name = null
if (res.data.config.database_host) {
databaseData.value.database_hostname = res.data.config.database_host
}
if (res.data.config.database_port) {
databaseData.value.database_port = res.data.config.database_port
}
}
}
@@ -127,6 +134,10 @@ export default {
}
}
onMounted(() => {
getDatabaseConfig()
})
return {
databaseData,
database_connection,

View File

@@ -22,8 +22,8 @@
<ul class="w-full text-gray-600 list-disc list-inside">
<li class="text-sm leading-8">
{{ $t('wizard.verify_domain.notes.not_contain') }}
<b class="inline-block px-1 bg-gray-100 rounded-sm">https://</b> {{ $t('wizard.verify_domain.notes.or') }}
<b class="inline-block px-1 bg-gray-100 rounded-sm">http</b> {{ $t('wizard.verify_domain.notes.in_front') }}
<b class="inline-block px-1 bg-gray-100 rounded-xs">https://</b> {{ $t('wizard.verify_domain.notes.or') }}
<b class="inline-block px-1 bg-gray-100 rounded-xs">http</b> {{ $t('wizard.verify_domain.notes.in_front') }}
</li>
<li class="text-sm leading-8">
{{ $t('wizard.verify_domain.notes.if_you') }}

View File

@@ -41,8 +41,6 @@ export default {
const mailDriverStore = useMailDriverStore()
mailDriverStore.mail_driver = 'mail'
loadData()
function changeDriver(value) {
@@ -52,6 +50,7 @@ export default {
async function loadData() {
isFetchingInitialData.value = true
await mailDriverStore.fetchMailDrivers()
await mailDriverStore.fetchMailConfig()
isFetchingInitialData.value = false
}

View File

@@ -412,9 +412,9 @@ onSearched = debounce(onSearched, 500)
:id="'invoice-' + invoice.id"
:to="`/admin/invoices/${invoice.id}/view`"
:class="[
'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-transparent',
'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-l-transparent',
{
'bg-gray-100 border-l-4 border-primary-500 border-solid':
'bg-gray-100 border-l-4 border-l-primary-500 border-solid':
hasActiveUrl(invoice.id),
},
]"

View File

@@ -32,7 +32,7 @@
:class="[
'relative md:h-24 lg:h-36 rounded hover:bg-gray-50',
{
'outline-none ring ring-offset-1 ring-primary-500':
'outline-hidden ring-3 ring-offset-1 ring-primary-500':
displayVideo,
},
]"
@@ -66,7 +66,7 @@
:class="[
'relative md:h-24 lg:h-36 rounded hover:bg-gray-50',
{
'outline-none ring ring-offset-1 ring-primary-500':
'outline-hidden ring-3 ring-offset-1 ring-primary-500':
displayImage === screenshot.url,
},
]"
@@ -195,7 +195,7 @@
checked
? 'bg-primary-50 border-primary-200 z-10'
: 'border-gray-200',
'relative border p-4 flex flex-col cursor-pointer md:pl-4 md:pr-6 md:grid md:grid-cols-2 focus:outline-none',
'relative border p-4 flex flex-col cursor-pointer md:pl-4 md:pr-6 md:grid md:grid-cols-2 focus:outline-hidden',
]"
>
<div class="flex items-center text-sm">
@@ -673,7 +673,7 @@ import { useRoute } from 'vue-router'
import { useDialogStore } from '@/scripts/stores/dialog'
import { useI18n } from 'vue-i18n'
import moment from 'moment'
import axios from 'axios'
import http from '@/scripts/http'
import ModulePlaceholder from './partials/ModulePlaceholder.vue'
import RecentModuleCard from './partials/RecentModuleCard.vue'
import { useNotificationStore } from '@/scripts/stores/notification'
@@ -853,7 +853,7 @@ async function installModule() {
module: moduleData.value.module_name,
}
let requestResponse = await axios.post(currentStep.stepUrl, updateParams)
let requestResponse = await http.post(currentStep.stepUrl, updateParams)
currentStep.completed = true
if (requestResponse.data) {

View File

@@ -3,7 +3,7 @@
class="
relative
shadow-md
border-2 border-gray-200 border-opacity-60
border-2 border-gray-200/60
rounded-lg
cursor-pointer
overflow-hidden
@@ -18,7 +18,7 @@
<label
v-if="data.purchased"
class="
bg-white bg-opacity-75
bg-white/75
text-xs
px-3
py-1
@@ -33,7 +33,7 @@
v-if="data.installed"
class="
ml-2
bg-white bg-opacity-75
bg-white/75
text-xs
px-3
py-1

View File

@@ -3,7 +3,7 @@
<div
class="
shadow-md
border-2 border-gray-200 border-opacity-60
border-2 border-gray-200/60
rounded-lg
cursor-pointer
overflow-hidden

View File

@@ -10,7 +10,7 @@
<div
class="
w-full
bg-white bg-opacity-75
bg-white/75
backdrop-filter backdrop-blur
py-2
px-4

View File

@@ -147,9 +147,9 @@
:id="'payment-' + payment.id"
:to="`/admin/payments/${payment.id}/view`"
:class="[
'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-transparent',
'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-l-transparent',
{
'bg-gray-100 border-l-4 border-primary-500 border-solid':
'bg-gray-100 border-l-4 border-l-primary-500 border-solid':
hasActiveUrl(payment.id),
},
]"

View File

@@ -251,9 +251,9 @@ onSearched = debounce(onSearched, 500)
:id="'recurring-invoice-' + invoice.id"
:to="`/admin/recurring-invoices/${invoice.id}/view`"
:class="[
'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-transparent',
'flex justify-between side-invoice p-4 cursor-pointer hover:bg-gray-100 items-center border-l-4 border-l-transparent',
{
'bg-gray-100 border-l-4 border-primary-500 border-solid':
'bg-gray-100 border-l-4 border-l-primary-500 border-solid':
hasActiveUrl(invoice.id),
},
]"

View File

@@ -121,7 +121,7 @@
<div class="mt-5">
<button
type="button"
class="inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md text-red-700 bg-red-100 hover:bg-red-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:text-sm"
class="inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-md text-red-700 bg-red-100 hover:bg-red-200 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:text-sm"
@click="removeCompany"
>
{{ $t('general.delete') }}

View File

@@ -214,7 +214,7 @@
<script setup>
import { useNotificationStore } from '@/scripts/stores/notification'
import axios from 'axios'
import http from '@/scripts/http'
import LoadingIcon from '@/scripts/components/icons/LoadingIcon.vue'
import { reactive, ref, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n'
@@ -301,7 +301,7 @@ window.addEventListener('beforeunload', (event) => {
// Created
axios.get('/api/v1/app/version').then((res) => {
http.get('/api/v1/app/version').then((res) => {
currentVersion.value = res.data.version
insiderChannel.value = res.data.channel === 'insider'
})
@@ -344,7 +344,7 @@ function statusClass(step) {
async function checkUpdate() {
try {
isCheckingforUpdate.value = true
let response = await axios.get('/api/v1/check/update', {
let response = await http.get('/api/v1/check/update', {
params: {
channel: insiderChannel ? 'insider' : ''
}
@@ -409,7 +409,7 @@ function onUpdateApp() {
path: path || null,
}
let requestResponse = await axios.post(
let requestResponse = await http.post(
currentStep.stepUrl,
updateParams
)

View File

@@ -12,10 +12,9 @@
md:h-9
ml-2
text-sm text-white
bg-white
bg-white/20
rounded
cursor-pointer
bg-opacity-20
"
@click="isShow = !isShow"
>

View File

@@ -1,7 +1,7 @@
I
<template>
<div class="h-screen overflow-y-auto min-h-0">
<div class="bg-gradient-to-r from-primary-500 to-primary-400 h-5"></div>
<div class="bg-linear-to-r from-primary-500 to-primary-400 h-5"></div>
<div
class="
@@ -73,7 +73,7 @@ I
</template>
<script setup>
import axios from 'axios'
import http from '@/scripts/http'
import { ref, reactive, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import InvoiceInformationCard from '@/scripts/components/InvoiceInformationCard.vue'
@@ -85,7 +85,7 @@ const router = useRouter()
loadInvoice()
async function loadInvoice() {
let res = await axios.get(`/customer/invoices/${route.params.hash}`)
let res = await http.get(`/customer/invoices/${route.params.hash}`)
invoiceData.value = res.data.data
}

View File

@@ -437,9 +437,9 @@ export default {
required: false,
default: () => ({
container:
'p-0 relative mx-auto w-full flex items-center justify-end box-border cursor-pointer border border-gray-200 rounded-md bg-white text-sm leading-snug outline-none max-h-10',
'p-0 relative mx-auto w-full flex items-center justify-end box-border cursor-pointer border border-gray-200 rounded-md bg-white text-sm leading-snug outline-hidden max-h-10',
containerDisabled:
'cursor-default bg-gray-200 bg-opacity-50 !text-gray-400',
'cursor-default bg-gray-200/50 !text-gray-400',
containerOpen: '',
containerOpenTop: '',
containerActive: 'ring-1 ring-primary-400 border-primary-400',
@@ -451,17 +451,17 @@ export default {
multipleLabel:
'flex items-center h-full absolute left-0 top-0 pointer-events-none bg-transparent leading-snug pl-3.5',
search:
'w-full absolute inset-0 outline-none appearance-none box-border border-0 text-sm font-sans bg-white rounded-md pl-3.5',
'w-full absolute inset-0 outline-hidden appearance-none box-border border-0 text-sm font-sans bg-white rounded-md pl-3.5',
tags: 'grow shrink flex flex-wrap mt-1 pl-2',
tag: 'bg-primary-500 text-white text-sm font-semibold py-0.5 pl-2 rounded mr-1 mb-1 flex items-center whitespace-nowrap',
tagDisabled: 'pr-2 !bg-gray-400 text-white',
tagRemove:
'flex items-center justify-center p-1 mx-0.5 rounded-sm hover:bg-black hover:bg-opacity-10 group',
'flex items-center justify-center p-1 mx-0.5 rounded-xs hover:bg-black/10 group',
tagRemoveIcon:
'bg-multiselect-remove text-white bg-center bg-no-repeat opacity-30 inline-block w-3 h-3 group-hover:opacity-60',
tagsSearchWrapper: 'inline-block relative mx-1 mb-1 grow shrink h-full',
tagsSearch:
'absolute inset-0 border-0 focus:outline-none !shadow-none !focus:shadow-none appearance-none p-0 text-sm font-sans box-border w-full',
'absolute inset-0 border-0 focus:outline-hidden !shadow-none !focus:shadow-none appearance-none p-0 text-sm font-sans box-border w-full',
tagsSearchCopy: 'invisible whitespace-pre-wrap inline-block h-px',
placeholder:
'flex items-center h-full absolute left-0 top-0 pointer-events-none bg-transparent leading-snug pl-3.5 text-gray-400 text-sm',
@@ -491,7 +491,7 @@ export default {
groupLabelDisabled: 'bg-gray-100 text-gray-300 cursor-not-allowed',
groupLabelSelectedPointed: 'bg-primary-600 text-white opacity-90',
groupLabelSelectedDisabled:
'text-primary-100 bg-primary-600 bg-opacity-50 cursor-not-allowed',
'text-primary-100 bg-primary-600/50 cursor-not-allowed',
groupOptions: 'p-0 m-0',
option:
'flex items-center justify-start box-border text-left cursor-pointer text-sm leading-snug py-2 px-3',
@@ -500,11 +500,11 @@ export default {
optionDisabled: 'text-gray-300 cursor-not-allowed',
optionSelectedPointed: 'text-white bg-primary-500 opacity-90',
optionSelectedDisabled:
'text-primary-100 bg-primary-500 bg-opacity-50 cursor-not-allowed',
'text-primary-100 bg-primary-500/50 cursor-not-allowed',
noOptions: 'py-2 px-3 text-gray-600 bg-white',
noResults: 'py-2 px-3 text-gray-600 bg-white',
fakeInput:
'bg-transparent absolute left-0 right-0 -bottom-px w-full h-px border-0 p-0 appearance-none outline-none text-transparent',
'bg-transparent absolute left-0 right-0 -bottom-px w-full h-px border-0 p-0 appearance-none outline-hidden text-transparent',
spacer: 'h-9 py-px box-content',
}),
},

View File

@@ -8,7 +8,7 @@
font-medium
leading-5
text-gray-900
outline-none
outline-hidden
focus:ring-2 focus:ring-offset-2 focus:ring-primary-400
"
:to="to"

View File

@@ -9,7 +9,7 @@ const props = defineProps({
defaultClass: {
type: String,
default:
'inline-flex whitespace-nowrap items-center border font-medium focus:outline-none focus:ring-2 focus:ring-offset-2',
'inline-flex whitespace-nowrap items-center border font-medium focus:outline-hidden focus:ring-2 focus:ring-offset-2',
},
tag: {
type: String,
@@ -81,7 +81,7 @@ const placeHolderSize = computed(() => {
const variantClass = computed(() => {
return {
'border-transparent shadow-sm text-white bg-primary-600 hover:bg-primary-700 focus:ring-primary-500':
'border-transparent shadow-xs text-white bg-primary-600 hover:bg-primary-700 focus:ring-primary-500':
props.variant === 'primary',
'border-transparent text-primary-700 bg-primary-100 hover:bg-primary-200 focus:ring-primary-500':
props.variant === 'secondary',
@@ -89,9 +89,9 @@ const variantClass = computed(() => {
props.variant == 'primary-outline',
'border-gray-200 text-gray-700 bg-white hover:bg-gray-50 focus:ring-primary-500 focus:ring-offset-0':
props.variant == 'white',
'border-transparent shadow-sm text-white bg-red-600 hover:bg-red-700 focus:ring-red-500':
'border-transparent shadow-xs text-white bg-red-600 hover:bg-red-700 focus:ring-red-500':
props.variant === 'danger',
'border-transparent bg-gray-200 border hover:bg-opacity-60 focus:ring-gray-500 focus:ring-offset-0':
'border-transparent bg-gray-200 border hover:bg-gray-200/60 focus:ring-gray-500 focus:ring-offset-0':
props.variant === 'gray',
}
})

View File

@@ -32,43 +32,38 @@ const classObject = computed(() => {
})
</script>
<style lang="scss">
@use 'sass:color';
$base-content-placeholders-primary-color: #ccc !default;
$base-content-placeholders-secondary-color: #eee !default;
$base-content-placeholders-border-radius: 6px !default;
$base-content-placeholders-line-height: 15px !default;
$base-content-placeholders-spacing: 10px !default;
// Animations
<style>
@keyframes vueContentPlaceholdersAnimation {
0% {
transform: translate3d(-30%, 0, 0);
}
100% {
transform: translate3d(100%, 0, 0);
}
}
// Mixins
@mixin base-content-placeholders {
.base-content-placeholders-heading {
display: flex;
[class^='base-content-placeholders-'] + & {
margin-top: 20px;
}
}
.base-content-placeholders-heading__img {
margin-right: 15px;
position: relative;
overflow: hidden;
min-height: $base-content-placeholders-line-height;
background: $base-content-placeholders-secondary-color;
min-height: 15px;
background: #eee;
.base-content-placeholders-is-rounded & {
border-radius: $base-content-placeholders-border-radius;
border-radius: 6px;
}
.base-content-placeholders-is-centered & {
margin-left: auto;
margin-right: auto;
}
.base-content-placeholders-is-animated &::before {
content: '';
position: absolute;
@@ -77,88 +72,125 @@ $base-content-placeholders-spacing: 10px !default;
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(
to right,
transparent 0%,
color.adjust($base-content-placeholders-secondary-color, $lightness: -5%) 15%,
transparent 30%
);
animation-duration: 1.5s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: vueContentPlaceholdersAnimation;
animation-timing-function: linear;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}
@mixin base-content-placeholders-spacing {
[class^='base-content-placeholders-'] + & {
margin-top: 2 * $base-content-placeholders-spacing;
}
}
// Styles
.base-content-placeholders-heading {
.base-content-placeholders-heading__content {
display: flex;
@include base-content-placeholders-spacing;
flex: 1;
flex-direction: column;
justify-content: center;
}
&__img {
margin-right: 1.5 * $base-content-placeholders-spacing;
@include base-content-placeholders;
.base-content-placeholders-heading__title {
width: 85%;
margin-bottom: 10px;
background: #ccc;
position: relative;
overflow: hidden;
min-height: 15px;
.base-content-placeholders-is-rounded & {
border-radius: 6px;
}
&__content {
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
.base-content-placeholders-is-centered & {
margin-left: auto;
margin-right: auto;
}
&__title {
width: 85%;
margin-bottom: $base-content-placeholders-spacing;
background: $base-content-placeholders-primary-color;
@include base-content-placeholders;
.base-content-placeholders-is-animated &::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}
&__subtitle {
width: 90%;
@include base-content-placeholders;
.base-content-placeholders-heading__subtitle {
width: 90%;
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
.base-content-placeholders-is-rounded & {
border-radius: 6px;
}
.base-content-placeholders-is-centered & {
margin-left: auto;
margin-right: auto;
}
.base-content-placeholders-is-animated &::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
}
.base-content-placeholders-text {
@include base-content-placeholders-spacing;
[class^='base-content-placeholders-'] + & {
margin-top: 20px;
}
}
&__line {
.base-content-placeholders-text__line {
width: 100%;
margin-bottom: 10px;
position: relative;
overflow: hidden;
min-height: 15px;
background: #eee;
.base-content-placeholders-is-rounded & {
border-radius: 6px;
}
.base-content-placeholders-is-centered & {
margin-left: auto;
margin-right: auto;
}
.base-content-placeholders-is-animated &::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
&:first-child {
width: 100%;
margin-bottom: $base-content-placeholders-spacing;
@include base-content-placeholders;
&:first-child {
width: 100%;
}
&:nth-child(2) {
width: 90%;
}
&:nth-child(3) {
width: 80%;
}
&:nth-child(4) {
width: 70%;
}
}
&:nth-child(2) {
width: 90%;
}
&:nth-child(3) {
width: 80%;
}
&:nth-child(4) {
width: 70%;
}
}
.base-content-placeholders-box {
position: relative;
overflow: hidden;
min-height: $base-content-placeholders-line-height;
background: $base-content-placeholders-secondary-color;
min-height: 15px;
background: #eee;
.base-content-placeholders-is-animated &::before {
content: '';
@@ -168,20 +200,9 @@ $base-content-placeholders-spacing: 10px !default;
width: 100vw;
max-width: 1000px;
height: 100%;
background: linear-gradient(
to right,
transparent 0%,
color.adjust($base-content-placeholders-secondary-color, $lightness: -5%) 15%,
transparent 30%
);
animation-duration: 1.5s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: vueContentPlaceholdersAnimation;
animation-timing-function: linear;
background: linear-gradient(to right, transparent 0%, #e1e1e1 15%, transparent 30%);
animation: vueContentPlaceholdersAnimation 1.5s linear infinite forwards;
}
// @include base-content-placeholders-spacing;
}
.base-content-circle {
@@ -189,6 +210,6 @@ $base-content-placeholders-spacing: 10px !default;
}
.base-content-placeholders-is-rounded {
border-radius: $base-content-placeholders-border-radius;
border-radius: 6px;
}
</style>

View File

@@ -172,12 +172,12 @@
<Popover v-else v-slot="{ open }" class="relative flex flex-col rounded-md">
<PopoverButton
:class="{
'text-opacity-90': open,
'': open,
'border border-solid border-red-500 focus:ring-red-500 rounded':
valid.$error,
'focus:ring-2 focus:ring-primary-400': !valid.$error,
}"
class="w-full outline-none rounded-md"
class="w-full outline-hidden rounded-md"
>
<div
class="
@@ -243,7 +243,7 @@
overflow-hidden
rounded-md
shadow-lg
ring-1 ring-black ring-opacity-5
ring-1 ring-black/5
bg-white
"
>
@@ -277,7 +277,7 @@
border-b border-gray-200 border-solid
cursor-pointer
hover:cursor-pointer hover:bg-gray-100
focus:outline-none focus:bg-gray-100
focus:outline-hidden focus:bg-gray-100
last:border-b-0
"
@click="selectNewCustomer(customer.id, close)"
@@ -352,7 +352,7 @@
py-3
bg-gray-200
border-none
outline-none
outline-hidden
focus:bg-gray-300
"
@click="openCustomerModal"

View File

@@ -121,7 +121,7 @@ const props = defineProps({
defaultInputClass: {
type: String,
default:
'font-base pl-8 py-2 outline-none focus:ring-primary-400 focus:outline-none focus:border-primary-400 block w-full sm:text-sm border-gray-200 rounded-md text-black',
'font-base pl-8 py-2 outline-hidden focus:ring-primary-400 focus:outline-hidden focus:border-primary-400 block w-full sm:text-sm border-gray-200 rounded-md text-black',
},
time24hr: {
type: Boolean,
@@ -282,7 +282,7 @@ const inputInvalidClass = computed(() => {
const inputDisabledClass = computed(() => {
if (props.disabled) {
return 'border border-solid rounded-md outline-none input-field box-border-2 base-date-picker-input placeholder-gray-400 bg-gray-200 text-gray-600 border-gray-200'
return 'border border-solid rounded-md outline-hidden input-field box-border-2 base-date-picker-input placeholder-gray-400 bg-gray-200 text-gray-600 border-gray-200'
}
return ''

View File

@@ -30,7 +30,7 @@
leave-to="opacity-0"
>
<DialogOverlay
class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75"
class="fixed inset-0 transition-opacity bg-gray-500/75"
/>
</TransitionChild>

View File

@@ -11,7 +11,7 @@
/>
</BaseContentPlaceholders>
<Menu v-else>
<MenuButton ref="trigger" class="focus:outline-none" @click="onClick">
<MenuButton ref="trigger" class="focus:outline-hidden" @click="onClick">
<slot name="activator" />
</MenuButton>
@@ -69,7 +69,7 @@ const props = defineProps({
})
const containerClasses = computed(() => {
const baseClass = `origin-top-right rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 divide-y divide-gray-100 focus:outline-none`
const baseClass = `origin-top-right rounded-md shadow-lg bg-white ring-1 ring-black/5 divide-y divide-gray-100 focus:outline-hidden`
return `${baseClass} ${props.containerClass}`
})

View File

@@ -18,19 +18,19 @@ const props = defineProps({
const badgeColorClasses = computed(() => {
switch (props.status) {
case 'DRAFT':
return 'bg-yellow-300 bg-opacity-25 px-2 py-1 text-sm text-yellow-800 uppercase font-normal text-center '
return 'bg-yellow-300/25 px-2 py-1 text-sm text-yellow-800 uppercase font-normal text-center '
case 'SENT':
return ' bg-yellow-500 bg-opacity-25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center '
return ' bg-yellow-500/25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center '
case 'VIEWED':
return 'bg-blue-400 bg-opacity-25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
return 'bg-blue-400/25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
case 'EXPIRED':
return 'bg-red-300 bg-opacity-25 px-2 py-1 text-sm text-red-800 uppercase font-normal text-center'
return 'bg-red-300/25 px-2 py-1 text-sm text-red-800 uppercase font-normal text-center'
case 'ACCEPTED':
return 'bg-green-400 bg-opacity-25 px-2 py-1 text-sm text-green-800 uppercase font-normal text-center'
return 'bg-green-400/25 px-2 py-1 text-sm text-green-800 uppercase font-normal text-center'
case 'REJECTED':
return 'bg-purple-300 bg-opacity-25 px-2 py-1 text-sm text-purple-800 uppercase font-normal text-center'
return 'bg-purple-300/25 px-2 py-1 text-sm text-purple-800 uppercase font-normal text-center'
default:
return 'bg-gray-500 bg-opacity-25 px-2 py-1 text-sm text-gray-900 uppercase font-normal text-center'
return 'bg-gray-500/25 px-2 py-1 text-sm text-gray-900 uppercase font-normal text-center'
}
})
</script>

View File

@@ -11,7 +11,7 @@
rounded-md
cursor-pointer
avatar-upload
border-gray-200
border-gray-300
transition-all
duration-300
ease-in-out
@@ -379,7 +379,7 @@
<script setup>
import { ref, onMounted, watch } from 'vue'
import axios from 'axios'
import http from '@/scripts/http'
import utils from '@/scripts/helpers/utilities'
const props = defineProps({
@@ -456,7 +456,7 @@ function reset() {
function upload(formData) {
return (
axios
http
.post(props.uploadUrl, formData)
// get data
.then((x) => x.data)

View File

@@ -42,7 +42,7 @@
font-medium
text-yellow-800
hover:bg-yellow-100
focus:outline-none
focus:outline-hidden
focus:ring-2
focus:ring-offset-2
focus:ring-offset-yellow-50
@@ -66,7 +66,7 @@
font-medium
text-yellow-800
hover:bg-yellow-100
focus:outline-none
focus:outline-hidden
focus:ring-2
focus:ring-offset-2
focus:ring-offset-yellow-50

View File

@@ -10,7 +10,7 @@
<div
v-else
:class="[containerClass, computedContainerClass]"
class="relative rounded-md shadow-sm font-base"
class="relative rounded-md shadow-xs font-base"
>
<div
v-if="loading && loadingPosition === 'left'"

View File

@@ -20,25 +20,25 @@ export default {
const badgeColorClasses = computed(() => {
switch (props.status) {
case 'DRAFT':
return 'bg-yellow-300 bg-opacity-25 px-2 py-1 text-sm text-yellow-800 uppercase font-normal text-center'
return 'bg-yellow-300/25 px-2 py-1 text-sm text-yellow-800 uppercase font-normal text-center'
case 'SENT':
return ' bg-yellow-500 bg-opacity-25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center '
return ' bg-yellow-500/25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center '
case 'VIEWED':
return 'bg-blue-400 bg-opacity-25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
return 'bg-blue-400/25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
case 'COMPLETED':
return 'bg-green-500 bg-opacity-25 px-2 py-1 text-sm text-green-900 uppercase font-normal text-center'
return 'bg-green-500/25 px-2 py-1 text-sm text-green-900 uppercase font-normal text-center'
case 'DUE':
return 'bg-yellow-500 bg-opacity-25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center'
return 'bg-yellow-500/25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center'
case 'OVERDUE':
return 'bg-red-300 bg-opacity-50 px-2 py-1 text-sm text-red-900 uppercase font-normal text-center'
return 'bg-red-300/50 px-2 py-1 text-sm text-red-900 uppercase font-normal text-center'
case 'UNPAID':
return 'bg-yellow-500 bg-opacity-25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center'
return 'bg-yellow-500/25 px-2 py-1 text-sm text-yellow-900 uppercase font-normal text-center'
case 'PARTIALLY_PAID':
return 'bg-blue-400 bg-opacity-25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
return 'bg-blue-400/25 px-2 py-1 text-sm text-blue-900 uppercase font-normal text-center'
case 'PAID':
return 'bg-green-500 bg-opacity-25 px-2 py-1 text-sm text-green-900 uppercase font-normal text-center'
return 'bg-green-500/25 px-2 py-1 text-sm text-green-900 uppercase font-normal text-center'
default:
return 'bg-gray-500 bg-opacity-25 px-2 py-1 text-sm text-gray-900 uppercase font-normal text-center'
return 'bg-gray-500/25 px-2 py-1 text-sm text-gray-900 uppercase font-normal text-center'
}
})
return { badgeColorClasses }

Some files were not shown because too many files have changed in this diff Show More