mirror of
https://github.com/crater-invoice/crater.git
synced 2025-10-27 11:41:09 -04:00
Compare commits
74 Commits
report-pdf
...
dark-custo
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a1d124633 | |||
| e9abb197b7 | |||
| 6402771cb8 | |||
| 3bb53d2a24 | |||
| feda20431c | |||
| 238cdb3c25 | |||
| 55bf70c868 | |||
| 0c5adff9b4 | |||
| 3d5732ee26 | |||
| 5aa7decdbe | |||
| 5c67780870 | |||
| ba7f619c67 | |||
| 82efad71c0 | |||
| 826ef72faa | |||
| 2adaa7a84a | |||
| 13557ea075 | |||
| ce88c772d1 | |||
| a32d36363d | |||
| f874b3507d | |||
| c36d25931f | |||
| 1e6c3b287f | |||
| 0462ff60a0 | |||
| 29a135adaf | |||
| 1aceb2c672 | |||
| fb9fab641d | |||
| 8f2edc220b | |||
| d14ab013ad | |||
| f6639f5863 | |||
| c5acf1343e | |||
| 0321ca5515 | |||
| bd345949e5 | |||
| b4b00ebdd6 | |||
| 43316dae28 | |||
| 80e2548b38 | |||
| e8d92cd641 | |||
| 2c8bb38531 | |||
| 04c7ae39a2 | |||
| af2482a69c | |||
| cac35826c2 | |||
| 18b5705372 | |||
| c61fbad5ce | |||
| 15f3f566e3 | |||
| 2e93082282 | |||
| ca55221c4f | |||
| 98196194e2 | |||
| 7447cc24f9 | |||
| 889d22d92c | |||
| bc8f2cd484 | |||
| 4e47f58bad | |||
| d8c429912e | |||
| df04fd9e53 | |||
| 0aaf0e7e75 | |||
| 3d0b89bb4d | |||
| 189c51cdf4 | |||
| bd5f0fe5cf | |||
| 787619b907 | |||
| fd70ab9a99 | |||
| 33315638df | |||
| bba14bf51a | |||
| ea41989034 | |||
| 3f3f83a00a | |||
| adc5962071 | |||
| c4c00002d7 | |||
| a7c1e12db6 | |||
| 32949d1eec | |||
| 7718f77f3d | |||
| a9e54981bf | |||
| ef35293f8a | |||
| 5c63770b6b | |||
| d130e20c92 | |||
| 586fb1ae10 | |||
| 20c2502e31 | |||
| 0e31f85c18 | |||
| e7301eb7a3 |
162
.github/workflows/uffizzi-build.yml
vendored
Normal file
162
.github/workflows/uffizzi-build.yml
vendored
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
name: Build PR Image
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened,synchronize,reopened,closed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build-application:
|
||||||
|
name: Build and Push `application`
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
|
||||||
|
outputs:
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout git repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Generate UUID image name
|
||||||
|
id: uuid
|
||||||
|
run: echo "UUID_TAG_APP=$(uuidgen)" >> $GITHUB_ENV
|
||||||
|
- name: Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v3
|
||||||
|
with:
|
||||||
|
images: registry.uffizzi.com/${{ env.UUID_TAG_APP }}
|
||||||
|
tags: type=raw,value=60d
|
||||||
|
- name: Build and Push Image to registry.uffizzi.com ephemeral registry
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
file: ./uffizzi/Dockerfile
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
|
||||||
|
build-nginx:
|
||||||
|
name: Build and Push `nginx`
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
|
||||||
|
outputs:
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout git repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Generate UUID image name
|
||||||
|
id: uuid
|
||||||
|
run: echo "UUID_TAG_NGINX=$(uuidgen)" >> $GITHUB_ENV
|
||||||
|
- name: Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v3
|
||||||
|
with:
|
||||||
|
images: registry.uffizzi.com/${{ env.UUID_TAG_NGINX }}
|
||||||
|
tags: type=raw,value=60d
|
||||||
|
- name: Build and Push Image to Uffizzi ephemeral registry
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
file: ./uffizzi/nginx/Dockerfile
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
|
||||||
|
build-crond:
|
||||||
|
name: Build and Push `crond`
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
|
||||||
|
outputs:
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout git repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Generate UUID image name
|
||||||
|
id: uuid
|
||||||
|
run: echo "UUID_TAG_CROND=$(uuidgen)" >> $GITHUB_ENV
|
||||||
|
- name: Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v3
|
||||||
|
with:
|
||||||
|
images: registry.uffizzi.com/${{ env.UUID_TAG_CROND }}
|
||||||
|
tags: type=raw,value=60d
|
||||||
|
- name: Build and Push Image to registry.uffizzi.com ephemeral registry
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
context: ./
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
file: ./uffizzi/crond/Dockerfile
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
render-compose-file:
|
||||||
|
name: Render Docker Compose File
|
||||||
|
# Pass output of this workflow to another triggered by `workflow_run` event.
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
compose-file-cache-key: ${{ steps.hash.outputs.hash }}
|
||||||
|
needs:
|
||||||
|
- build-application
|
||||||
|
- build-nginx
|
||||||
|
- build-crond
|
||||||
|
steps:
|
||||||
|
- name: Checkout git repo
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Render Compose File
|
||||||
|
run: |
|
||||||
|
APP_IMAGE=$(echo ${{ needs.build-application.outputs.tags }})
|
||||||
|
export APP_IMAGE
|
||||||
|
NGINX_IMAGE=$(echo ${{ needs.build-nginx.outputs.tags }})
|
||||||
|
export NGINX_IMAGE
|
||||||
|
CROND_IMAGE=$(echo ${{ needs.build-crond.outputs.tags }})
|
||||||
|
export CROND_IMAGE
|
||||||
|
# Render simple template from environment variables.
|
||||||
|
envsubst < ./uffizzi/docker-compose.uffizzi.yml > docker-compose.rendered.yml
|
||||||
|
cat docker-compose.rendered.yml
|
||||||
|
- name: Upload Rendered Compose File as Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: preview-spec
|
||||||
|
path: docker-compose.rendered.yml
|
||||||
|
retention-days: 2
|
||||||
|
- name: Serialize PR Event to File
|
||||||
|
run: |
|
||||||
|
cat << EOF > event.json
|
||||||
|
${{ toJSON(github.event) }}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
- name: Upload PR Event as Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: preview-spec
|
||||||
|
path: event.json
|
||||||
|
retention-days: 2
|
||||||
|
|
||||||
|
delete-preview:
|
||||||
|
name: Call for Preview Deletion
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event.action == 'closed' }}
|
||||||
|
steps:
|
||||||
|
# If this PR is closing, we will not render a compose file nor pass it to the next workflow.
|
||||||
|
- name: Serialize PR Event to File
|
||||||
|
run: echo '${{ toJSON(github.event) }}' > event.json
|
||||||
|
- name: Upload PR Event as Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: preview-spec
|
||||||
|
path: event.json
|
||||||
|
retention-days: 2
|
||||||
|
|
||||||
84
.github/workflows/uffizzi-preview.yml
vendored
Normal file
84
.github/workflows/uffizzi-preview.yml
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
name: Deploy Uffizzi Preview
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows:
|
||||||
|
- "Build PR Image"
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
cache-compose-file:
|
||||||
|
name: Cache Compose File
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
compose-file-cache-key: ${{ env.COMPOSE_FILE_HASH }}
|
||||||
|
pr-number: ${{ env.PR_NUMBER }}
|
||||||
|
steps:
|
||||||
|
- name: 'Download artifacts'
|
||||||
|
# Fetch output (zip archive) from the workflow run that triggered this workflow.
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
run_id: context.payload.workflow_run.id,
|
||||||
|
});
|
||||||
|
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
|
||||||
|
return artifact.name == "preview-spec"
|
||||||
|
})[0];
|
||||||
|
let download = await github.rest.actions.downloadArtifact({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
artifact_id: matchArtifact.id,
|
||||||
|
archive_format: 'zip',
|
||||||
|
});
|
||||||
|
let fs = require('fs');
|
||||||
|
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/preview-spec.zip`, Buffer.from(download.data));
|
||||||
|
- name: 'Unzip artifact'
|
||||||
|
run: unzip preview-spec.zip
|
||||||
|
- name: Read Event into ENV
|
||||||
|
run: |
|
||||||
|
echo 'EVENT_JSON<<EOF' >> $GITHUB_ENV
|
||||||
|
cat event.json >> $GITHUB_ENV
|
||||||
|
echo 'EOF' >> $GITHUB_ENV
|
||||||
|
- name: Hash Rendered Compose File
|
||||||
|
id: hash
|
||||||
|
# If the previous workflow was triggered by a PR close event, we will not have a compose file artifact.
|
||||||
|
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
|
||||||
|
run: echo "COMPOSE_FILE_HASH=$(md5sum docker-compose.rendered.yml | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||||
|
- name: Cache Rendered Compose File
|
||||||
|
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: docker-compose.rendered.yml
|
||||||
|
key: ${{ env.COMPOSE_FILE_HASH }}
|
||||||
|
|
||||||
|
- name: Read PR Number From Event Object
|
||||||
|
id: pr
|
||||||
|
run: echo "PR_NUMBER=${{ fromJSON(env.EVENT_JSON).number }}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: DEBUG - Print Job Outputs
|
||||||
|
if: ${{ runner.debug }}
|
||||||
|
run: |
|
||||||
|
echo "PR number: ${{ env.PR_NUMBER }}"
|
||||||
|
echo "Compose file hash: ${{ env.COMPOSE_FILE_HASH }}"
|
||||||
|
cat event.json
|
||||||
|
deploy-uffizzi-preview:
|
||||||
|
name: Use Remote Workflow to Preview on Uffizzi
|
||||||
|
needs:
|
||||||
|
- cache-compose-file
|
||||||
|
uses: UffizziCloud/preview-action/.github/workflows/reusable.yaml@v2.6.1
|
||||||
|
with:
|
||||||
|
# If this workflow was triggered by a PR close event, cache-key will be an empty string
|
||||||
|
# and this reusable workflow will delete the preview deployment.
|
||||||
|
compose-file-cache-key: ${{ needs.cache-compose-file.outputs.compose-file-cache-key }}
|
||||||
|
compose-file-cache-path: docker-compose.rendered.yml
|
||||||
|
server: https://app.uffizzi.com/
|
||||||
|
pr-number: ${{ needs.cache-compose-file.outputs.pr-number }}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
id-token: write
|
||||||
@ -1,4 +1,4 @@
|
|||||||
FROM php:7.4-fpm
|
FROM php:8.1-fpm
|
||||||
|
|
||||||
# Arguments defined in docker-compose.yml
|
# Arguments defined in docker-compose.yml
|
||||||
ARG user
|
ARG user
|
||||||
|
|||||||
@ -103,6 +103,7 @@ class CustomerStatsController extends Controller
|
|||||||
)
|
)
|
||||||
->whereCompany()
|
->whereCompany()
|
||||||
->whereCustomer($customer->id)
|
->whereCustomer($customer->id)
|
||||||
|
->where('status', '<>', Invoice::STATUS_DRAFT)
|
||||||
->sum('total');
|
->sum('total');
|
||||||
$totalReceipts = Payment::whereBetween(
|
$totalReceipts = Payment::whereBetween(
|
||||||
'payment_date',
|
'payment_date',
|
||||||
|
|||||||
@ -104,6 +104,7 @@ class DashboardController extends Controller
|
|||||||
'invoice_date',
|
'invoice_date',
|
||||||
[$startDate->format('Y-m-d'), $start->format('Y-m-d')]
|
[$startDate->format('Y-m-d'), $start->format('Y-m-d')]
|
||||||
)
|
)
|
||||||
|
->where('status', '<>', Invoice::STATUS_DRAFT)
|
||||||
->whereCompany()
|
->whereCompany()
|
||||||
->sum('base_total');
|
->sum('base_total');
|
||||||
|
|
||||||
@ -141,6 +142,7 @@ class DashboardController extends Controller
|
|||||||
$recent_due_invoices = Invoice::with('customer')
|
$recent_due_invoices = Invoice::with('customer')
|
||||||
->whereCompany()
|
->whereCompany()
|
||||||
->where('base_due_amount', '>', 0)
|
->where('base_due_amount', '>', 0)
|
||||||
|
->where('status', '<>', Invoice::STATUS_DRAFT)
|
||||||
->take(5)
|
->take(5)
|
||||||
->latest()
|
->latest()
|
||||||
->get();
|
->get();
|
||||||
|
|||||||
@ -24,6 +24,7 @@ class InvoicesController extends Controller
|
|||||||
$limit = $request->has('limit') ? $request->limit : 10;
|
$limit = $request->has('limit') ? $request->limit : 10;
|
||||||
|
|
||||||
$invoices = Invoice::whereCompany()
|
$invoices = Invoice::whereCompany()
|
||||||
|
->whereTabFilters($request->tab_status)
|
||||||
->join('customers', 'customers.id', '=', 'invoices.customer_id')
|
->join('customers', 'customers.id', '=', 'invoices.customer_id')
|
||||||
->applyFilters($request->all())
|
->applyFilters($request->all())
|
||||||
->select('invoices.*', 'customers.name')
|
->select('invoices.*', 'customers.name')
|
||||||
|
|||||||
@ -2,24 +2,25 @@
|
|||||||
|
|
||||||
namespace Crater\Http\Controllers\V1\Admin\Report;
|
namespace Crater\Http\Controllers\V1\Admin\Report;
|
||||||
|
|
||||||
|
use PDF;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Crater\Http\Controllers\Controller;
|
|
||||||
use Crater\Models\Company;
|
use Crater\Models\Company;
|
||||||
use Crater\Models\CompanySetting;
|
use Crater\Models\Currency;
|
||||||
use Crater\Models\Customer;
|
use Crater\Models\Customer;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Crater\Models\CompanySetting;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
use PDF;
|
use Crater\Http\Controllers\Controller;
|
||||||
|
|
||||||
class CustomerSalesReportController extends Controller
|
class CustomerSalesReportController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle the incoming request.
|
* Handle the incoming request.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string $hash
|
* @param string $hash
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function __invoke(Request $request, $hash)
|
public function __invoke(Request $request, $hash)
|
||||||
{
|
{
|
||||||
$company = Company::where('unique_hash', $hash)->first();
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
@ -56,6 +57,7 @@ class CustomerSalesReportController extends Controller
|
|||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
||||||
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
'primary_text_color',
|
'primary_text_color',
|
||||||
@ -80,6 +82,7 @@ class CustomerSalesReportController extends Controller
|
|||||||
'company' => $company,
|
'company' => $company,
|
||||||
'from_date' => $from_date,
|
'from_date' => $from_date,
|
||||||
'to_date' => $to_date,
|
'to_date' => $to_date,
|
||||||
|
'currency' => $currency,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$pdf = PDF::loadView('app.pdf.reports.sales-customers');
|
$pdf = PDF::loadView('app.pdf.reports.sales-customers');
|
||||||
|
|||||||
@ -2,24 +2,25 @@
|
|||||||
|
|
||||||
namespace Crater\Http\Controllers\V1\Admin\Report;
|
namespace Crater\Http\Controllers\V1\Admin\Report;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Crater\Http\Controllers\Controller;
|
|
||||||
use Crater\Models\Company;
|
|
||||||
use Crater\Models\CompanySetting;
|
|
||||||
use Crater\Models\Expense;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\App;
|
|
||||||
use PDF;
|
use PDF;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Crater\Models\Company;
|
||||||
|
use Crater\Models\Expense;
|
||||||
|
use Crater\Models\Currency;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Crater\Models\CompanySetting;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
use Crater\Http\Controllers\Controller;
|
||||||
|
|
||||||
class ExpensesReportController extends Controller
|
class ExpensesReportController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle the incoming request.
|
* Handle the incoming request.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string $hash
|
* @param string $hash
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function __invoke(Request $request, $hash)
|
public function __invoke(Request $request, $hash)
|
||||||
{
|
{
|
||||||
$company = Company::where('unique_hash', $hash)->first();
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
@ -43,6 +44,7 @@ class ExpensesReportController extends Controller
|
|||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
||||||
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
'primary_text_color',
|
'primary_text_color',
|
||||||
@ -66,6 +68,7 @@ class ExpensesReportController extends Controller
|
|||||||
'company' => $company,
|
'company' => $company,
|
||||||
'from_date' => $from_date,
|
'from_date' => $from_date,
|
||||||
'to_date' => $to_date,
|
'to_date' => $to_date,
|
||||||
|
'currency' => $currency,
|
||||||
]);
|
]);
|
||||||
$pdf = PDF::loadView('app.pdf.reports.expenses');
|
$pdf = PDF::loadView('app.pdf.reports.expenses');
|
||||||
|
|
||||||
|
|||||||
@ -2,24 +2,25 @@
|
|||||||
|
|
||||||
namespace Crater\Http\Controllers\V1\Admin\Report;
|
namespace Crater\Http\Controllers\V1\Admin\Report;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Crater\Http\Controllers\Controller;
|
|
||||||
use Crater\Models\Company;
|
|
||||||
use Crater\Models\CompanySetting;
|
|
||||||
use Crater\Models\InvoiceItem;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\App;
|
|
||||||
use PDF;
|
use PDF;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Crater\Models\Company;
|
||||||
|
use Crater\Models\Currency;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Crater\Models\InvoiceItem;
|
||||||
|
use Crater\Models\CompanySetting;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
use Crater\Http\Controllers\Controller;
|
||||||
|
|
||||||
class ItemSalesReportController extends Controller
|
class ItemSalesReportController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle the incoming request.
|
* Handle the incoming request.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string $hash
|
* @param string $hash
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function __invoke(Request $request, $hash)
|
public function __invoke(Request $request, $hash)
|
||||||
{
|
{
|
||||||
$company = Company::where('unique_hash', $hash)->first();
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
@ -43,6 +44,7 @@ class ItemSalesReportController extends Controller
|
|||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
||||||
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
'primary_text_color',
|
'primary_text_color',
|
||||||
@ -66,6 +68,7 @@ class ItemSalesReportController extends Controller
|
|||||||
'company' => $company,
|
'company' => $company,
|
||||||
'from_date' => $from_date,
|
'from_date' => $from_date,
|
||||||
'to_date' => $to_date,
|
'to_date' => $to_date,
|
||||||
|
'currency' => $currency,
|
||||||
]);
|
]);
|
||||||
$pdf = PDF::loadView('app.pdf.reports.sales-items');
|
$pdf = PDF::loadView('app.pdf.reports.sales-items');
|
||||||
|
|
||||||
|
|||||||
@ -2,25 +2,26 @@
|
|||||||
|
|
||||||
namespace Crater\Http\Controllers\V1\Admin\Report;
|
namespace Crater\Http\Controllers\V1\Admin\Report;
|
||||||
|
|
||||||
|
use PDF;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Crater\Http\Controllers\Controller;
|
|
||||||
use Crater\Models\Company;
|
use Crater\Models\Company;
|
||||||
use Crater\Models\CompanySetting;
|
|
||||||
use Crater\Models\Expense;
|
use Crater\Models\Expense;
|
||||||
use Crater\Models\Payment;
|
use Crater\Models\Payment;
|
||||||
|
use Crater\Models\Currency;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Crater\Models\CompanySetting;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
use PDF;
|
use Crater\Http\Controllers\Controller;
|
||||||
|
|
||||||
class ProfitLossReportController extends Controller
|
class ProfitLossReportController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle the incoming request.
|
* Handle the incoming request.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string $hash
|
* @param string $hash
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function __invoke(Request $request, $hash)
|
public function __invoke(Request $request, $hash)
|
||||||
{
|
{
|
||||||
$company = Company::where('unique_hash', $hash)->first();
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
@ -49,6 +50,8 @@ class ProfitLossReportController extends Controller
|
|||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
||||||
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
'primary_text_color',
|
'primary_text_color',
|
||||||
@ -74,6 +77,7 @@ class ProfitLossReportController extends Controller
|
|||||||
'company' => $company,
|
'company' => $company,
|
||||||
'from_date' => $from_date,
|
'from_date' => $from_date,
|
||||||
'to_date' => $to_date,
|
'to_date' => $to_date,
|
||||||
|
'currency' => $currency,
|
||||||
]);
|
]);
|
||||||
$pdf = PDF::loadView('app.pdf.reports.profit-loss');
|
$pdf = PDF::loadView('app.pdf.reports.profit-loss');
|
||||||
|
|
||||||
|
|||||||
@ -2,24 +2,25 @@
|
|||||||
|
|
||||||
namespace Crater\Http\Controllers\V1\Admin\Report;
|
namespace Crater\Http\Controllers\V1\Admin\Report;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Crater\Http\Controllers\Controller;
|
|
||||||
use Crater\Models\Company;
|
|
||||||
use Crater\Models\CompanySetting;
|
|
||||||
use Crater\Models\Tax;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\App;
|
|
||||||
use PDF;
|
use PDF;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Crater\Models\Tax;
|
||||||
|
use Crater\Models\Company;
|
||||||
|
use Crater\Models\Currency;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Crater\Models\CompanySetting;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
use Crater\Http\Controllers\Controller;
|
||||||
|
|
||||||
class TaxSummaryReportController extends Controller
|
class TaxSummaryReportController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle the incoming request.
|
* Handle the incoming request.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param string $hash
|
* @param string $hash
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function __invoke(Request $request, $hash)
|
public function __invoke(Request $request, $hash)
|
||||||
{
|
{
|
||||||
$company = Company::where('unique_hash', $hash)->first();
|
$company = Company::where('unique_hash', $hash)->first();
|
||||||
@ -44,6 +45,8 @@ class TaxSummaryReportController extends Controller
|
|||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
||||||
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
'primary_text_color',
|
'primary_text_color',
|
||||||
@ -68,6 +71,7 @@ class TaxSummaryReportController extends Controller
|
|||||||
'company' => $company,
|
'company' => $company,
|
||||||
'from_date' => $from_date,
|
'from_date' => $from_date,
|
||||||
'to_date' => $to_date,
|
'to_date' => $to_date,
|
||||||
|
'currency' => $currency,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$pdf = PDF::loadView('app.pdf.reports.tax-summary');
|
$pdf = PDF::loadView('app.pdf.reports.tax-summary');
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
namespace Crater\Http\Requests;
|
namespace Crater\Http\Requests;
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
class CompaniesRequest extends FormRequest
|
class CompaniesRequest extends FormRequest
|
||||||
@ -34,6 +33,10 @@ class CompaniesRequest extends FormRequest
|
|||||||
'currency' => [
|
'currency' => [
|
||||||
'required'
|
'required'
|
||||||
],
|
],
|
||||||
|
'slug' => [
|
||||||
|
'required',
|
||||||
|
Rule::unique('companies')
|
||||||
|
],
|
||||||
'address.name' => [
|
'address.name' => [
|
||||||
'nullable',
|
'nullable',
|
||||||
],
|
],
|
||||||
@ -68,11 +71,11 @@ class CompaniesRequest extends FormRequest
|
|||||||
{
|
{
|
||||||
return collect($this->validated())
|
return collect($this->validated())
|
||||||
->only([
|
->only([
|
||||||
'name'
|
'name',
|
||||||
|
'slug'
|
||||||
])
|
])
|
||||||
->merge([
|
->merge([
|
||||||
'owner_id' => $this->user()->id,
|
'owner_id' => $this->user()->id
|
||||||
'slug' => Str::slug($this->name)
|
|
||||||
])
|
])
|
||||||
->toArray();
|
->toArray();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,8 @@ class CompanyRequest extends FormRequest
|
|||||||
Rule::unique('companies')->ignore($this->header('company'), 'id'),
|
Rule::unique('companies')->ignore($this->header('company'), 'id'),
|
||||||
],
|
],
|
||||||
'slug' => [
|
'slug' => [
|
||||||
'nullable'
|
'required',
|
||||||
|
Rule::unique('companies')->ignore($this->header('company'), 'id'),
|
||||||
],
|
],
|
||||||
'address.country_id' => [
|
'address.country_id' => [
|
||||||
'required',
|
'required',
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class EstimateResource extends JsonResource
|
|||||||
'reference_number' => $this->reference_number,
|
'reference_number' => $this->reference_number,
|
||||||
'tax_per_item' => $this->tax_per_item,
|
'tax_per_item' => $this->tax_per_item,
|
||||||
'discount_per_item' => $this->discount_per_item,
|
'discount_per_item' => $this->discount_per_item,
|
||||||
'notes' => $this->getNotes(),
|
'notes' => $this->notes,
|
||||||
'discount' => $this->discount,
|
'discount' => $this->discount,
|
||||||
'discount_type' => $this->discount_type,
|
'discount_type' => $this->discount_type,
|
||||||
'discount_val' => $this->discount_val,
|
'discount_val' => $this->discount_val,
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class PaymentResource extends JsonResource
|
|||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'payment_number' => $this->payment_number,
|
'payment_number' => $this->payment_number,
|
||||||
'payment_date' => $this->payment_date,
|
'payment_date' => $this->payment_date,
|
||||||
'notes' => $this->getNotes(),
|
'notes' => $this->notes,
|
||||||
'amount' => $this->amount,
|
'amount' => $this->amount,
|
||||||
'unique_hash' => $this->unique_hash,
|
'unique_hash' => $this->unique_hash,
|
||||||
'invoice_id' => $this->invoice_id,
|
'invoice_id' => $this->invoice_id,
|
||||||
|
|||||||
@ -217,7 +217,7 @@ class Company extends Model implements HasMedia
|
|||||||
'estimate_billing_address_format' => $billingAddressFormat,
|
'estimate_billing_address_format' => $billingAddressFormat,
|
||||||
'payment_company_address_format' => $companyAddressFormat,
|
'payment_company_address_format' => $companyAddressFormat,
|
||||||
'payment_from_customer_address_format' => $paymentFromCustomerAddress,
|
'payment_from_customer_address_format' => $paymentFromCustomerAddress,
|
||||||
'currency' => request()->currency ?? 13,
|
'currency' => request()->currency ?? 1,
|
||||||
'time_zone' => 'Asia/Kolkata',
|
'time_zone' => 'Asia/Kolkata',
|
||||||
'language' => 'en',
|
'language' => 'en',
|
||||||
'fiscal_year' => '1-12',
|
'fiscal_year' => '1-12',
|
||||||
|
|||||||
@ -483,7 +483,8 @@ class Estimate extends Model implements HasMedia
|
|||||||
'{ESTIMATE_DATE}' => $this->formattedEstimateDate,
|
'{ESTIMATE_DATE}' => $this->formattedEstimateDate,
|
||||||
'{ESTIMATE_EXPIRY_DATE}' => $this->formattedExpiryDate,
|
'{ESTIMATE_EXPIRY_DATE}' => $this->formattedExpiryDate,
|
||||||
'{ESTIMATE_NUMBER}' => $this->estimate_number,
|
'{ESTIMATE_NUMBER}' => $this->estimate_number,
|
||||||
'{ESTIMATE_REF_NUMBER}' => $this->reference_number,
|
'{PDF_LINK}' => $this->estimatePdfUrl,
|
||||||
|
'{TOTAL_AMOUNT}' => format_money_pdf($this->total, $this->customer->currency)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -240,7 +240,7 @@ class Expense extends Model implements HasMedia
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($request->hasFile('attachment_receipt')) {
|
if ($request->hasFile('attachment_receipt')) {
|
||||||
$expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts');
|
$expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->customFields) {
|
if ($request->customFields) {
|
||||||
@ -262,12 +262,12 @@ class Expense extends Model implements HasMedia
|
|||||||
ExchangeRateLog::addExchangeRateLog($this);
|
ExchangeRateLog::addExchangeRateLog($this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($request->is_attachment_receipt_removed) && (bool) $request->is_attachment_receipt_removed) {
|
if (isset($request->is_attachment_receipt_removed) && $request->is_attachment_receipt_removed == "true") {
|
||||||
$this->clearMediaCollection('receipts');
|
$this->clearMediaCollection('receipts');
|
||||||
}
|
}
|
||||||
if ($request->hasFile('attachment_receipt')) {
|
if ($request->hasFile('attachment_receipt')) {
|
||||||
$this->clearMediaCollection('receipts');
|
$this->clearMediaCollection('receipts');
|
||||||
$this->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts');
|
$this->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->customFields) {
|
if ($request->customFields) {
|
||||||
|
|||||||
@ -187,16 +187,6 @@ class Invoice extends Model implements HasMedia
|
|||||||
return Carbon::parse($this->invoice_date)->format($dateFormat);
|
return Carbon::parse($this->invoice_date)->format($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scopeWhereStatus($query, $status)
|
|
||||||
{
|
|
||||||
return $query->where('invoices.status', $status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function scopeWherePaidStatus($query, $status)
|
|
||||||
{
|
|
||||||
return $query->where('invoices.paid_status', $status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function scopeWhereDueStatus($query, $status)
|
public function scopeWhereDueStatus($query, $status)
|
||||||
{
|
{
|
||||||
return $query->whereIn('invoices.paid_status', [
|
return $query->whereIn('invoices.paid_status', [
|
||||||
@ -234,6 +224,40 @@ class Invoice extends Model implements HasMedia
|
|||||||
$query->orderBy($orderByField, $orderBy);
|
$query->orderBy($orderByField, $orderBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scopeWhereStatus($query, $status)
|
||||||
|
{
|
||||||
|
return $query->where('invoices.status', $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWherePaidStatus($query, $status)
|
||||||
|
{
|
||||||
|
return $query->where('invoices.paid_status', $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeWhereTabFilters($query, $status)
|
||||||
|
{
|
||||||
|
if ($status == "DRAFT") {
|
||||||
|
return $query->where('invoices.status', $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status == "SENT") {
|
||||||
|
return $query->whereIn('invoices.status', [
|
||||||
|
self::STATUS_SENT,
|
||||||
|
self::STATUS_VIEWED,
|
||||||
|
self::STATUS_COMPLETED
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status == 'DUE') {
|
||||||
|
return $query->whereIn('invoices.paid_status', [
|
||||||
|
self::STATUS_UNPAID,
|
||||||
|
self::STATUS_PARTIALLY_PAID,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
public function scopeApplyFilters($query, array $filters)
|
public function scopeApplyFilters($query, array $filters)
|
||||||
{
|
{
|
||||||
$filters = collect($filters);
|
$filters = collect($filters);
|
||||||
@ -249,17 +273,11 @@ class Invoice extends Model implements HasMedia
|
|||||||
$filters->get('status') == self::STATUS_PAID
|
$filters->get('status') == self::STATUS_PAID
|
||||||
) {
|
) {
|
||||||
$query->wherePaidStatus($filters->get('status'));
|
$query->wherePaidStatus($filters->get('status'));
|
||||||
} elseif ($filters->get('status') == 'DUE') {
|
|
||||||
$query->whereDueStatus($filters->get('status'));
|
|
||||||
} else {
|
} else {
|
||||||
$query->whereStatus($filters->get('status'));
|
$query->whereStatus($filters->get('status'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($filters->get('paid_status')) {
|
|
||||||
$query->wherePaidStatus($filters->get('status'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($filters->get('invoice_id')) {
|
if ($filters->get('invoice_id')) {
|
||||||
$query->whereInvoice($filters->get('invoice_id'));
|
$query->whereInvoice($filters->get('invoice_id'));
|
||||||
}
|
}
|
||||||
@ -651,7 +669,9 @@ class Invoice extends Model implements HasMedia
|
|||||||
'{INVOICE_DATE}' => $this->formattedInvoiceDate,
|
'{INVOICE_DATE}' => $this->formattedInvoiceDate,
|
||||||
'{INVOICE_DUE_DATE}' => $this->formattedDueDate,
|
'{INVOICE_DUE_DATE}' => $this->formattedDueDate,
|
||||||
'{INVOICE_NUMBER}' => $this->invoice_number,
|
'{INVOICE_NUMBER}' => $this->invoice_number,
|
||||||
'{INVOICE_REF_NUMBER}' => $this->reference_number,
|
'{PDF_LINK}' => $this->invoicePdfUrl,
|
||||||
|
'{DUE_AMOUNT}' => format_money_pdf($this->due_amount, $this->customer->currency),
|
||||||
|
'{TOTAL_AMOUNT}' => format_money_pdf($this->total, $this->customer->currency)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -435,7 +435,8 @@ class Payment extends Model implements HasMedia
|
|||||||
'{PAYMENT_DATE}' => $this->formattedPaymentDate,
|
'{PAYMENT_DATE}' => $this->formattedPaymentDate,
|
||||||
'{PAYMENT_MODE}' => $this->paymentMethod ? $this->paymentMethod->name : null,
|
'{PAYMENT_MODE}' => $this->paymentMethod ? $this->paymentMethod->name : null,
|
||||||
'{PAYMENT_NUMBER}' => $this->payment_number,
|
'{PAYMENT_NUMBER}' => $this->payment_number,
|
||||||
'{PAYMENT_AMOUNT}' => $this->reference_number,
|
'{PDF_LINK}' => $this->paymentPdfUrl,
|
||||||
|
'{PAYMENT_AMOUNT}' => format_money_pdf($this->amount, $this->customer->currency)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
"barryvdh/laravel-ide-helper": "^2.6",
|
"barryvdh/laravel-ide-helper": "^2.6",
|
||||||
"beyondcode/laravel-dump-server": "^1.0",
|
"beyondcode/laravel-dump-server": "^1.0",
|
||||||
"facade/ignition": "^2.3.6",
|
"facade/ignition": "^2.3.6",
|
||||||
"friendsofphp/php-cs-fixer": "^3.0",
|
"friendsofphp/php-cs-fixer": "^3.8",
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
"mockery/mockery": "^1.3.1",
|
"mockery/mockery": "^1.3.1",
|
||||||
"nunomaduro/collision": "^5.0",
|
"nunomaduro/collision": "^5.0",
|
||||||
@ -81,7 +81,10 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"optimize-autoloader": true,
|
"optimize-autoloader": true,
|
||||||
"preferred-install": "dist",
|
"preferred-install": "dist",
|
||||||
"sort-packages": true
|
"sort-packages": true,
|
||||||
|
"allow-plugins": {
|
||||||
|
"pestphp/pest-plugin": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"laravel": {
|
"laravel": {
|
||||||
|
|||||||
2331
composer.lock
generated
2331
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
docker compose exec app composer config --no-plugins allow-plugins.pestphp/pest-plugin true
|
|
||||||
docker-compose exec app composer install --no-interaction --prefer-dist --optimize-autoloader
|
docker-compose exec app composer install --no-interaction --prefer-dist --optimize-autoloader
|
||||||
|
|
||||||
docker-compose exec app php artisan storage:link || true
|
docker-compose exec app php artisan storage:link || true
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
"vite": "^2.6.1"
|
"vite": "^2.6.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/vue": "^1.4.0",
|
"@headlessui/vue": "^1.5.0",
|
||||||
"@heroicons/vue": "^1.0.1",
|
"@heroicons/vue": "^1.0.1",
|
||||||
"@popperjs/core": "^2.9.2",
|
"@popperjs/core": "^2.9.2",
|
||||||
"@stripe/stripe-js": "^1.21.2",
|
"@stripe/stripe-js": "^1.21.2",
|
||||||
@ -48,7 +48,8 @@
|
|||||||
"mini-svg-data-uri": "^1.3.3",
|
"mini-svg-data-uri": "^1.3.3",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"pinia": "^2.0.4",
|
"pinia": "^2.0.4",
|
||||||
"v-money3": "^3.13.5",
|
"v-calendar": "3.0.0-alpha.8",
|
||||||
|
"v-money3": "3.16.1",
|
||||||
"v-tooltip": "^4.0.0-alpha.1",
|
"v-tooltip": "^4.0.0-alpha.1",
|
||||||
"vue": "^3.2.0-beta.5",
|
"vue": "^3.2.0-beta.5",
|
||||||
"vue-flatpickr-component": "^9.0.3",
|
"vue-flatpickr-component": "^9.0.3",
|
||||||
|
|||||||
@ -6,8 +6,17 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import Chart from 'chart.js'
|
import Chart from 'chart.js'
|
||||||
import { ref, reactive, computed, onMounted, watchEffect, inject } from 'vue'
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
computed,
|
||||||
|
onMounted,
|
||||||
|
watchEffect,
|
||||||
|
inject,
|
||||||
|
watch,
|
||||||
|
} from 'vue'
|
||||||
import { useCompanyStore } from '@/scripts/admin/stores/company'
|
import { useCompanyStore } from '@/scripts/admin/stores/company'
|
||||||
|
import { useGlobalStore } from '@/scripts/admin/stores/global'
|
||||||
|
|
||||||
const utils = inject('utils')
|
const utils = inject('utils')
|
||||||
|
|
||||||
@ -44,9 +53,11 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isDarkModeOn = document.documentElement.classList.contains('dark')
|
||||||
let myLineChart = null
|
let myLineChart = null
|
||||||
const graph = ref(null)
|
const graph = ref(null)
|
||||||
const companyStore = useCompanyStore()
|
const companyStore = useCompanyStore()
|
||||||
|
const globalStore = useGlobalStore()
|
||||||
const defaultCurrency = computed(() => {
|
const defaultCurrency = computed(() => {
|
||||||
return companyStore.selectedCompanyCurrency
|
return companyStore.selectedCompanyCurrency
|
||||||
})
|
})
|
||||||
@ -60,6 +71,14 @@ watchEffect(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => globalStore.isDarkModeOn,
|
||||||
|
() => {
|
||||||
|
myLineChart.reset()
|
||||||
|
updateColors()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
let context = graph.value.getContext('2d')
|
let context = graph.value.getContext('2d')
|
||||||
let options = reactive({
|
let options = reactive({
|
||||||
@ -81,6 +100,8 @@ onMounted(() => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const salesColor = globalStore.isDarkModeOn ? '#ffffff' : '#040405'
|
||||||
|
|
||||||
let data = reactive({
|
let data = reactive({
|
||||||
labels: props.labels,
|
labels: props.labels,
|
||||||
datasets: [
|
datasets: [
|
||||||
@ -89,16 +110,16 @@ onMounted(() => {
|
|||||||
fill: false,
|
fill: false,
|
||||||
lineTension: 0.3,
|
lineTension: 0.3,
|
||||||
backgroundColor: 'rgba(230, 254, 249)',
|
backgroundColor: 'rgba(230, 254, 249)',
|
||||||
borderColor: '#040405',
|
borderColor: salesColor,
|
||||||
borderCapStyle: 'butt',
|
borderCapStyle: 'butt',
|
||||||
borderDash: [],
|
borderDash: [],
|
||||||
borderDashOffset: 0.0,
|
borderDashOffset: 0.0,
|
||||||
borderJoinStyle: 'miter',
|
borderJoinStyle: 'miter',
|
||||||
pointBorderColor: '#040405',
|
pointBorderColor: salesColor,
|
||||||
pointBackgroundColor: '#fff',
|
pointBackgroundColor: '#fff',
|
||||||
pointBorderWidth: 1,
|
pointBorderWidth: 1,
|
||||||
pointHoverRadius: 5,
|
pointHoverRadius: 5,
|
||||||
pointHoverBackgroundColor: '#040405',
|
pointHoverBackgroundColor: salesColor,
|
||||||
pointHoverBorderColor: 'rgba(220,220,220,1)',
|
pointHoverBorderColor: 'rgba(220,220,220,1)',
|
||||||
pointHoverBorderWidth: 2,
|
pointHoverBorderWidth: 2,
|
||||||
pointRadius: 4,
|
pointRadius: 4,
|
||||||
@ -194,4 +215,12 @@ function update() {
|
|||||||
lazy: true,
|
lazy: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateColors() {
|
||||||
|
const newColor = globalStore.isDarkModeOn ? '#ffffff' : '#040405'
|
||||||
|
|
||||||
|
myLineChart.data.datasets[0].borderColor = newColor
|
||||||
|
myLineChart.data.datasets[0].pointBorderColor = newColor
|
||||||
|
myLineChart.data.datasets[0].pointHoverBackgroundColor = newColor
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -50,21 +50,11 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</template>
|
</template>
|
||||||
</ValidateEach>
|
</ValidateEach>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
slot="footer"
|
|
||||||
class="
|
|
||||||
z-0
|
|
||||||
flex
|
|
||||||
justify-end
|
|
||||||
mt-4
|
|
||||||
pt-4
|
|
||||||
border-t border-gray-200 border-solid border-modal-bg
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<BaseButton :loading="isSaving" variant="primary" type="submit">
|
<BaseButton :loading="isSaving" variant="primary" type="submit">
|
||||||
{{ $t('general.save') }}
|
{{ $t('general.save') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -64,7 +64,7 @@ function mergeExistingValues() {
|
|||||||
if (props.isEdit) {
|
if (props.isEdit) {
|
||||||
props.store[props.storeProp].fields.forEach((field) => {
|
props.store[props.storeProp].fields.forEach((field) => {
|
||||||
const existingIndex = props.store[props.storeProp].customFields.findIndex(
|
const existingIndex = props.store[props.storeProp].customFields.findIndex(
|
||||||
(f) => f.id === field.custom_field_id
|
(f) => f.id == field.custom_field_id
|
||||||
)
|
)
|
||||||
|
|
||||||
if (existingIndex > -1) {
|
if (existingIndex > -1) {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { computed } from 'vue'
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: String,
|
type: String,
|
||||||
default: moment().format('YYYY-MM-DD hh:MM'),
|
default: moment().format('YYYY-MM-DD HH:mm'),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -7,11 +7,12 @@
|
|||||||
<!-- edit customField -->
|
<!-- edit customField -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.EDIT_CUSTOM_FIELDS)"
|
v-if="userStore.hasAbilities(abilities.EDIT_CUSTOM_FIELDS)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="editCustomField(row.id)"
|
@click="editCustomField(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -19,11 +20,12 @@
|
|||||||
<!-- delete customField -->
|
<!-- delete customField -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_CUSTOM_FIELDS)"
|
v-if="userStore.hasAbilities(abilities.DELETE_CUSTOM_FIELDS)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeCustomField(row.id)"
|
@click="removeCustomField(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -12,10 +12,10 @@
|
|||||||
v-if="userStore.hasAbilities(abilities.EDIT_CUSTOMER)"
|
v-if="userStore.hasAbilities(abilities.EDIT_CUSTOMER)"
|
||||||
:to="`/admin/customers/${row.id}/edit`"
|
:to="`/admin/customers/${row.id}/edit`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -29,10 +29,10 @@
|
|||||||
"
|
"
|
||||||
:to="`customers/${row.id}/view`"
|
:to="`customers/${row.id}/view`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="EyeIcon"
|
name="EyeIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.view') }}
|
{{ $t('general.view') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -41,11 +41,12 @@
|
|||||||
<!-- Delete Customer -->
|
<!-- Delete Customer -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_CUSTOMER)"
|
v-if="userStore.hasAbilities(abilities.DELETE_CUSTOMER)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeCustomer(row.id)"
|
@click="removeCustomer(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -10,11 +10,12 @@
|
|||||||
<!-- Copy PDF url -->
|
<!-- Copy PDF url -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="route.name === 'estimates.view'"
|
v-if="route.name === 'estimates.view'"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="copyPdfUrl"
|
@click="copyPdfUrl"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="LinkIcon"
|
name="LinkIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.copy_pdf_url') }}
|
{{ $t('general.copy_pdf_url') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -24,10 +25,10 @@
|
|||||||
v-if="userStore.hasAbilities(abilities.EDIT_ESTIMATE)"
|
v-if="userStore.hasAbilities(abilities.EDIT_ESTIMATE)"
|
||||||
:to="`/admin/estimates/${row.id}/edit`"
|
:to="`/admin/estimates/${row.id}/edit`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -36,11 +37,12 @@
|
|||||||
<!-- Delete Estimate -->
|
<!-- Delete Estimate -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_ESTIMATE)"
|
v-if="userStore.hasAbilities(abilities.DELETE_ESTIMATE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeEstimate(row.id)"
|
@click="removeEstimate(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -53,10 +55,10 @@
|
|||||||
"
|
"
|
||||||
:to="`estimates/${row.id}/view`"
|
:to="`estimates/${row.id}/view`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="EyeIcon"
|
name="EyeIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.view') }}
|
{{ $t('general.view') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -65,11 +67,12 @@
|
|||||||
<!-- Convert into Invoice -->
|
<!-- Convert into Invoice -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)"
|
v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="convertInToinvoice(row.id)"
|
@click="convertInToinvoice(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="DocumentTextIcon"
|
name="DocumentTextIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('estimates.convert_to_invoice') }}
|
{{ $t('estimates.convert_to_invoice') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -81,11 +84,12 @@
|
|||||||
route.name !== 'estimates.view' &&
|
route.name !== 'estimates.view' &&
|
||||||
userStore.hasAbilities(abilities.SEND_ESTIMATE)
|
userStore.hasAbilities(abilities.SEND_ESTIMATE)
|
||||||
"
|
"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="onMarkAsSent(row.id)"
|
@click="onMarkAsSent(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="CheckCircleIcon"
|
name="CheckCircleIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('estimates.mark_as_sent') }}
|
{{ $t('estimates.mark_as_sent') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -97,20 +101,21 @@
|
|||||||
route.name !== 'estimates.view' &&
|
route.name !== 'estimates.view' &&
|
||||||
userStore.hasAbilities(abilities.SEND_ESTIMATE)
|
userStore.hasAbilities(abilities.SEND_ESTIMATE)
|
||||||
"
|
"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="sendEstimate(row)"
|
@click="sendEstimate(row)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PaperAirplaneIcon"
|
name="PaperAirplaneIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('estimates.send_estimate') }}
|
{{ $t('estimates.send_estimate') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|
||||||
<!-- Resend Estimate -->
|
<!-- Resend Estimate -->
|
||||||
<BaseDropdownItem v-if="canResendEstimate(row)" @click="sendEstimate(row)">
|
<BaseDropdownItem v-if="canResendEstimate(row)" v-slot="slotProps" @click="sendEstimate(row)">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PaperAirplaneIcon"
|
name="PaperAirplaneIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('estimates.resend_estimate') }}
|
{{ $t('estimates.resend_estimate') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -121,11 +126,12 @@
|
|||||||
row.status !== 'ACCEPTED' &&
|
row.status !== 'ACCEPTED' &&
|
||||||
userStore.hasAbilities(abilities.EDIT_ESTIMATE)
|
userStore.hasAbilities(abilities.EDIT_ESTIMATE)
|
||||||
"
|
"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="onMarkAsAccepted(row.id)"
|
@click="onMarkAsAccepted(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="CheckCircleIcon"
|
name="CheckCircleIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('estimates.mark_as_accepted') }}
|
{{ $t('estimates.mark_as_accepted') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -136,11 +142,12 @@
|
|||||||
row.status !== 'REJECTED' &&
|
row.status !== 'REJECTED' &&
|
||||||
userStore.hasAbilities(abilities.EDIT_ESTIMATE)
|
userStore.hasAbilities(abilities.EDIT_ESTIMATE)
|
||||||
"
|
"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="onMarkAsRejected(row.id)"
|
@click="onMarkAsRejected(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="XCircleIcon"
|
name="XCircleIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('estimates.mark_as_rejected') }}
|
{{ $t('estimates.mark_as_rejected') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -13,11 +13,12 @@
|
|||||||
<!-- edit expenseCategory -->
|
<!-- edit expenseCategory -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.EDIT_EXPENSE)"
|
v-if="userStore.hasAbilities(abilities.EDIT_EXPENSE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="editExpenseCategory(row.id)"
|
@click="editExpenseCategory(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -25,11 +26,12 @@
|
|||||||
<!-- delete expenseCategory -->
|
<!-- delete expenseCategory -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_EXPENSE)"
|
v-if="userStore.hasAbilities(abilities.DELETE_EXPENSE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeExpenseCategory(row.id)"
|
@click="removeExpenseCategory(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -12,10 +12,10 @@
|
|||||||
v-if="userStore.hasAbilities(abilities.EDIT_EXPENSE)"
|
v-if="userStore.hasAbilities(abilities.EDIT_EXPENSE)"
|
||||||
:to="`/admin/expenses/${row.id}/edit`"
|
:to="`/admin/expenses/${row.id}/edit`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -24,11 +24,12 @@
|
|||||||
<!-- delete expense -->
|
<!-- delete expense -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_EXPENSE)"
|
v-if="userStore.hasAbilities(abilities.DELETE_EXPENSE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeExpense(row.id)"
|
@click="removeExpense(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -12,20 +12,20 @@
|
|||||||
v-if="userStore.hasAbilities(abilities.EDIT_INVOICE)"
|
v-if="userStore.hasAbilities(abilities.EDIT_INVOICE)"
|
||||||
:to="`/admin/invoices/${row.id}/edit`"
|
:to="`/admin/invoices/${row.id}/edit`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem v-show="row.allow_edit">
|
<BaseDropdownItem v-show="row.allow_edit" v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<!-- Copy PDF url -->
|
<!-- Copy PDF url -->
|
||||||
<BaseDropdownItem v-if="route.name === 'invoices.view'" @click="copyPdfUrl">
|
<BaseDropdownItem v-if="route.name === 'invoices.view'" v-slot="slotProps" @click="copyPdfUrl">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="LinkIcon"
|
name="LinkIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.copy_pdf_url') }}
|
{{ $t('general.copy_pdf_url') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -38,29 +38,29 @@
|
|||||||
"
|
"
|
||||||
:to="`/admin/invoices/${row.id}/view`"
|
:to="`/admin/invoices/${row.id}/view`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="EyeIcon"
|
name="EyeIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.view') }}
|
{{ $t('general.view') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<!-- Send Invoice Mail -->
|
<!-- Send Invoice Mail -->
|
||||||
<BaseDropdownItem v-if="canSendInvoice(row)" @click="sendInvoice(row)">
|
<BaseDropdownItem v-if="canSendInvoice(row)" v-slot="slotProps" @click="sendInvoice(row)">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PaperAirplaneIcon"
|
name="PaperAirplaneIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('invoices.send_invoice') }}
|
{{ $t('invoices.send_invoice') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|
||||||
<!-- Resend Invoice -->
|
<!-- Resend Invoice -->
|
||||||
<BaseDropdownItem v-if="canReSendInvoice(row)" @click="sendInvoice(row)">
|
<BaseDropdownItem v-if="canReSendInvoice(row)" v-slot="slotProps" @click="sendInvoice(row)">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PaperAirplaneIcon"
|
name="PaperAirplaneIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('invoices.resend_invoice') }}
|
{{ $t('invoices.resend_invoice') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -69,20 +69,21 @@
|
|||||||
<router-link :to="`/admin/payments/${row.id}/create`">
|
<router-link :to="`/admin/payments/${row.id}/create`">
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="row.status == 'SENT' && route.name !== 'invoices.view'"
|
v-if="row.status == 'SENT' && route.name !== 'invoices.view'"
|
||||||
|
v-slot="slotProps"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="CreditCardIcon"
|
name="CreditCardIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('invoices.record_payment') }}
|
{{ $t('invoices.record_payment') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<!-- Mark as sent Invoice -->
|
<!-- Mark as sent Invoice -->
|
||||||
<BaseDropdownItem v-if="canSendInvoice(row)" @click="onMarkAsSent(row.id)">
|
<BaseDropdownItem v-if="canSendInvoice(row)" v-slot="slotProps" @click="onMarkAsSent(row.id)">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="CheckCircleIcon"
|
name="CheckCircleIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('invoices.mark_as_sent') }}
|
{{ $t('invoices.mark_as_sent') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -90,11 +91,12 @@
|
|||||||
<!-- Clone Invoice into new invoice -->
|
<!-- Clone Invoice into new invoice -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)"
|
v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="cloneInvoiceData(row)"
|
@click="cloneInvoiceData(row)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="DocumentTextIcon"
|
name="DocumentTextIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('invoices.clone_invoice') }}
|
{{ $t('invoices.clone_invoice') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -102,11 +104,12 @@
|
|||||||
<!-- Delete Invoice -->
|
<!-- Delete Invoice -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_INVOICE)"
|
v-if="userStore.hasAbilities(abilities.DELETE_INVOICE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeInvoice(row.id)"
|
@click="removeInvoice(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -12,11 +12,8 @@
|
|||||||
v-if="userStore.hasAbilities(abilities.EDIT_ITEM)"
|
v-if="userStore.hasAbilities(abilities.EDIT_ITEM)"
|
||||||
:to="`/admin/items/${row.id}/edit`"
|
:to="`/admin/items/${row.id}/edit`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon name="PencilIcon" :class="slotProps.class" />
|
||||||
name="PencilIcon"
|
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
|
||||||
/>
|
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
</router-link>
|
</router-link>
|
||||||
@ -24,12 +21,10 @@
|
|||||||
<!-- delete item -->
|
<!-- delete item -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_ITEM)"
|
v-if="userStore.hasAbilities(abilities.DELETE_ITEM)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeItem(row.id)"
|
@click="removeItem(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon name="TrashIcon" :class="slotProps.class" />
|
||||||
name="TrashIcon"
|
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
|
||||||
/>
|
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
</BaseDropdown>
|
</BaseDropdown>
|
||||||
|
|||||||
@ -10,11 +10,12 @@
|
|||||||
<!-- edit note -->
|
<!-- edit note -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.MANAGE_NOTE)"
|
v-if="userStore.hasAbilities(abilities.MANAGE_NOTE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="editNote(row.id)"
|
@click="editNote(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -22,11 +23,12 @@
|
|||||||
<!-- delete note -->
|
<!-- delete note -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.MANAGE_NOTE)"
|
v-if="userStore.hasAbilities(abilities.MANAGE_NOTE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeNote(row.id)"
|
@click="removeNote(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -8,30 +8,31 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Copy pdf url -->
|
<!-- Copy pdf url -->
|
||||||
<BaseDropdown-item
|
<BaseDropdownItem
|
||||||
v-if="
|
v-if="
|
||||||
route.name === 'payments.view' &&
|
route.name === 'payments.view' &&
|
||||||
userStore.hasAbilities(abilities.VIEW_PAYMENT)
|
userStore.hasAbilities(abilities.VIEW_PAYMENT)
|
||||||
"
|
"
|
||||||
|
v-slot="slotProps"
|
||||||
class="rounded-md"
|
class="rounded-md"
|
||||||
@click="copyPdfUrl"
|
@click="copyPdfUrl"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="LinkIcon"
|
name="LinkIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.copy_pdf_url') }}
|
{{ $t('general.copy_pdf_url') }}
|
||||||
</BaseDropdown-item>
|
</BaseDropdownItem>
|
||||||
|
|
||||||
<!-- edit payment -->
|
<!-- edit payment -->
|
||||||
<router-link
|
<router-link
|
||||||
v-if="userStore.hasAbilities(abilities.EDIT_PAYMENT)"
|
v-if="userStore.hasAbilities(abilities.EDIT_PAYMENT)"
|
||||||
:to="`/admin/payments/${row.id}/edit`"
|
:to="`/admin/payments/${row.id}/edit`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -45,10 +46,10 @@
|
|||||||
"
|
"
|
||||||
:to="`/admin/payments/${row.id}/view`"
|
:to="`/admin/payments/${row.id}/view`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="EyeIcon"
|
name="EyeIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.view') }}
|
{{ $t('general.view') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -61,11 +62,12 @@
|
|||||||
route.name !== 'payments.view' &&
|
route.name !== 'payments.view' &&
|
||||||
userStore.hasAbilities(abilities.SEND_PAYMENT)
|
userStore.hasAbilities(abilities.SEND_PAYMENT)
|
||||||
"
|
"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="sendPayment(row)"
|
@click="sendPayment(row)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PaperAirplaneIcon"
|
name="PaperAirplaneIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('payments.send_payment') }}
|
{{ $t('payments.send_payment') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -73,11 +75,12 @@
|
|||||||
<!-- delete payment -->
|
<!-- delete payment -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_PAYMENT)"
|
v-if="userStore.hasAbilities(abilities.DELETE_PAYMENT)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removePayment(row.id)"
|
@click="removePayment(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -8,19 +8,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- edit paymentMode -->
|
<!-- edit paymentMode -->
|
||||||
<BaseDropdownItem @click="editPaymentMode(row.id)">
|
<BaseDropdownItem v-slot="slotProps" @click="editPaymentMode(row.id)">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|
||||||
<!-- delete paymentMode -->
|
<!-- delete paymentMode -->
|
||||||
<BaseDropdownItem @click="removePaymentMode(row.id)">
|
<BaseDropdownItem v-slot="slotProps" @click="removePaymentMode(row.id)">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -15,10 +15,10 @@
|
|||||||
v-if="userStore.hasAbilities(abilities.EDIT_RECURRING_INVOICE)"
|
v-if="userStore.hasAbilities(abilities.EDIT_RECURRING_INVOICE)"
|
||||||
:to="`/admin/recurring-invoices/${row.id}/edit`"
|
:to="`/admin/recurring-invoices/${row.id}/edit`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -32,10 +32,10 @@
|
|||||||
"
|
"
|
||||||
:to="`recurring-invoices/${row.id}/view`"
|
:to="`recurring-invoices/${row.id}/view`"
|
||||||
>
|
>
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="EyeIcon"
|
name="EyeIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.view') }}
|
{{ $t('general.view') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -44,11 +44,12 @@
|
|||||||
<!-- Delete Recurring Invoice -->
|
<!-- Delete Recurring Invoice -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_RECURRING_INVOICE)"
|
v-if="userStore.hasAbilities(abilities.DELETE_RECURRING_INVOICE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeMultipleRecurringInvoices(row.id)"
|
@click="removeMultipleRecurringInvoices(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -10,11 +10,12 @@
|
|||||||
<!-- edit role -->
|
<!-- edit role -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.currentUser.is_owner"
|
v-if="userStore.currentUser.is_owner"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="editRole(row.id)"
|
@click="editRole(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -22,11 +23,12 @@
|
|||||||
<!-- delete role -->
|
<!-- delete role -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.currentUser.is_owner"
|
v-if="userStore.currentUser.is_owner"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeRole(row.id)"
|
@click="removeRole(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -10,11 +10,12 @@
|
|||||||
<!-- edit tax-type -->
|
<!-- edit tax-type -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.EDIT_TAX_TYPE)"
|
v-if="userStore.hasAbilities(abilities.EDIT_TAX_TYPE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="editTaxType(row.id)"
|
@click="editTaxType(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
@ -22,11 +23,12 @@
|
|||||||
<!-- delete tax-type -->
|
<!-- delete tax-type -->
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.DELETE_TAX_TYPE)"
|
v-if="userStore.hasAbilities(abilities.DELETE_TAX_TYPE)"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeTaxType(row.id)"
|
@click="removeTaxType(row.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -9,20 +9,20 @@
|
|||||||
|
|
||||||
<!-- edit user -->
|
<!-- edit user -->
|
||||||
<router-link :to="`/admin/users/${row.id}/edit`">
|
<router-link :to="`/admin/users/${row.id}/edit`">
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="PencilIcon"
|
name="PencilIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<!-- delete user -->
|
<!-- delete user -->
|
||||||
<BaseDropdownItem @click="removeUser(row.id)">
|
<BaseDropdownItem v-slot="slotProps" @click="removeUser(row.id)">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="TrashIcon"
|
name="TrashIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
/>
|
/>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|||||||
@ -17,18 +17,7 @@
|
|||||||
<td class="px-5 py-4 text-left align-top">
|
<td class="px-5 py-4 text-left align-top">
|
||||||
<div class="flex justify-start">
|
<div class="flex justify-start">
|
||||||
<div
|
<div
|
||||||
class="
|
class="flex items-center justify-center w-5 h-5 mt-2 mr-2 text-gray-300 cursor-move handle"
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
w-5
|
|
||||||
h-5
|
|
||||||
mt-2
|
|
||||||
text-gray-300
|
|
||||||
cursor-move
|
|
||||||
handle
|
|
||||||
mr-2
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<DragIcon />
|
<DragIcon />
|
||||||
</div>
|
</div>
|
||||||
@ -108,7 +97,7 @@
|
|||||||
|
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="ChevronDownIcon"
|
name="ChevronDownIcon"
|
||||||
class="w-4 h-4 text-gray-500 ml-1"
|
class="w-4 h-4 ml-1 text-gray-500"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
@ -155,7 +144,7 @@
|
|||||||
<BaseContentPlaceholders v-if="loading">
|
<BaseContentPlaceholders v-if="loading">
|
||||||
<BaseContentPlaceholdersText
|
<BaseContentPlaceholdersText
|
||||||
:lines="1"
|
:lines="1"
|
||||||
class="w-24 h-8 rounded-md border"
|
class="w-24 h-8 border rounded-md"
|
||||||
/>
|
/>
|
||||||
</BaseContentPlaceholders>
|
</BaseContentPlaceholders>
|
||||||
|
|
||||||
@ -175,6 +164,7 @@
|
|||||||
:ability="abilities.CREATE_INVOICE"
|
:ability="abilities.CREATE_INVOICE"
|
||||||
:store="store"
|
:store="store"
|
||||||
:store-prop="storeProp"
|
:store-prop="storeProp"
|
||||||
|
:discount="discount"
|
||||||
@update="updateTax"
|
@update="updateTax"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -30,24 +30,13 @@
|
|||||||
<template v-if="userStore.hasAbilities(ability)" #action>
|
<template v-if="userStore.hasAbilities(ability)" #action>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="
|
class="flex items-center justify-center w-full px-2 py-2 bg-gray-200 border-none outline-none cursor-pointer "
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
w-full
|
|
||||||
px-2
|
|
||||||
cursor-pointer
|
|
||||||
py-2
|
|
||||||
bg-gray-200
|
|
||||||
border-none
|
|
||||||
outline-none
|
|
||||||
"
|
|
||||||
@click="openTaxModal"
|
@click="openTaxModal"
|
||||||
>
|
>
|
||||||
<BaseIcon name="CheckCircleIcon" class="h-5 text-primary-400" />
|
<BaseIcon name="CheckCircleIcon" class="h-5 text-primary-400" />
|
||||||
|
|
||||||
<label
|
<label
|
||||||
class="ml-2 text-sm leading-none text-primary-400 cursor-pointer"
|
class="ml-2 text-sm leading-none cursor-pointer text-primary-400"
|
||||||
>{{ $t('invoices.add_new_tax') }}</label
|
>{{ $t('invoices.add_new_tax') }}</label
|
||||||
>
|
>
|
||||||
</button>
|
</button>
|
||||||
@ -115,6 +104,10 @@ const props = defineProps({
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
|
discountedTotal: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
currency: {
|
currency: {
|
||||||
type: [Object, String],
|
type: [Object, String],
|
||||||
required: true,
|
required: true,
|
||||||
@ -153,19 +146,19 @@ const filteredTypes = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const taxAmount = computed(() => {
|
const taxAmount = computed(() => {
|
||||||
if (localTax.compound_tax && props.total) {
|
if (localTax.compound_tax && props.discountedTotal) {
|
||||||
return ((props.total + props.totalTax) * localTax.percent) / 100
|
return ((props.discountedTotal + props.totalTax) * localTax.percent) / 100
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.total && localTax.percent) {
|
if (props.discountedTotal && localTax.percent) {
|
||||||
return (props.total * localTax.percent) / 100
|
return (props.discountedTotal * localTax.percent) / 100
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.total,
|
() => props.discountedTotal,
|
||||||
() => {
|
() => {
|
||||||
updateRowTax()
|
updateRowTax()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,14 +29,7 @@
|
|||||||
|
|
||||||
<label
|
<label
|
||||||
v-else
|
v-else
|
||||||
class="
|
class="flex items-center justify-center m-0 text-lg text-black uppercase "
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
m-0
|
|
||||||
text-lg text-black
|
|
||||||
uppercase
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<BaseFormatMoney
|
<BaseFormatMoney
|
||||||
:amount="store.getSubTotal"
|
:amount="store.getSubTotal"
|
||||||
@ -66,14 +59,7 @@
|
|||||||
|
|
||||||
<label
|
<label
|
||||||
v-else-if="store[storeProp].tax_per_item === 'YES'"
|
v-else-if="store[storeProp].tax_per_item === 'YES'"
|
||||||
class="
|
class="flex items-center justify-center m-0 text-lg text-black uppercase "
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
m-0
|
|
||||||
text-lg text-black
|
|
||||||
uppercase
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<BaseFormatMoney :amount="tax.amount" :currency="defaultCurrency" />
|
<BaseFormatMoney :amount="tax.amount" :currency="defaultCurrency" />
|
||||||
</label>
|
</label>
|
||||||
@ -98,7 +84,7 @@
|
|||||||
<BaseContentPlaceholders v-if="isLoading">
|
<BaseContentPlaceholders v-if="isLoading">
|
||||||
<BaseContentPlaceholdersText
|
<BaseContentPlaceholdersText
|
||||||
:lines="1"
|
:lines="1"
|
||||||
class="w-24 h-8 rounded-md border"
|
class="w-24 h-8 border rounded-md"
|
||||||
/>
|
/>
|
||||||
</BaseContentPlaceholders>
|
</BaseContentPlaceholders>
|
||||||
<div v-else class="flex" style="width: 140px" role="group">
|
<div v-else class="flex" style="width: 140px" role="group">
|
||||||
@ -114,7 +100,7 @@
|
|||||||
<BaseDropdown position="bottom-end">
|
<BaseDropdown position="bottom-end">
|
||||||
<template #activator>
|
<template #activator>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="rounded-tr-md rounded-br-md p-2 rounded-none"
|
class="p-2 rounded-none rounded-tr-md rounded-br-md"
|
||||||
type="button"
|
type="button"
|
||||||
variant="white"
|
variant="white"
|
||||||
>
|
>
|
||||||
@ -127,7 +113,7 @@
|
|||||||
|
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="ChevronDownIcon"
|
name="ChevronDownIcon"
|
||||||
class="w-4 h-4 text-gray-500 ml-1"
|
class="w-4 h-4 ml-1 text-gray-500"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
@ -180,15 +166,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="
|
class="flex items-center justify-between w-full pt-2 mt-5 border-t border-gray-200 border-solid "
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
justify-between
|
|
||||||
w-full
|
|
||||||
pt-2
|
|
||||||
mt-5
|
|
||||||
border-t border-gray-200 border-solid
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<BaseContentPlaceholders v-if="isLoading">
|
<BaseContentPlaceholders v-if="isLoading">
|
||||||
<BaseContentPlaceholdersText :lines="1" class="w-16 h-5" />
|
<BaseContentPlaceholdersText :lines="1" class="w-16 h-5" />
|
||||||
@ -204,14 +182,7 @@
|
|||||||
</BaseContentPlaceholders>
|
</BaseContentPlaceholders>
|
||||||
<label
|
<label
|
||||||
v-else
|
v-else
|
||||||
class="
|
class="flex items-center justify-center text-lg uppercase text-primary-400"
|
||||||
flex
|
|
||||||
items-center
|
|
||||||
justify-center
|
|
||||||
text-lg
|
|
||||||
uppercase
|
|
||||||
text-primary-400
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<BaseFormatMoney :amount="store.getTotal" :currency="defaultCurrency" />
|
<BaseFormatMoney :amount="store.getTotal" :currency="defaultCurrency" />
|
||||||
</label>
|
</label>
|
||||||
@ -334,6 +305,7 @@ function selectPercentage() {
|
|||||||
|
|
||||||
function onSelectTax(selectedTax) {
|
function onSelectTax(selectedTax) {
|
||||||
let amount = 0
|
let amount = 0
|
||||||
|
|
||||||
if (selectedTax.compound_tax && props.store.getSubtotalWithDiscount) {
|
if (selectedTax.compound_tax && props.store.getSubtotalWithDiscount) {
|
||||||
amount = Math.round(
|
amount = Math.round(
|
||||||
((props.store.getSubtotalWithDiscount + props.store.getTotalSimpleTax) *
|
((props.store.getSubtotalWithDiscount + props.store.getTotalSimpleTax) *
|
||||||
|
|||||||
@ -57,9 +57,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -84,7 +82,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ $t('general.create') }}
|
{{ $t('general.create') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -47,15 +47,7 @@
|
|||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="
|
|
||||||
z-0
|
|
||||||
flex
|
|
||||||
justify-end
|
|
||||||
p-4
|
|
||||||
border-t border-gray-200 border-solid border-modal-bg
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
type="button"
|
type="button"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -80,7 +72,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ categoryStore.isEdit ? $t('general.update') : $t('general.save') }}
|
{{ categoryStore.isEdit ? $t('general.update') : $t('general.save') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -48,6 +48,24 @@
|
|||||||
/>
|
/>
|
||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
|
|
||||||
|
<BaseInputGroup
|
||||||
|
:label="$tc('settings.company_info.company_slug')"
|
||||||
|
:help-text="$t('settings.company_info.company_slug_help_text')"
|
||||||
|
:error="
|
||||||
|
v$.newCompanyForm.slug.$error &&
|
||||||
|
v$.newCompanyForm.slug.$errors[0].$message
|
||||||
|
"
|
||||||
|
:content-loading="isFetchingInitialData"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<BaseInput
|
||||||
|
v-model="newCompanyForm.slug"
|
||||||
|
:invalid="v$.newCompanyForm.slug.$error"
|
||||||
|
:content-loading="isFetchingInitialData"
|
||||||
|
@input="v$.newCompanyForm.slug.$touch()"
|
||||||
|
/>
|
||||||
|
</BaseInputGroup>
|
||||||
|
|
||||||
<BaseInputGroup
|
<BaseInputGroup
|
||||||
:content-loading="isFetchingInitialData"
|
:content-loading="isFetchingInitialData"
|
||||||
:label="$tc('settings.company_info.country')"
|
:label="$tc('settings.company_info.country')"
|
||||||
@ -98,7 +116,7 @@
|
|||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="z-0 flex justify-end p-4 bg-gray-50 border-modal-bg">
|
<BaseModalFooter>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3 text-sm"
|
class="mr-3 text-sm"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -123,14 +141,14 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ $t('general.save') }}
|
{{ $t('general.save') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useModalStore } from '@/scripts/stores/modal'
|
import { useModalStore } from '@/scripts/stores/modal'
|
||||||
import { computed, onMounted, ref, reactive } from 'vue'
|
import { computed, onMounted, ref, reactive, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { required, minLength, helpers } from '@vuelidate/validators'
|
import { required, minLength, helpers } from '@vuelidate/validators'
|
||||||
import { useVuelidate } from '@vuelidate/core'
|
import { useVuelidate } from '@vuelidate/core'
|
||||||
@ -152,6 +170,7 @@ let companyLogoName = ref(null)
|
|||||||
|
|
||||||
const newCompanyForm = reactive({
|
const newCompanyForm = reactive({
|
||||||
name: null,
|
name: null,
|
||||||
|
slug: null,
|
||||||
currency: '',
|
currency: '',
|
||||||
address: {
|
address: {
|
||||||
country_id: null,
|
country_id: null,
|
||||||
@ -162,6 +181,9 @@ const modalActive = computed(() => {
|
|||||||
return modalStore.active && modalStore.componentName === 'CompanyModal'
|
return modalStore.active && modalStore.componentName === 'CompanyModal'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const slugValidator = (value) => {
|
||||||
|
return value == slugify(value)
|
||||||
|
}
|
||||||
const rules = {
|
const rules = {
|
||||||
newCompanyForm: {
|
newCompanyForm: {
|
||||||
name: {
|
name: {
|
||||||
@ -171,6 +193,17 @@ const rules = {
|
|||||||
minLength(3)
|
minLength(3)
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
slug: {
|
||||||
|
required: helpers.withMessage(t('validation.required'), required),
|
||||||
|
minLength: helpers.withMessage(
|
||||||
|
t('validation.name_min_length', { count: 3 }),
|
||||||
|
minLength(3)
|
||||||
|
),
|
||||||
|
slugValidator: helpers.withMessage(
|
||||||
|
t('validation.invalid_slug'),
|
||||||
|
slugValidator
|
||||||
|
),
|
||||||
|
},
|
||||||
address: {
|
address: {
|
||||||
country_id: {
|
country_id: {
|
||||||
required: helpers.withMessage(t('validation.required'), required),
|
required: helpers.withMessage(t('validation.required'), required),
|
||||||
@ -243,6 +276,7 @@ async function submitCompanyData() {
|
|||||||
|
|
||||||
function resetNewCompanyForm() {
|
function resetNewCompanyForm() {
|
||||||
newCompanyForm.name = ''
|
newCompanyForm.name = ''
|
||||||
|
newCompanyForm.slug = ''
|
||||||
newCompanyForm.currency = ''
|
newCompanyForm.currency = ''
|
||||||
newCompanyForm.address.country_id = ''
|
newCompanyForm.address.country_id = ''
|
||||||
|
|
||||||
@ -257,4 +291,24 @@ function closeCompanyModal() {
|
|||||||
v$.value.$reset()
|
v$.value.$reset()
|
||||||
}, 300)
|
}, 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// watcher for if change company name then auto fill company slug value
|
||||||
|
watch(
|
||||||
|
() => newCompanyForm.name,
|
||||||
|
(currentValue) => {
|
||||||
|
newCompanyForm.slug = slugify(currentValue)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
function slugify(string) {
|
||||||
|
return string
|
||||||
|
.toString()
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, '-')
|
||||||
|
.replace(/[^\w\-]+/g, '')
|
||||||
|
.replace(/\-\-+/g, '-')
|
||||||
|
.replace(/^-+/, '')
|
||||||
|
.replace(/-+$/, '')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -425,9 +425,7 @@
|
|||||||
</BaseTabGroup>
|
</BaseTabGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3 text-sm"
|
class="mr-3 text-sm"
|
||||||
type="button"
|
type="button"
|
||||||
@ -447,7 +445,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ $t('general.save') }}
|
{{ $t('general.save') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="z-0 flex justify-end p-4 bg-gray-50 border-modal-bg">
|
<BaseModalFooter>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3 text-sm"
|
class="mr-3 text-sm"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -63,7 +63,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -150,9 +150,7 @@
|
|||||||
@Remove="removeUsedSelectedCurrencies"
|
@Remove="removeUsedSelectedCurrencies"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -179,7 +177,7 @@
|
|||||||
exchangeRateStore.isEdit ? $t('general.update') : $t('general.save')
|
exchangeRateStore.isEdit ? $t('general.update') : $t('general.save')
|
||||||
}}
|
}}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -20,15 +20,7 @@
|
|||||||
@submit="createNewDisk"
|
@submit="createNewDisk"
|
||||||
>
|
>
|
||||||
<template #default="slotProps">
|
<template #default="slotProps">
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="
|
|
||||||
z-0
|
|
||||||
flex
|
|
||||||
justify-end
|
|
||||||
p-4
|
|
||||||
border-t border-solid border-gray-light
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3 text-sm"
|
class="mr-3 text-sm"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -52,7 +44,7 @@
|
|||||||
|
|
||||||
{{ $t('general.save') }}
|
{{ $t('general.save') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</template>
|
</template>
|
||||||
</component>
|
</component>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -89,9 +89,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -111,7 +109,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ itemStore.isEdit ? $t('general.update') : $t('general.save') }}
|
{{ itemStore.isEdit ? $t('general.update') : $t('general.save') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
|
|||||||
@ -31,15 +31,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="
|
|
||||||
z-0
|
|
||||||
flex
|
|
||||||
justify-end
|
|
||||||
p-4
|
|
||||||
border-t border-gray-200 border-solid border-modal-bg
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
type="button"
|
type="button"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -66,7 +58,7 @@
|
|||||||
itemStore.isItemUnitEdit ? $t('general.update') : $t('general.save')
|
itemStore.isItemUnitEdit ? $t('general.update') : $t('general.save')
|
||||||
}}
|
}}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -62,9 +62,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
type="button"
|
type="button"
|
||||||
@ -84,7 +82,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ $t('general.send') }}
|
{{ $t('general.send') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -63,16 +63,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="
|
|
||||||
z-0
|
|
||||||
flex
|
|
||||||
justify-end
|
|
||||||
px-4
|
|
||||||
py-4
|
|
||||||
border-t border-solid border-gray-light
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -93,7 +84,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ noteStore.isEdit ? $t('general.update') : $t('general.save') }}
|
{{ noteStore.isEdit ? $t('general.update') : $t('general.save') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -29,9 +29,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
@ -56,7 +54,7 @@
|
|||||||
: $t('general.save')
|
: $t('general.save')
|
||||||
}}
|
}}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -72,7 +72,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="border-t border-gray-200 py-3">
|
<div class="border-t border-gray-200 dark:border-gray-600 py-3">
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
grid grid-cols-1
|
grid grid-cols-1
|
||||||
@ -89,7 +89,7 @@
|
|||||||
:key="gIndex"
|
:key="gIndex"
|
||||||
class="flex flex-col space-y-1"
|
class="flex flex-col space-y-1"
|
||||||
>
|
>
|
||||||
<p class="text-sm text-gray-500 border-b border-gray-200 pb-1 mb-2">
|
<p class="text-sm text-gray-500 dark:text-gray-200 border-b dark:border-gray-600 pb-1 mb-2">
|
||||||
{{ gIndex }}
|
{{ gIndex }}
|
||||||
</p>
|
</p>
|
||||||
<div
|
<div
|
||||||
@ -116,15 +116,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="
|
|
||||||
z-0
|
|
||||||
flex
|
|
||||||
justify-end
|
|
||||||
p-4
|
|
||||||
border-t border-solid border--200 border-modal-bg
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3 text-sm"
|
class="mr-3 text-sm"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -144,7 +136,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ !roleStore.isEdit ? $t('general.save') : $t('general.update') }}
|
{{ !roleStore.isEdit ? $t('general.save') : $t('general.update') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -70,7 +70,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid">
|
<BaseModalFooter>
|
||||||
<BaseButton class="mr-3" variant="primary-outline" @click="closeModal">
|
<BaseButton class="mr-3" variant="primary-outline" @click="closeModal">
|
||||||
{{ $t('general.cancel') }}
|
{{ $t('general.cancel') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
@ -80,7 +80,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ $t('general.choose') }}
|
{{ $t('general.choose') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -62,9 +62,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -85,7 +83,7 @@
|
|||||||
<BaseIcon v-if="!isLoading" name="PhotographIcon" class="h-5 mr-2" />
|
<BaseIcon v-if="!isLoading" name="PhotographIcon" class="h-5 mr-2" />
|
||||||
{{ $t('general.preview') }}
|
{{ $t('general.preview') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div class="my-6 mx-4 border border-gray-200 relative">
|
<div class="my-6 mx-4 border border-gray-200 relative">
|
||||||
@ -106,9 +104,7 @@
|
|||||||
></iframe>
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -127,7 +123,7 @@
|
|||||||
<BaseIcon v-if="!isLoading" name="PaperAirplaneIcon" class="mr-2" />
|
<BaseIcon v-if="!isLoading" name="PaperAirplaneIcon" class="mr-2" />
|
||||||
{{ $t('general.send') }}
|
{{ $t('general.send') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</div>
|
</div>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -65,9 +65,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -93,7 +91,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ $t('general.preview') }}
|
{{ $t('general.preview') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div class="my-6 mx-4 border border-gray-200 relative">
|
<div class="my-6 mx-4 border border-gray-200 relative">
|
||||||
@ -114,9 +112,7 @@
|
|||||||
style="min-height: 500px"
|
style="min-height: 500px"
|
||||||
></iframe>
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -140,7 +136,7 @@
|
|||||||
/>
|
/>
|
||||||
{{ $t('general.send') }}
|
{{ $t('general.send') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</div>
|
</div>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -65,9 +65,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -93,7 +91,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ $t('general.preview') }}
|
{{ $t('general.preview') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div class="my-6 mx-4 border border-gray-200 relative">
|
<div class="my-6 mx-4 border border-gray-200 relative">
|
||||||
@ -114,9 +112,7 @@
|
|||||||
style="min-height: 500px"
|
style="min-height: 500px"
|
||||||
></iframe>
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -140,7 +136,7 @@
|
|||||||
/>
|
/>
|
||||||
{{ $t('general.send') }}
|
{{ $t('general.send') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</div>
|
</div>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -90,15 +90,7 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="
|
|
||||||
z-0
|
|
||||||
flex
|
|
||||||
justify-end
|
|
||||||
p-4
|
|
||||||
border-t border-solid border--200 border-modal-bg
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3 text-sm"
|
class="mr-3 text-sm"
|
||||||
variant="primary-outline"
|
variant="primary-outline"
|
||||||
@ -122,7 +114,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ taxTypeStore.isEdit ? $t('general.update') : $t('general.save') }}
|
{{ taxTypeStore.isEdit ? $t('general.update') : $t('general.save') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -87,9 +87,7 @@
|
|||||||
</BaseInputGrid>
|
</BaseInputGrid>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="z-0 flex justify-end p-4 border-t border-gray-200 border-solid"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3 text-sm"
|
class="mr-3 text-sm"
|
||||||
type="button"
|
type="button"
|
||||||
@ -109,7 +107,7 @@
|
|||||||
</template>
|
</template>
|
||||||
{{ $t('general.save') }}
|
{{ $t('general.save') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -172,15 +172,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<BaseModalFooter>
|
||||||
class="
|
|
||||||
z-0
|
|
||||||
flex
|
|
||||||
justify-end
|
|
||||||
p-4
|
|
||||||
border-t border-solid border-gray-light border-modal-bg
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
class="mr-3"
|
class="mr-3"
|
||||||
type="button"
|
type="button"
|
||||||
@ -207,7 +199,7 @@
|
|||||||
!customFieldStore.isEdit ? $t('general.save') : $t('general.update')
|
!customFieldStore.isEdit ? $t('general.save') : $t('general.update')
|
||||||
}}
|
}}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</div>
|
</BaseModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -153,7 +153,7 @@
|
|||||||
<BaseSwitch v-model="set_as_default" class="flex" />
|
<BaseSwitch v-model="set_as_default" class="flex" />
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 right">
|
<div class="ml-4 right">
|
||||||
<p class="p-0 mb-1 text-base leading-snug text-black box-title">
|
<p class="p-0 mb-1 text-base leading-snug text-black dark:text-white box-title">
|
||||||
{{ $t('settings.disk.is_default') }}
|
{{ $t('settings.disk.is_default') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -132,7 +132,7 @@
|
|||||||
<BaseSwitch v-model="set_as_default" class="flex" />
|
<BaseSwitch v-model="set_as_default" class="flex" />
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 right">
|
<div class="ml-4 right">
|
||||||
<p class="p-0 mb-1 text-base leading-snug text-black box-title">
|
<p class="p-0 mb-1 text-base leading-snug text-black dark:text-white box-title">
|
||||||
{{ $t('settings.disk.is_default') }}
|
{{ $t('settings.disk.is_default') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -63,7 +63,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ml-4 right">
|
<div class="ml-4 right">
|
||||||
<p class="p-0 mb-1 text-base leading-snug text-black box-title">
|
<p class="p-0 mb-1 text-base leading-snug text-black dark:text-white box-title">
|
||||||
{{ $t('settings.disk.is_default') }}
|
{{ $t('settings.disk.is_default') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -134,7 +134,7 @@
|
|||||||
<BaseSwitch v-model="set_as_default" class="flex" />
|
<BaseSwitch v-model="set_as_default" class="flex" />
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-4 right">
|
<div class="ml-4 right">
|
||||||
<p class="p-0 mb-1 text-base leading-snug text-black box-title">
|
<p class="p-0 mb-1 text-base leading-snug text-black dark:text-white box-title">
|
||||||
{{ $t('settings.disk.is_default') }}
|
{{ $t('settings.disk.is_default') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -15,8 +15,17 @@
|
|||||||
bg-gradient-to-r
|
bg-gradient-to-r
|
||||||
from-primary-500
|
from-primary-500
|
||||||
to-primary-400
|
to-primary-400
|
||||||
|
dark:from-gray-700/70 dark:to-gray-800/70
|
||||||
|
bg-primary-500
|
||||||
|
dark:bg-transparent
|
||||||
|
dark:backdrop-blur-xl
|
||||||
|
dark:shadow-glass
|
||||||
|
dark:border
|
||||||
|
dark:border-white/10
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
<BaseDarkHighlight />
|
||||||
|
|
||||||
<router-link
|
<router-link
|
||||||
to="/admin/dashboard"
|
to="/admin/dashboard"
|
||||||
class="
|
class="
|
||||||
@ -53,6 +62,7 @@
|
|||||||
cursor-pointer
|
cursor-pointer
|
||||||
md:hidden md:ml-0
|
md:hidden md:ml-0
|
||||||
hover:bg-gray-100
|
hover:bg-gray-100
|
||||||
|
dark:bg-gray-800 dark:border-gray-500 dark:border
|
||||||
"
|
"
|
||||||
@click.prevent="onToggle"
|
@click.prevent="onToggle"
|
||||||
>
|
>
|
||||||
@ -64,7 +74,7 @@
|
|||||||
v-if="hasCreateAbilities"
|
v-if="hasCreateAbilities"
|
||||||
class="relative hidden float-left m-0 md:block"
|
class="relative hidden float-left m-0 md:block"
|
||||||
>
|
>
|
||||||
<BaseDropdown width-class="w-48">
|
<BaseDropdown width-class="w-48" >
|
||||||
<template #activator>
|
<template #activator>
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
@ -78,19 +88,21 @@
|
|||||||
bg-white
|
bg-white
|
||||||
rounded
|
rounded
|
||||||
md:h-9 md:w-9
|
md:h-9 md:w-9
|
||||||
|
dark:bg-gray-700 dark:border-gray-500 dark:border
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<BaseIcon name="PlusIcon" class="w-5 h-5 text-gray-600" />
|
<BaseIcon name="PlusIcon" class="w-5 h-5 text-gray-600 dark:text-white" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<router-link to="/admin/invoices/create">
|
<router-link to="/admin/invoices/create">
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)"
|
v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)"
|
||||||
|
v-slot="slotProps"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="DocumentTextIcon"
|
name="DocumentTextIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
{{ $t('invoices.new_invoice') }}
|
{{ $t('invoices.new_invoice') }}
|
||||||
@ -99,10 +111,11 @@
|
|||||||
<router-link to="/admin/estimates/create">
|
<router-link to="/admin/estimates/create">
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.CREATE_ESTIMATE)"
|
v-if="userStore.hasAbilities(abilities.CREATE_ESTIMATE)"
|
||||||
|
v-slot="slotProps"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="DocumentIcon"
|
name="DocumentIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
{{ $t('estimates.new_estimate') }}
|
{{ $t('estimates.new_estimate') }}
|
||||||
@ -112,10 +125,11 @@
|
|||||||
<router-link to="/admin/customers/create">
|
<router-link to="/admin/customers/create">
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="userStore.hasAbilities(abilities.CREATE_CUSTOMER)"
|
v-if="userStore.hasAbilities(abilities.CREATE_CUSTOMER)"
|
||||||
|
v-slot="slotProps"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="UserIcon"
|
name="UserIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
{{ $t('customers.new_customer') }}
|
{{ $t('customers.new_customer') }}
|
||||||
@ -143,25 +157,25 @@
|
|||||||
<template #activator>
|
<template #activator>
|
||||||
<img
|
<img
|
||||||
:src="previewAvatar"
|
:src="previewAvatar"
|
||||||
class="block w-8 h-8 rounded md:h-9 md:w-9"
|
class="block w-8 h-8 rounded md:h-9 md:w-9 object-cover"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<router-link to="/admin/settings/account-settings">
|
<router-link to="/admin/settings/account-settings">
|
||||||
<BaseDropdownItem>
|
<BaseDropdownItem v-slot="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="CogIcon"
|
name="CogIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
{{ $t('navigation.settings') }}
|
{{ $t('navigation.settings') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
<BaseDropdownItem @click="logout">
|
<BaseDropdownItem v-slot="slotProps" @click="logout">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="LogoutIcon"
|
name="LogoutIcon"
|
||||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
:class="slotProps.class"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
{{ $t('navigation.logout') }}
|
{{ $t('navigation.logout') }}
|
||||||
|
|||||||
@ -15,7 +15,9 @@
|
|||||||
leave-from="opacity-100"
|
leave-from="opacity-100"
|
||||||
leave-to="opacity-0"
|
leave-to="opacity-0"
|
||||||
>
|
>
|
||||||
<DialogOverlay class="fixed inset-0 bg-gray-600 bg-opacity-75" />
|
<DialogOverlay
|
||||||
|
class="fixed inset-0 bg-gray-600 bg-opacity-75 dark:bg-gray-900/90"
|
||||||
|
/>
|
||||||
</TransitionChild>
|
</TransitionChild>
|
||||||
|
|
||||||
<TransitionChild
|
<TransitionChild
|
||||||
@ -27,7 +29,9 @@
|
|||||||
leave-from="translate-x-0"
|
leave-from="translate-x-0"
|
||||||
leave-to="-translate-x-full"
|
leave-to="-translate-x-full"
|
||||||
>
|
>
|
||||||
<div class="relative flex flex-col flex-1 w-full max-w-xs bg-white">
|
<div
|
||||||
|
class="relative flex flex-col flex-1 w-full max-w-xs bg-white dark:bg-gray-800"
|
||||||
|
>
|
||||||
<TransitionChild
|
<TransitionChild
|
||||||
as="template"
|
as="template"
|
||||||
enter="ease-in-out duration-300"
|
enter="ease-in-out duration-300"
|
||||||
@ -40,18 +44,17 @@
|
|||||||
<div class="absolute top-0 right-0 pt-2 -mr-12">
|
<div class="absolute top-0 right-0 pt-2 -mr-12">
|
||||||
<button
|
<button
|
||||||
class="
|
class="
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
justify-center
|
||||||
w-10
|
w-10
|
||||||
h-10
|
h-10
|
||||||
ml-1
|
ml-1
|
||||||
rounded-full
|
rounded-full
|
||||||
focus:outline-none
|
focus:outline-none
|
||||||
focus:ring-2
|
focus:ring-2
|
||||||
focus:ring-inset
|
focus:ring-inset
|
||||||
focus:ring-white
|
focus:ring-white"
|
||||||
"
|
|
||||||
@click="globalStore.setSidebarVisibility(false)"
|
@click="globalStore.setSidebarVisibility(false)"
|
||||||
>
|
>
|
||||||
<span class="sr-only">Close sidebar</span>
|
<span class="sr-only">Close sidebar</span>
|
||||||
@ -82,8 +85,8 @@
|
|||||||
:to="item.link"
|
:to="item.link"
|
||||||
:class="[
|
:class="[
|
||||||
hasActiveUrl(item.link)
|
hasActiveUrl(item.link)
|
||||||
? 'text-primary-500 border-primary-500 bg-gray-100 '
|
? 'text-primary-500 border-primary-500 bg-gray-100 dark:shadow-glass dark:backdrop-blur-xl dark:hover:bg-gray-700 dark:bg-gray-700/50 dark:text-primary-400 dark:font-medium'
|
||||||
: 'text-black',
|
: 'text-black dark:text-gray-300',
|
||||||
'cursor-pointer px-0 pl-4 py-3 border-transparent flex items-center border-l-4 border-solid text-sm not-italic font-medium',
|
'cursor-pointer px-0 pl-4 py-3 border-transparent flex items-center border-l-4 border-solid text-sm not-italic font-medium',
|
||||||
]"
|
]"
|
||||||
@click="globalStore.setSidebarVisibility(false)"
|
@click="globalStore.setSidebarVisibility(false)"
|
||||||
@ -100,6 +103,10 @@
|
|||||||
/>
|
/>
|
||||||
{{ $t(item.title) }}
|
{{ $t(item.title) }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
<LightDarkSwitch
|
||||||
|
:show-label="false"
|
||||||
|
class="absolute right-6 top-6 !w-auto"
|
||||||
|
/>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -113,17 +120,16 @@
|
|||||||
<!-- DESKTOP MENU -->
|
<!-- DESKTOP MENU -->
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
hidden
|
hidden
|
||||||
w-56
|
w-56
|
||||||
h-screen
|
h-screen
|
||||||
pb-32
|
bg-white
|
||||||
overflow-y-auto
|
border-r border-gray-200 border-solid
|
||||||
bg-white
|
xl:w-64
|
||||||
border-r border-gray-200 border-solid
|
md:fixed md:flex md:flex-col md:inset-y-0
|
||||||
xl:w-64
|
pt-16
|
||||||
md:fixed md:flex md:flex-col md:inset-y-0
|
dark:border-gray-800
|
||||||
pt-16
|
dark:bg-gray-800/80"
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="menu in globalStore.menuGroups"
|
v-for="menu in globalStore.menuGroups"
|
||||||
@ -136,8 +142,8 @@
|
|||||||
:to="item.link"
|
:to="item.link"
|
||||||
:class="[
|
:class="[
|
||||||
hasActiveUrl(item.link)
|
hasActiveUrl(item.link)
|
||||||
? 'text-primary-500 border-primary-500 bg-gray-100 '
|
? 'text-primary-500 border-primary-500 bg-gray-100 dark:border-primary-400 dark:shadow-glass dark:backdrop-blur-xl dark:hover:bg-gray-700 dark:bg-gray-700/50 dark:text-primary-400 dark:font-medium'
|
||||||
: 'text-black',
|
: 'text-black dark:hover:bg-transparent dark:hover:text-white dark:text-gray-300',
|
||||||
'cursor-pointer px-0 pl-6 hover:bg-gray-50 py-3 group flex items-center border-l-4 border-solid border-transparent text-sm not-italic font-medium',
|
'cursor-pointer px-0 pl-6 hover:bg-gray-50 py-3 group flex items-center border-l-4 border-solid border-transparent text-sm not-italic font-medium',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
@ -145,8 +151,8 @@
|
|||||||
:name="item.icon"
|
:name="item.icon"
|
||||||
:class="[
|
:class="[
|
||||||
hasActiveUrl(item.link)
|
hasActiveUrl(item.link)
|
||||||
? 'text-primary-500 group-hover:text-primary-500 '
|
? 'text-primary-500 group-hover:text-primary-500 dark:text-primary-400 dark:group-hover:text-primary-500 '
|
||||||
: 'text-gray-400 group-hover:text-black',
|
: 'text-gray-400 group-hover:text-black dark:text-gray-400 dark:group-hover:text-white',
|
||||||
'mr-4 shrink-0 h-5 w-5 ',
|
'mr-4 shrink-0 h-5 w-5 ',
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
@ -154,6 +160,9 @@
|
|||||||
{{ $t(item.title) }}
|
{{ $t(item.title) }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
<LightDarkSwitch
|
||||||
|
class="absolute bottom-0 py-4 border-t border-gray-200 dark:border-gray-700"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -169,6 +178,7 @@ import {
|
|||||||
|
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { useGlobalStore } from '@/scripts/admin/stores/global'
|
import { useGlobalStore } from '@/scripts/admin/stores/global'
|
||||||
|
import LightDarkSwitch from '@/scripts/components/LightDarkSwitcher.vue'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const globalStore = useGlobalStore()
|
const globalStore = useGlobalStore()
|
||||||
|
|||||||
@ -184,6 +184,20 @@ export const useCompanyStore = (useWindow = false) => {
|
|||||||
setDefaultCurrency(data) {
|
setDefaultCurrency(data) {
|
||||||
this.defaultCurrency = data.currency
|
this.defaultCurrency = data.currency
|
||||||
},
|
},
|
||||||
|
|
||||||
|
checkCompanyHasCurrencyTransactions() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
axios
|
||||||
|
.get(`/api/v1/company/has-transactions`)
|
||||||
|
.then((response) => {
|
||||||
|
resolve(response)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
handleError(err)
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@ export const useGlobalStore = (useWindow = false) => {
|
|||||||
isAppLoaded: false,
|
isAppLoaded: false,
|
||||||
isSidebarOpen: false,
|
isSidebarOpen: false,
|
||||||
areCurrenciesLoading: false,
|
areCurrenciesLoading: false,
|
||||||
|
isDarkModeOn: false,
|
||||||
|
|
||||||
downloadReport: null,
|
downloadReport: null,
|
||||||
}),
|
}),
|
||||||
@ -70,8 +71,8 @@ export const useGlobalStore = (useWindow = false) => {
|
|||||||
moduleStore.apiToken = response.data.global_settings.api_token
|
moduleStore.apiToken = response.data.global_settings.api_token
|
||||||
moduleStore.enableModules = response.data.modules
|
moduleStore.enableModules = response.data.modules
|
||||||
|
|
||||||
// company store
|
// company store
|
||||||
companyStore.companies = response.data.companies
|
companyStore.companies = response.data.companies
|
||||||
companyStore.selectedCompany = response.data.current_company
|
companyStore.selectedCompany = response.data.current_company
|
||||||
companyStore.setSelectedCompany(response.data.current_company)
|
companyStore.setSelectedCompany(response.data.current_company)
|
||||||
companyStore.selectedCompanySettings =
|
companyStore.selectedCompanySettings =
|
||||||
|
|||||||
@ -2,8 +2,23 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
v-if="dashboardStore.isDashboardDataLoaded"
|
v-if="dashboardStore.isDashboardDataLoaded"
|
||||||
class="grid grid-cols-10 mt-8 bg-white rounded shadow"
|
class="
|
||||||
|
grid
|
||||||
|
grid-cols-10
|
||||||
|
mt-8
|
||||||
|
bg-white
|
||||||
|
rounded shadow
|
||||||
|
dark:text-white
|
||||||
|
dark:backdrop-blur-xl
|
||||||
|
dark:shadow-glass
|
||||||
|
dark:border
|
||||||
|
dark:bg-opacity-70
|
||||||
|
dark:border-white/10
|
||||||
|
dark:bg-gray-800
|
||||||
|
relative
|
||||||
|
"
|
||||||
>
|
>
|
||||||
|
<BaseDarkHighlight />
|
||||||
<!-- Chart -->
|
<!-- Chart -->
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
@ -54,6 +69,7 @@
|
|||||||
lg:border-t-0 lg:text-right lg:col-span-3
|
lg:border-t-0 lg:text-right lg:col-span-3
|
||||||
xl:col-span-2
|
xl:col-span-2
|
||||||
lg:grid-cols-1
|
lg:grid-cols-1
|
||||||
|
dark:border-white/10
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div class="p-6">
|
<div class="p-6">
|
||||||
@ -96,15 +112,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<br />
|
<br />
|
||||||
<span
|
<span
|
||||||
class="
|
class="block mt-1 text-xl font-semibold leading-8 lg:text-2xl text-red-400"
|
||||||
block
|
|
||||||
mt-1
|
|
||||||
text-xl
|
|
||||||
font-semibold
|
|
||||||
leading-8
|
|
||||||
lg:text-2xl
|
|
||||||
text-red-400
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<BaseFormatMoney
|
<BaseFormatMoney
|
||||||
:amount="dashboardStore.totalExpenses"
|
:amount="dashboardStore.totalExpenses"
|
||||||
@ -116,8 +124,10 @@
|
|||||||
class="
|
class="
|
||||||
col-span-3
|
col-span-3
|
||||||
p-6
|
p-6
|
||||||
border-t border-gray-200 border-solid
|
border-t
|
||||||
|
border-gray-200 border-solid
|
||||||
lg:col-span-1
|
lg:col-span-1
|
||||||
|
dark:border-white/10
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<span class="text-xs leading-5 lg:text-sm">
|
<span class="text-xs leading-5 lg:text-sm">
|
||||||
@ -132,7 +142,7 @@
|
|||||||
font-semibold
|
font-semibold
|
||||||
leading-8
|
leading-8
|
||||||
lg:text-2xl
|
lg:text-2xl
|
||||||
text-primary-500
|
text-primary-500 dark:text-primary-400
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<BaseFormatMoney
|
<BaseFormatMoney
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<BaseContentPlaceholders
|
<BaseContentPlaceholders
|
||||||
class="grid grid-cols-10 mt-8 bg-white rounded shadow"
|
class="grid grid-cols-10 mt-8 bg-white rounded shadow dark:bg-gray-800"
|
||||||
>
|
>
|
||||||
<!-- Chart -->
|
<!-- Chart -->
|
||||||
<div
|
<div
|
||||||
@ -29,6 +29,7 @@
|
|||||||
text-center
|
text-center
|
||||||
border-t border-l border-gray-200 border-solid
|
border-t border-l border-gray-200 border-solid
|
||||||
lg:border-t-0 lg:text-right lg:col-span-3
|
lg:border-t-0 lg:text-right lg:col-span-3
|
||||||
|
dark:border-gray-600
|
||||||
xl:col-span-2
|
xl:col-span-2
|
||||||
lg:grid-cols-1
|
lg:grid-cols-1
|
||||||
"
|
"
|
||||||
@ -77,6 +78,7 @@
|
|||||||
col-span-3
|
col-span-3
|
||||||
p-6
|
p-6
|
||||||
border-t border-gray-200 border-solid
|
border-t border-gray-200 border-solid
|
||||||
|
dark:border-gray-600
|
||||||
lg:justify-end lg:items-end lg:col-span-1
|
lg:justify-end lg:items-end lg:col-span-1
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
|||||||
@ -12,18 +12,24 @@
|
|||||||
hover:bg-gray-50
|
hover:bg-gray-50
|
||||||
xl:p-4
|
xl:p-4
|
||||||
lg:col-span-2
|
lg:col-span-2
|
||||||
|
dark:backdrop-blur-xl
|
||||||
|
dark:shadow-glass
|
||||||
|
dark:border
|
||||||
|
dark:border-white/10
|
||||||
|
dark:bg-gray-800/70
|
||||||
"
|
"
|
||||||
:class="{ 'lg:!col-span-3': large }"
|
:class="{ 'lg:!col-span-3': large }"
|
||||||
:to="route"
|
:to="route"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<span class="text-xl font-semibold leading-tight text-black xl:text-3xl">
|
<span class="text-xl font-semibold leading-tight text-black xl:text-3xl dark:text-white">
|
||||||
<slot />
|
<slot />
|
||||||
</span>
|
</span>
|
||||||
<span class="block mt-1 text-sm leading-tight text-gray-500 xl:text-lg">
|
<span class="block mt-1 text-sm leading-tight text-gray-500 xl:text-lg dark:text-gray-300">
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<BaseDarkHighlight class="!bg-highlight/[.17] !top-5" />
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<component :is="iconComponent" class="w-10 h-10 xl:w-12 xl:h-12" />
|
<component :is="iconComponent" class="w-10 h-10 xl:w-12 xl:h-12" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<BaseContentPlaceholders
|
<BaseContentPlaceholders
|
||||||
:rounded="true"
|
:rounded="true"
|
||||||
class="relative flex justify-between w-full p-3 bg-white rounded shadow lg:col-span-3 xl:p-4"
|
class="relative flex justify-between w-full p-3 bg-white rounded shadow lg:col-span-3 xl:p-4 dark:bg-gray-800"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<BaseContentPlaceholdersText
|
<BaseContentPlaceholdersText
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
shadow
|
shadow
|
||||||
lg:col-span-2
|
lg:col-span-2
|
||||||
xl:p-4
|
xl:p-4
|
||||||
|
dark:bg-gray-800
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -130,6 +130,7 @@
|
|||||||
mt-5
|
mt-5
|
||||||
list-none
|
list-none
|
||||||
border-b-2 border-gray-200 border-solid
|
border-b-2 border-gray-200 border-solid
|
||||||
|
dark:border-gray-600
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<!-- Tabs -->
|
<!-- Tabs -->
|
||||||
|
|||||||
@ -32,6 +32,8 @@
|
|||||||
:content-loading="isLoading"
|
:content-loading="isLoading"
|
||||||
:calendar-button="true"
|
:calendar-button="true"
|
||||||
calendar-button-icon="calendar"
|
calendar-button-icon="calendar"
|
||||||
|
:show-extra-options="true"
|
||||||
|
:source-date="estimateStore.newEstimate.estimate_date"
|
||||||
/>
|
/>
|
||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,24 @@
|
|||||||
/>
|
/>
|
||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
|
|
||||||
|
<BaseInputGroup
|
||||||
|
:label="$tc('wizard.company_slug')"
|
||||||
|
:help-text="$t('wizard.company_slug_help_text')"
|
||||||
|
:error="
|
||||||
|
v$.companyForm.slug.$error &&
|
||||||
|
v$.companyForm.slug.$errors[0].$message
|
||||||
|
"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<BaseInput
|
||||||
|
v-model="companyForm.slug"
|
||||||
|
:invalid="v$.companyForm.slug.$error"
|
||||||
|
type="text"
|
||||||
|
name="slug"
|
||||||
|
@input="v$.companyForm.slug.$touch()"
|
||||||
|
/>
|
||||||
|
</BaseInputGroup>
|
||||||
|
|
||||||
<BaseInputGroup
|
<BaseInputGroup
|
||||||
:label="$t('wizard.country')"
|
:label="$t('wizard.country')"
|
||||||
:error="
|
:error="
|
||||||
@ -57,9 +75,7 @@
|
|||||||
track-by="name"
|
track-by="name"
|
||||||
/>
|
/>
|
||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6">
|
|
||||||
<BaseInputGroup :label="$t('wizard.state')">
|
<BaseInputGroup :label="$t('wizard.state')">
|
||||||
<BaseInput
|
<BaseInput
|
||||||
v-model="companyForm.address.state"
|
v-model="companyForm.address.state"
|
||||||
@ -144,9 +160,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, reactive } from 'vue'
|
import { ref, computed, onMounted, reactive, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { required, maxLength, helpers } from '@vuelidate/validators'
|
import { required, minLength, maxLength, helpers } from '@vuelidate/validators'
|
||||||
import { useVuelidate } from '@vuelidate/core'
|
import { useVuelidate } from '@vuelidate/core'
|
||||||
import { useGlobalStore } from '@/scripts/admin/stores/global'
|
import { useGlobalStore } from '@/scripts/admin/stores/global'
|
||||||
import { useCompanyStore } from '@/scripts/admin/stores/company'
|
import { useCompanyStore } from '@/scripts/admin/stores/company'
|
||||||
@ -162,6 +178,7 @@ let logoFileName = ref(null)
|
|||||||
|
|
||||||
const companyForm = reactive({
|
const companyForm = reactive({
|
||||||
name: null,
|
name: null,
|
||||||
|
slug: null,
|
||||||
address: {
|
address: {
|
||||||
address_street_1: '',
|
address_street_1: '',
|
||||||
address_street_2: '',
|
address_street_2: '',
|
||||||
@ -188,10 +205,28 @@ onMounted(async () => {
|
|||||||
})?.id
|
})?.id
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const slugValidator = (value) => {
|
||||||
|
return value == slugify(value)
|
||||||
|
}
|
||||||
const rules = {
|
const rules = {
|
||||||
companyForm: {
|
companyForm: {
|
||||||
name: {
|
name: {
|
||||||
required: helpers.withMessage(t('validation.required'), required),
|
required: helpers.withMessage(t('validation.required'), required),
|
||||||
|
minLength: helpers.withMessage(
|
||||||
|
t('validation.name_min_length', { count: 3 }),
|
||||||
|
minLength(3)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
slug: {
|
||||||
|
required: helpers.withMessage(t('validation.required'), required),
|
||||||
|
minLength: helpers.withMessage(
|
||||||
|
t('validation.name_min_length', { count: 3 }),
|
||||||
|
minLength(3)
|
||||||
|
),
|
||||||
|
slugValidator: helpers.withMessage(
|
||||||
|
t('validation.invalid_slug'),
|
||||||
|
slugValidator
|
||||||
|
),
|
||||||
},
|
},
|
||||||
address: {
|
address: {
|
||||||
country_id: {
|
country_id: {
|
||||||
@ -249,4 +284,24 @@ async function next() {
|
|||||||
emit('next', 7)
|
emit('next', 7)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// watcher for if change company name then auto fill company slug value
|
||||||
|
watch(
|
||||||
|
() => companyForm.name,
|
||||||
|
(currentValue) => {
|
||||||
|
companyForm.slug = slugify(currentValue)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
function slugify(string) {
|
||||||
|
return string
|
||||||
|
.toString()
|
||||||
|
.trim()
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, '-')
|
||||||
|
.replace(/[^\w\-]+/g, '')
|
||||||
|
.replace(/\-\-+/g, '-')
|
||||||
|
.replace(/^-+/, '')
|
||||||
|
.replace(/-+$/, '')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -56,7 +56,7 @@
|
|||||||
<BaseMultiselect
|
<BaseMultiselect
|
||||||
v-model="filters.status"
|
v-model="filters.status"
|
||||||
:groups="true"
|
:groups="true"
|
||||||
:options="status"
|
:options="invoiceStatus"
|
||||||
searchable
|
searchable
|
||||||
:placeholder="$t('general.select_a_status')"
|
:placeholder="$t('general.select_a_status')"
|
||||||
@update:modelValue="setActiveTab"
|
@update:modelValue="setActiveTab"
|
||||||
@ -127,14 +127,31 @@
|
|||||||
mt-5
|
mt-5
|
||||||
list-none
|
list-none
|
||||||
border-b-2 border-gray-200 border-solid
|
border-b-2 border-gray-200 border-solid
|
||||||
|
dark:border-gray-600
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<!-- Tabs -->
|
<!-- Tabs -->
|
||||||
<BaseTabGroup class="-mb-5" @change="setStatusFilter">
|
<BaseTabGroup
|
||||||
<BaseTab :title="$t('general.all')" filter="" />
|
class="-mb-5"
|
||||||
<BaseTab :title="$t('general.draft')" filter="DRAFT" />
|
:selected-index="selectedIndex"
|
||||||
<BaseTab :title="$t('general.sent')" filter="SENT" />
|
@change="changeTabStatus"
|
||||||
<BaseTab :title="$t('general.due')" filter="DUE" />
|
>
|
||||||
|
<BaseTab
|
||||||
|
:title="invoiceTabStatus[0].title"
|
||||||
|
:tab-status="invoiceTabStatus[0].value"
|
||||||
|
/>
|
||||||
|
<BaseTab
|
||||||
|
:title="invoiceTabStatus[1].title"
|
||||||
|
:tab-status="invoiceTabStatus[1].value"
|
||||||
|
/>
|
||||||
|
<BaseTab
|
||||||
|
:title="invoiceTabStatus[2].title"
|
||||||
|
:tab-status="invoiceTabStatus[2].value"
|
||||||
|
/>
|
||||||
|
<BaseTab
|
||||||
|
:title="invoiceTabStatus[3].title"
|
||||||
|
:tab-status="invoiceTabStatus[3].value"
|
||||||
|
/>
|
||||||
</BaseTabGroup>
|
</BaseTabGroup>
|
||||||
|
|
||||||
<BaseDropdown
|
<BaseDropdown
|
||||||
@ -289,10 +306,10 @@ const utils = inject('$utils')
|
|||||||
const table = ref(null)
|
const table = ref(null)
|
||||||
const showFilters = ref(false)
|
const showFilters = ref(false)
|
||||||
|
|
||||||
const status = ref([
|
const invoiceStatus = ref([
|
||||||
{
|
{
|
||||||
label: 'Status',
|
label: 'Status',
|
||||||
options: ['DRAFT', 'DUE', 'SENT', 'VIEWED', 'COMPLETED'],
|
options: ['DRAFT', 'SENT', 'VIEWED', 'COMPLETED'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Paid Status',
|
label: 'Paid Status',
|
||||||
@ -300,10 +317,29 @@ const status = ref([
|
|||||||
},
|
},
|
||||||
,
|
,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const invoiceTabStatus = {
|
||||||
|
0: {
|
||||||
|
title: t('general.all'),
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
title: t('general.draft'),
|
||||||
|
value: 'DRAFT',
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
title: t('general.sent'),
|
||||||
|
value: 'SENT',
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
title: t('general.due'),
|
||||||
|
value: 'DUE',
|
||||||
|
},
|
||||||
|
}
|
||||||
const isRequestOngoing = ref(true)
|
const isRequestOngoing = ref(true)
|
||||||
const activeTab = ref('general.draft')
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
const selectedIndex = ref(0)
|
||||||
|
|
||||||
let filters = reactive({
|
let filters = reactive({
|
||||||
customer_id: '',
|
customer_id: '',
|
||||||
@ -311,6 +347,7 @@ let filters = reactive({
|
|||||||
from_date: '',
|
from_date: '',
|
||||||
to_date: '',
|
to_date: '',
|
||||||
invoice_number: '',
|
invoice_number: '',
|
||||||
|
tab_status: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
const showEmptyScreen = computed(
|
const showEmptyScreen = computed(
|
||||||
@ -401,6 +438,7 @@ async function fetchData({ page, filter, sort }) {
|
|||||||
from_date: filters.from_date,
|
from_date: filters.from_date,
|
||||||
to_date: filters.to_date,
|
to_date: filters.to_date,
|
||||||
invoice_number: filters.invoice_number,
|
invoice_number: filters.invoice_number,
|
||||||
|
tab_status: filters.tab_status,
|
||||||
orderByField: sort.fieldName || 'created_at',
|
orderByField: sort.fieldName || 'created_at',
|
||||||
orderBy: sort.order || 'desc',
|
orderBy: sort.order || 'desc',
|
||||||
page,
|
page,
|
||||||
@ -423,29 +461,9 @@ async function fetchData({ page, filter, sort }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setStatusFilter(val) {
|
function changeTabStatus(val, index) {
|
||||||
if (activeTab.value == val.title) {
|
filters.tab_status = val['tab-status']
|
||||||
return true
|
selectedIndex.value = index
|
||||||
}
|
|
||||||
|
|
||||||
activeTab.value = val.title
|
|
||||||
|
|
||||||
switch (val.title) {
|
|
||||||
case t('general.draft'):
|
|
||||||
filters.status = 'DRAFT'
|
|
||||||
break
|
|
||||||
case t('general.sent'):
|
|
||||||
filters.status = 'SENT'
|
|
||||||
break
|
|
||||||
|
|
||||||
case t('general.due'):
|
|
||||||
filters.status = 'DUE'
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
|
||||||
filters.status = ''
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setFilters() {
|
function setFilters() {
|
||||||
@ -463,8 +481,6 @@ function clearFilter() {
|
|||||||
filters.from_date = ''
|
filters.from_date = ''
|
||||||
filters.to_date = ''
|
filters.to_date = ''
|
||||||
filters.invoice_number = ''
|
filters.invoice_number = ''
|
||||||
|
|
||||||
activeTab.value = t('general.all')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function removeMultipleInvoices() {
|
async function removeMultipleInvoices() {
|
||||||
@ -505,39 +521,21 @@ function toggleFilter() {
|
|||||||
function setActiveTab(val) {
|
function setActiveTab(val) {
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 'DRAFT':
|
case 'DRAFT':
|
||||||
activeTab.value = t('general.draft')
|
selectedIndex.value = 1
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'SENT':
|
case 'SENT':
|
||||||
activeTab.value = t('general.sent')
|
case 'VIEWED':
|
||||||
break
|
|
||||||
|
|
||||||
case 'DUE':
|
|
||||||
activeTab.value = t('general.due')
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'COMPLETED':
|
case 'COMPLETED':
|
||||||
activeTab.value = t('invoices.completed')
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'PAID':
|
case 'PAID':
|
||||||
activeTab.value = t('invoices.paid')
|
selectedIndex.value = 2
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'UNPAID':
|
case 'UNPAID':
|
||||||
activeTab.value = t('invoices.unpaid')
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'PARTIALLY_PAID':
|
case 'PARTIALLY_PAID':
|
||||||
activeTab.value = t('invoices.partially_paid')
|
selectedIndex.value = 3
|
||||||
break
|
|
||||||
|
|
||||||
case 'VIEWED':
|
|
||||||
activeTab.value = t('invoices.viewed')
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
|
||||||
activeTab.value = t('general.all')
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
filters.tab_status = invoiceTabStatus[selectedIndex.value].value
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -32,6 +32,8 @@
|
|||||||
:content-loading="isLoading"
|
:content-loading="isLoading"
|
||||||
:calendar-button="true"
|
:calendar-button="true"
|
||||||
calendar-button-icon="calendar"
|
calendar-button-icon="calendar"
|
||||||
|
:show-extra-options="true"
|
||||||
|
:source-date="invoiceStore.newInvoice.invoice_date"
|
||||||
/>
|
/>
|
||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
|
|
||||||
|
|||||||
@ -82,9 +82,9 @@
|
|||||||
required
|
required
|
||||||
>
|
>
|
||||||
<BaseCustomerSelectInput
|
<BaseCustomerSelectInput
|
||||||
|
v-if="!isLoadingContent"
|
||||||
v-model="paymentStore.currentPayment.customer_id"
|
v-model="paymentStore.currentPayment.customer_id"
|
||||||
:content-loading="isLoadingContent"
|
:content-loading="isLoadingContent"
|
||||||
v-if="!isLoadingContent"
|
|
||||||
:invalid="v$.currentPayment.customer_id.$error"
|
:invalid="v$.currentPayment.customer_id.$error"
|
||||||
:placeholder="$t('customers.select_a_customer')"
|
:placeholder="$t('customers.select_a_customer')"
|
||||||
show-action
|
show-action
|
||||||
@ -423,7 +423,7 @@ function onCustomerChange(customer_id) {
|
|||||||
if (customer_id) {
|
if (customer_id) {
|
||||||
let data = {
|
let data = {
|
||||||
customer_id: customer_id,
|
customer_id: customer_id,
|
||||||
status: 'DUE',
|
tab_status: 'DUE',
|
||||||
limit: 'all',
|
limit: 'all',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +446,11 @@ function onCustomerChange(customer_id) {
|
|||||||
paymentStore.currentPayment.selectedCustomer = res2.data.data
|
paymentStore.currentPayment.selectedCustomer = res2.data.data
|
||||||
paymentStore.currentPayment.customer = res2.data.data
|
paymentStore.currentPayment.customer = res2.data.data
|
||||||
paymentStore.currentPayment.currency = res2.data.data.currency
|
paymentStore.currentPayment.currency = res2.data.data.currency
|
||||||
if(isEdit.value && !customerStore.editCustomer && paymentStore.currentPayment.customer_id) {
|
if (
|
||||||
|
isEdit.value &&
|
||||||
|
!customerStore.editCustomer &&
|
||||||
|
paymentStore.currentPayment.customer_id
|
||||||
|
) {
|
||||||
customerStore.editCustomer = res2.data.data
|
customerStore.editCustomer = res2.data.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -121,6 +121,7 @@
|
|||||||
mt-5
|
mt-5
|
||||||
list-none
|
list-none
|
||||||
border-b-2 border-gray-200 border-solid
|
border-b-2 border-gray-200 border-solid
|
||||||
|
dark:border-gray-600
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<!-- Tabs -->
|
<!-- Tabs -->
|
||||||
|
|||||||
@ -51,14 +51,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<BaseDropdownItem @click="onDownloadBckup(row.data)">
|
<BaseDropdownItem v-slot="slotProps" @click="onDownloadBckup(row.data)">
|
||||||
<BaseIcon name="CloudDownloadIcon" class="mr-3 text-gray-600" />
|
<BaseIcon name="CloudDownloadIcon" :class="slotProps.class" />
|
||||||
|
|
||||||
{{ $t('general.download') }}
|
{{ $t('general.download') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|
||||||
<BaseDropdownItem @click="onRemoveBackup(row.data)">
|
<BaseDropdownItem v-slot="slotProps" @click="onRemoveBackup(row.data)">
|
||||||
<BaseIcon name="TrashIcon" class="mr-3 text-gray-600" />
|
<BaseIcon name="TrashIcon" :class="slotProps.class" />
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
</BaseDropdown>
|
</BaseDropdown>
|
||||||
|
|||||||
@ -28,6 +28,19 @@
|
|||||||
/>
|
/>
|
||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
|
|
||||||
|
<BaseInputGroup
|
||||||
|
:label="$tc('settings.company_info.company_slug')"
|
||||||
|
:help-text="$t('settings.company_info.company_slug_help_text')"
|
||||||
|
:error="v$.slug.$error && v$.slug.$errors[0].$message"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<BaseInput
|
||||||
|
v-model="companyForm.slug"
|
||||||
|
:invalid="v$.slug.$error"
|
||||||
|
@blur="v$.slug.$touch()"
|
||||||
|
/>
|
||||||
|
</BaseInputGroup>
|
||||||
|
|
||||||
<BaseInputGroup :label="$tc('settings.company_info.phone')">
|
<BaseInputGroup :label="$tc('settings.company_info.phone')">
|
||||||
<BaseInput v-model="companyForm.address.phone" />
|
<BaseInput v-model="companyForm.address.phone" />
|
||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
@ -100,10 +113,10 @@
|
|||||||
|
|
||||||
<div v-if="companyStore.companies.length !== 1" class="py-5">
|
<div v-if="companyStore.companies.length !== 1" class="py-5">
|
||||||
<BaseDivider class="my-4" />
|
<BaseDivider class="my-4" />
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-white">
|
||||||
{{ $tc('settings.company_info.delete_company') }}
|
{{ $tc('settings.company_info.delete_company') }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="mt-2 max-w-xl text-sm text-gray-500">
|
<div class="mt-2 max-w-xl text-sm text-gray-500 dark:text-gray-400">
|
||||||
<p>
|
<p>
|
||||||
{{ $tc('settings.company_info.delete_company_description') }}
|
{{ $tc('settings.company_info.delete_company_description') }}
|
||||||
</p>
|
</p>
|
||||||
@ -160,6 +173,7 @@ let isSaving = ref(false)
|
|||||||
|
|
||||||
const companyForm = reactive({
|
const companyForm = reactive({
|
||||||
name: null,
|
name: null,
|
||||||
|
slug: null,
|
||||||
logo: null,
|
logo: null,
|
||||||
address: {
|
address: {
|
||||||
address_street_1: '',
|
address_street_1: '',
|
||||||
@ -193,7 +207,14 @@ const rules = computed(() => {
|
|||||||
name: {
|
name: {
|
||||||
required: helpers.withMessage(t('validation.required'), required),
|
required: helpers.withMessage(t('validation.required'), required),
|
||||||
minLength: helpers.withMessage(
|
minLength: helpers.withMessage(
|
||||||
t('validation.name_min_length'),
|
t('validation.name_min_length', { count: 3 }),
|
||||||
|
minLength(3)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
slug: {
|
||||||
|
required: helpers.withMessage(t('validation.required'), required),
|
||||||
|
minLength: helpers.withMessage(
|
||||||
|
t('validation.name_min_length', { count: 3 }),
|
||||||
minLength(3)
|
minLength(3)
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
{{ $t('settings.menu_title.exchange_rate') }}
|
{{ $t('settings.menu_title.exchange_rate') }}
|
||||||
</h6>
|
</h6>
|
||||||
<p
|
<p
|
||||||
class="mt-2 text-sm leading-snug text-left text-gray-500"
|
class="mt-2 text-sm leading-snug text-left text-gray-500 dark:text-gray-400"
|
||||||
style="max-width: 680px"
|
style="max-width: 680px"
|
||||||
>
|
>
|
||||||
{{ $t('settings.exchange_rate.providers_description') }}
|
{{ $t('settings.exchange_rate.providers_description') }}
|
||||||
|
|||||||
@ -45,27 +45,30 @@
|
|||||||
|
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="!row.data.set_as_default"
|
v-if="!row.data.set_as_default"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="setDefaultDiskData(row.data.id)"
|
@click="setDefaultDiskData(row.data.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon class="mr-3 tetx-gray-600" name="CheckCircleIcon" />
|
<BaseIcon :class="slotProps.class" name="CheckCircleIcon" />
|
||||||
|
|
||||||
{{ $t('settings.disk.set_default_disk') }}
|
{{ $t('settings.disk.set_default_disk') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="row.data.type !== 'SYSTEM'"
|
v-if="row.data.type !== 'SYSTEM'"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="openEditDiskModal(row.data)"
|
@click="openEditDiskModal(row.data)"
|
||||||
>
|
>
|
||||||
<BaseIcon name="PencilIcon" class="mr-3 text-gray-600" />
|
<BaseIcon name="PencilIcon" :class="slotProps.class" />
|
||||||
|
|
||||||
{{ $t('general.edit') }}
|
{{ $t('general.edit') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
|
|
||||||
<BaseDropdownItem
|
<BaseDropdownItem
|
||||||
v-if="row.data.type !== 'SYSTEM' && !row.data.set_as_default"
|
v-if="row.data.type !== 'SYSTEM' && !row.data.set_as_default"
|
||||||
|
v-slot="slotProps"
|
||||||
@click="removeDisk(row.data.id)"
|
@click="removeDisk(row.data.id)"
|
||||||
>
|
>
|
||||||
<BaseIcon name="TrashIcon" class="mr-3 text-gray-600" />
|
<BaseIcon name="TrashIcon" :class="slotProps.class" />
|
||||||
{{ $t('general.delete') }}
|
{{ $t('general.delete') }}
|
||||||
</BaseDropdownItem>
|
</BaseDropdownItem>
|
||||||
</BaseDropdown>
|
</BaseDropdown>
|
||||||
|
|||||||
@ -8,7 +8,11 @@
|
|||||||
<BaseInputGroup
|
<BaseInputGroup
|
||||||
:content-loading="isFetchingInitialData"
|
:content-loading="isFetchingInitialData"
|
||||||
:label="$tc('settings.preferences.currency')"
|
:label="$tc('settings.preferences.currency')"
|
||||||
:help-text="$t('settings.preferences.company_currency_unchangeable')"
|
:help-text="
|
||||||
|
isCurrencyDisabled
|
||||||
|
? $t('settings.preferences.company_currency_unchangeable')
|
||||||
|
: ''
|
||||||
|
"
|
||||||
:error="v$.currency.$error && v$.currency.$errors[0].$message"
|
:error="v$.currency.$error && v$.currency.$errors[0].$message"
|
||||||
required
|
required
|
||||||
>
|
>
|
||||||
@ -21,7 +25,7 @@
|
|||||||
:searchable="true"
|
:searchable="true"
|
||||||
track-by="name"
|
track-by="name"
|
||||||
:invalid="v$.currency.$error"
|
:invalid="v$.currency.$error"
|
||||||
disabled
|
:disabled="isCurrencyDisabled"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
>
|
>
|
||||||
</BaseMultiselect>
|
</BaseMultiselect>
|
||||||
@ -187,6 +191,7 @@ const { t, tm } = useI18n()
|
|||||||
let isSaving = ref(false)
|
let isSaving = ref(false)
|
||||||
let isDataSaving = ref(false)
|
let isDataSaving = ref(false)
|
||||||
let isFetchingInitialData = ref(false)
|
let isFetchingInitialData = ref(false)
|
||||||
|
let isCurrencyDisabled = ref(true)
|
||||||
|
|
||||||
const settingsForm = reactive({ ...companyStore.selectedCompanySettings })
|
const settingsForm = reactive({ ...companyStore.selectedCompanySettings })
|
||||||
|
|
||||||
@ -282,10 +287,14 @@ setInitialData()
|
|||||||
async function setInitialData() {
|
async function setInitialData() {
|
||||||
isFetchingInitialData.value = true
|
isFetchingInitialData.value = true
|
||||||
Promise.all([
|
Promise.all([
|
||||||
|
companyStore.checkCompanyHasCurrencyTransactions(),
|
||||||
globalStore.fetchCurrencies(),
|
globalStore.fetchCurrencies(),
|
||||||
globalStore.fetchDateFormats(),
|
globalStore.fetchDateFormats(),
|
||||||
globalStore.fetchTimeZones(),
|
globalStore.fetchTimeZones(),
|
||||||
]).then(([res1]) => {
|
]).then(([res1]) => {
|
||||||
|
if (res1.data?.has_transactions == false) {
|
||||||
|
isCurrencyDisabled.value = false
|
||||||
|
}
|
||||||
isFetchingInitialData.value = false
|
isFetchingInitialData.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<h6 class="text-gray-900 text-lg font-medium">
|
<BaseHeading
|
||||||
{{ $t(`settings.customization.${type}s.${type}_number_format`) }}
|
type="heading-title"
|
||||||
</h6>
|
:subtitle="
|
||||||
<p class="mt-1 text-sm text-gray-500">
|
|
||||||
{{
|
|
||||||
$t(`settings.customization.${type}s.${type}_number_format_description`)
|
$t(`settings.customization.${type}s.${type}_number_format_description`)
|
||||||
}}
|
"
|
||||||
</p>
|
>
|
||||||
|
{{ $t(`settings.customization.${type}s.${type}_number_format`) }}
|
||||||
|
</BaseHeading>
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="w-full mt-6 table-fixed">
|
<table class="w-full mt-6 table-fixed">
|
||||||
@ -29,6 +29,7 @@
|
|||||||
leading-5
|
leading-5
|
||||||
text-left text-gray-700
|
text-left text-gray-700
|
||||||
border-t border-b border-gray-200 border-solid
|
border-t border-b border-gray-200 border-solid
|
||||||
|
dark:border-gray-600
|
||||||
"
|
"
|
||||||
></th>
|
></th>
|
||||||
<th
|
<th
|
||||||
@ -41,6 +42,7 @@
|
|||||||
leading-5
|
leading-5
|
||||||
text-left text-gray-700
|
text-left text-gray-700
|
||||||
border-t border-b border-gray-200 border-solid
|
border-t border-b border-gray-200 border-solid
|
||||||
|
dark:text-gray-300 dark:border-gray-600
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Component
|
Component
|
||||||
@ -55,6 +57,7 @@
|
|||||||
leading-5
|
leading-5
|
||||||
text-left text-gray-700
|
text-left text-gray-700
|
||||||
border-t border-b border-gray-200 border-solid
|
border-t border-b border-gray-200 border-solid
|
||||||
|
dark:text-gray-300 dark:border-gray-600
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Parameter
|
Parameter
|
||||||
@ -69,13 +72,14 @@
|
|||||||
leading-5
|
leading-5
|
||||||
text-left text-gray-700
|
text-left text-gray-700
|
||||||
border-t border-b border-gray-200 border-solid
|
border-t border-b border-gray-200 border-solid
|
||||||
|
dark:border-gray-600
|
||||||
"
|
"
|
||||||
></th>
|
></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<draggable
|
<draggable
|
||||||
v-model="selectedFields"
|
v-model="selectedFields"
|
||||||
class="divide-y divide-gray-200"
|
class="divide-y divide-gray-200 dark:divide-gray-600"
|
||||||
item-key="id"
|
item-key="id"
|
||||||
tag="tbody"
|
tag="tbody"
|
||||||
handle=".handle"
|
handle=".handle"
|
||||||
@ -97,12 +101,13 @@
|
|||||||
whitespace-nowrap
|
whitespace-nowrap
|
||||||
mr-2
|
mr-2
|
||||||
min-w-[200px]
|
min-w-[200px]
|
||||||
|
dark:text-primary-400
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ element.label }}
|
{{ element.label }}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<p class="text-xs text-gray-500 mt-1">
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">
|
||||||
{{ element.description }}
|
{{ element.description }}
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<h6 class="text-gray-900 text-lg font-medium">
|
<BaseHeading
|
||||||
|
type="heading-title"
|
||||||
|
:subtitle="
|
||||||
|
$t('settings.customization.estimates.convert_estimate_description')
|
||||||
|
"
|
||||||
|
>
|
||||||
{{ $tc('settings.customization.estimates.convert_estimate_options') }}
|
{{ $tc('settings.customization.estimates.convert_estimate_options') }}
|
||||||
</h6>
|
</BaseHeading>
|
||||||
<p class="mt-1 text-sm text-gray-500">
|
|
||||||
{{ $t('settings.customization.estimates.convert_estimate_description') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<BaseInputGroup required>
|
<BaseInputGroup required>
|
||||||
<BaseRadio
|
<BaseRadio
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="submitForm">
|
<form @submit.prevent="submitForm">
|
||||||
<h6 class="text-gray-900 text-lg font-medium">
|
<BaseHeading
|
||||||
|
type="heading-title"
|
||||||
|
:subtitle="
|
||||||
|
$t('settings.customization.estimates.default_formats_description')
|
||||||
|
"
|
||||||
|
>
|
||||||
{{ $t('settings.customization.estimates.default_formats') }}
|
{{ $t('settings.customization.estimates.default_formats') }}
|
||||||
</h6>
|
</BaseHeading>
|
||||||
<p class="mt-1 text-sm text-gray-500 mb-2">
|
|
||||||
{{ $t('settings.customization.estimates.default_formats_description') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<BaseInputGroup
|
<BaseInputGroup
|
||||||
:label="
|
:label="
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="submitForm">
|
<form @submit.prevent="submitForm">
|
||||||
<h6 class="text-gray-900 text-lg font-medium">
|
<BaseHeading
|
||||||
|
type="heading-title"
|
||||||
|
:subtitle="
|
||||||
|
$t('settings.customization.estimates.expiry_date_description')
|
||||||
|
"
|
||||||
|
>
|
||||||
{{ $t('settings.customization.estimates.expiry_date') }}
|
{{ $t('settings.customization.estimates.expiry_date') }}
|
||||||
</h6>
|
</BaseHeading>
|
||||||
<p class="mt-1 text-sm text-gray-500 mb-2">
|
|
||||||
{{ $t('settings.customization.estimates.expiry_date_description') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<BaseSwitchSection
|
<BaseSwitchSection
|
||||||
v-model="expiryDateAutoField"
|
v-model="expiryDateAutoField"
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="submitForm">
|
<form @submit.prevent="submitForm">
|
||||||
<h6 class="text-gray-900 text-lg font-medium">
|
<BaseHeading
|
||||||
|
type="heading-title"
|
||||||
|
:subtitle="
|
||||||
|
$t('settings.customization.invoices.default_formats_description')
|
||||||
|
"
|
||||||
|
>
|
||||||
{{ $t('settings.customization.invoices.default_formats') }}
|
{{ $t('settings.customization.invoices.default_formats') }}
|
||||||
</h6>
|
</BaseHeading>
|
||||||
<p class="mt-1 text-sm text-gray-500 mb-2">
|
|
||||||
{{ $t('settings.customization.invoices.default_formats_description') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<BaseInputGroup
|
<BaseInputGroup
|
||||||
:label="$t('settings.customization.invoices.default_invoice_email_body')"
|
:label="$t('settings.customization.invoices.default_invoice_email_body')"
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="submitForm">
|
<form @submit.prevent="submitForm">
|
||||||
<h6 class="text-gray-900 text-lg font-medium">
|
<BaseHeading
|
||||||
{{ $t('settings.customization.invoices.due_date') }}
|
type="heading-title"
|
||||||
</h6>
|
:subtitle="
|
||||||
<p class="mt-1 text-sm text-gray-500 mb-2">
|
$t('settings.customization.invoices.due_date_description')
|
||||||
{{ $t('settings.customization.invoices.due_date_description') }}
|
"
|
||||||
</p>
|
>
|
||||||
|
{{ $t('settings.customization.invoices.due_date') }}
|
||||||
|
</BaseHeading>
|
||||||
|
|
||||||
<BaseSwitchSection
|
<BaseSwitchSection
|
||||||
v-model="dueDateAutoField"
|
v-model="dueDateAutoField"
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<h6 class="text-gray-900 text-lg font-medium">
|
<BaseHeading
|
||||||
|
type="heading-title"
|
||||||
|
:subtitle="
|
||||||
|
$t('settings.customization.invoices.retrospective_edits_description')
|
||||||
|
"
|
||||||
|
>
|
||||||
{{ $tc('settings.customization.invoices.retrospective_edits') }}
|
{{ $tc('settings.customization.invoices.retrospective_edits') }}
|
||||||
</h6>
|
</BaseHeading>
|
||||||
<p class="mt-1 text-sm text-gray-500">
|
|
||||||
{{ $t('settings.customization.invoices.retrospective_edits_description') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<BaseInputGroup required>
|
<BaseInputGroup required>
|
||||||
<BaseRadio
|
<BaseRadio
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="submitForm">
|
<form @submit.prevent="submitForm">
|
||||||
<h6 class="text-gray-900 text-lg font-medium">
|
<BaseHeading
|
||||||
|
type="heading-title"
|
||||||
|
:subtitle="
|
||||||
|
$t('settings.customization.payments.default_formats_description')
|
||||||
|
"
|
||||||
|
>
|
||||||
{{ $t('settings.customization.payments.default_formats') }}
|
{{ $t('settings.customization.payments.default_formats') }}
|
||||||
</h6>
|
</BaseHeading>
|
||||||
<p class="mt-1 text-sm text-gray-500 mb-2">
|
|
||||||
{{ $t('settings.customization.payments.default_formats_description') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<BaseInputGroup
|
<BaseInputGroup
|
||||||
:label="$t('settings.customization.payments.default_payment_email_body')"
|
:label="$t('settings.customization.payments.default_payment_email_body')"
|
||||||
|
|||||||
@ -1,21 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="companySwitchBar" class="relative rounded">
|
<div ref="companySwitchBar" class="relative rounded dark:text-white">
|
||||||
<CompanyModal />
|
<CompanyModal />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
justify-center
|
||||||
px-3
|
px-3
|
||||||
h-8
|
h-8
|
||||||
md:h-9
|
md:h-9
|
||||||
ml-2
|
ml-2
|
||||||
text-sm text-white
|
text-sm
|
||||||
bg-white
|
text-white
|
||||||
rounded
|
bg-white
|
||||||
cursor-pointer
|
rounded
|
||||||
bg-opacity-20
|
cursor-pointer
|
||||||
|
bg-opacity-20
|
||||||
|
dark:bg-gray-700
|
||||||
"
|
"
|
||||||
@click="isShow = !isShow"
|
@click="isShow = !isShow"
|
||||||
>
|
>
|
||||||
@ -38,28 +40,42 @@
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="isShow"
|
v-if="isShow"
|
||||||
class="absolute right-0 mt-2 bg-white rounded-md shadow-lg"
|
class="
|
||||||
|
absolute
|
||||||
|
right-0
|
||||||
|
mt-2
|
||||||
|
bg-white
|
||||||
|
rounded-md
|
||||||
|
shadow-lg
|
||||||
|
dark:border
|
||||||
|
dark:border-white/10
|
||||||
|
dark:text-white
|
||||||
|
dark:bg-gray-800/[.95]
|
||||||
|
dark:shadow-glass
|
||||||
|
dark:backdrop-blur-xl
|
||||||
|
"
|
||||||
>
|
>
|
||||||
|
<BaseDarkHighlight class="z-[-1] top-0 left-0" />
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
overflow-y-auto
|
overflow-y-auto
|
||||||
scrollbar-thin scrollbar-thumb-rounded-full
|
scrollbar-thin
|
||||||
w-[250px]
|
scrollbar-thumb-rounded-full
|
||||||
max-h-[350px]
|
w-[250px] max-h-[350px]
|
||||||
scrollbar-thumb-gray-300 scrollbar-track-gray-10
|
scrollbar-thumb-gray-300
|
||||||
pb-4
|
scrollbar-track-gray-10
|
||||||
|
pb-4
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="
|
class="
|
||||||
px-3
|
px-3
|
||||||
py-2
|
py-2
|
||||||
text-xs
|
text-xs
|
||||||
font-semibold
|
font-semibold
|
||||||
text-gray-400
|
text-gray-400
|
||||||
mb-0.5
|
mb-0.5
|
||||||
block
|
block uppercase
|
||||||
uppercase
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ $t('company_switcher.label') }}
|
{{ $t('company_switcher.label') }}
|
||||||
@ -68,13 +84,13 @@
|
|||||||
<div
|
<div
|
||||||
v-if="companyStore.companies.length < 1"
|
v-if="companyStore.companies.length < 1"
|
||||||
class="
|
class="
|
||||||
flex flex-col
|
flex flex-col
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
justify-center
|
||||||
p-2
|
p-2
|
||||||
px-3
|
px-3
|
||||||
mt-4
|
mt-4
|
||||||
text-base text-gray-400
|
text-base text-gray-400
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<BaseIcon name="ExclamationCircleIcon" class="h-5 text-gray-400" />
|
<BaseIcon name="ExclamationCircleIcon" class="h-5 text-gray-400" />
|
||||||
@ -86,14 +102,17 @@
|
|||||||
v-for="(company, index) in companyStore.companies"
|
v-for="(company, index) in companyStore.companies"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="
|
class="
|
||||||
p-2
|
p-2
|
||||||
px-3
|
px-3
|
||||||
rounded-md
|
rounded-md
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
hover:bg-gray-100 hover:text-primary-500
|
hover:bg-gray-100 hover:text-primary-500
|
||||||
|
dark:hover:bg-gray-700
|
||||||
|
text-gray-900
|
||||||
|
dark:text-white
|
||||||
"
|
"
|
||||||
:class="{
|
:class="{
|
||||||
'bg-gray-100 text-primary-500':
|
'bg-gray-100 text-primary-500 dark:bg-gray-700':
|
||||||
companyStore.selectedCompany.id === company.id,
|
companyStore.selectedCompany.id === company.id,
|
||||||
}"
|
}"
|
||||||
@click="changeCompany(company)"
|
@click="changeCompany(company)"
|
||||||
@ -101,18 +120,19 @@
|
|||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span
|
<span
|
||||||
class="
|
class="
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
justify-center
|
||||||
mr-3
|
mr-3
|
||||||
overflow-hidden
|
overflow-hidden
|
||||||
text-base
|
text-sm
|
||||||
font-semibold
|
font-semibold
|
||||||
bg-gray-200
|
bg-gray-200
|
||||||
rounded-md
|
rounded-md
|
||||||
w-9
|
w-9
|
||||||
h-9
|
h-9
|
||||||
text-primary-500
|
text-primary-500
|
||||||
|
dark:bg-gray-900
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<span v-if="!company.logo">
|
<span v-if="!company.logo">
|
||||||
@ -136,15 +156,17 @@
|
|||||||
<div
|
<div
|
||||||
v-if="userStore.currentUser.is_owner"
|
v-if="userStore.currentUser.is_owner"
|
||||||
class="
|
class="
|
||||||
flex
|
flex
|
||||||
items-center
|
items-center
|
||||||
justify-center
|
justify-center
|
||||||
p-4
|
p-4
|
||||||
pl-3
|
pl-3
|
||||||
border-t-2 border-gray-100
|
border-t-2
|
||||||
cursor-pointer
|
border-gray-100
|
||||||
text-primary-400
|
cursor-pointer
|
||||||
hover:text-primary-500
|
text-primary-400
|
||||||
|
hover:text-primary-500
|
||||||
|
dark:border-gray-600
|
||||||
"
|
"
|
||||||
@click="addNewCompany"
|
@click="addNewCompany"
|
||||||
>
|
>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="searchBar" class="hidden rounded md:block relative">
|
<div ref="searchBar" class="hidden rounded md:block relative dark:text-white">
|
||||||
<div>
|
<div>
|
||||||
<BaseInput
|
<BaseInput
|
||||||
v-model="name"
|
v-model="name"
|
||||||
@ -41,6 +41,11 @@
|
|||||||
w-[300px]
|
w-[300px]
|
||||||
h-[200px]
|
h-[200px]
|
||||||
right-0
|
right-0
|
||||||
|
dark:border-white/10
|
||||||
|
dark:text-white
|
||||||
|
dark:bg-gray-800/[.95]
|
||||||
|
dark:shadow-glass
|
||||||
|
dark:backdrop-blur-xl
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -68,7 +73,7 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(customer, index) in usersStore.customerList"
|
v-for="(customer, index) in usersStore.customerList"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="p-2 hover:bg-gray-100 cursor-pointer rounded-md"
|
class="p-2 hover:bg-gray-100 cursor-pointer rounded-md dark:hover:bg-gray-700/40"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ path: `/admin/customers/${customer.id}/view` }"
|
:to="{ path: `/admin/customers/${customer.id}/view` }"
|
||||||
@ -87,6 +92,7 @@
|
|||||||
bg-gray-200
|
bg-gray-200
|
||||||
rounded-full
|
rounded-full
|
||||||
text-primary-500
|
text-primary-500
|
||||||
|
dark:bg-gray-600
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ initGenerator(customer.name) }}
|
{{ initGenerator(customer.name) }}
|
||||||
@ -116,7 +122,7 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(user, index) in usersStore.userList"
|
v-for="(user, index) in usersStore.userList"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="p-2 hover:bg-gray-100 cursor-pointer rounded-md"
|
class="p-2 hover:bg-gray-100 cursor-pointer rounded-md dark:hover:bg-gray-700/40"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ path: `/admin/users/${user.id}/edit` }"
|
:to="{ path: `/admin/users/${user.id}/edit` }"
|
||||||
@ -135,6 +141,7 @@
|
|||||||
bg-gray-200
|
bg-gray-200
|
||||||
rounded-full
|
rounded-full
|
||||||
text-primary-500
|
text-primary-500
|
||||||
|
dark:bg-gray-600
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ initGenerator(user.name) }}
|
{{ initGenerator(user.name) }}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user