updating env example file
This commit is contained in:
parent
f96e7eb0aa
commit
74055ea11b
@ -1,3 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
composer require itsgoingd/clockwork enlightn/security-checker
|
||||
composer require --dev itsgoingd/clockwork enlightn/security-checker
|
||||
|
@ -1,10 +1,16 @@
|
||||
APP_NAME=Invoicer
|
||||
APP_NAME="App Name"
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:hSCTwZ507IdKQ5QJHJ+mQw0DSMgDdAspasjwHCdiB8Y=
|
||||
APP_DEBUG=true
|
||||
APP_URL=https://invoicer.test
|
||||
APP_DOMAIN=localhost
|
||||
APP_URL="https://${APP_DOMAIN}"
|
||||
APP_UID_BYTES=8
|
||||
|
||||
APP_JS_INTEGRITY_HASH=""
|
||||
GIT_HASH="00000000"
|
||||
GIT_TAG="x.x.x"
|
||||
GIT_BRANCH="master"
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
@ -12,7 +18,7 @@ LOG_LEVEL=debug
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=mariadb
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=invoicer_v3
|
||||
DB_DATABASE=database_name
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=root
|
||||
|
||||
@ -36,7 +42,7 @@ MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS=null
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
MAIL_FROM_NAME="no-reply@${APP_DOMAIN}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
|
43
src/app/Http/Requests/Users/StoreRequest.php
Normal file
43
src/app/Http/Requests/Users/StoreRequest.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Users;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @throws \JsonException
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
// Use this if you want to have some JSON be converted from a string to an object(?)
|
||||
//$this->merge(json_decode($this->payload, true, 512, JSON_THROW_ON_ERROR));
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Traits\HasUidTrait;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Prunable;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
||||
@ -11,6 +12,7 @@ use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Fortify\TwoFactorAuthenticatable;
|
||||
use Laravel\Jetstream\HasProfilePhoto;
|
||||
use Laravel\Jetstream\HasTeams;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
@ -119,28 +121,32 @@ class User extends Authenticatable
|
||||
|
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return the surname then (first)name separated by a comma.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFullNameAttribute(): string
|
||||
{
|
||||
return "{$this->surname}, {$this->name}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return both the (first)name and surname.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @return string
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function getNameFullAttribute(): string
|
||||
public function fullName(): Attribute
|
||||
{
|
||||
return "{$this->name} {$this->surname}";
|
||||
return Attribute::make(
|
||||
get: fn ($value, $attributes) => "{$attributes['name']} {$attributes['surname']}",
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the surname then (first)name separated by a comma.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
||||
*/
|
||||
public function fullNameReversed(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn ($value, $attributes) => "{$attributes['surname']}, {$attributes['name']}",
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
|
303
src/app/Support/Address.php
Normal file
303
src/app/Support/Address.php
Normal file
@ -0,0 +1,303 @@
|
||||
<?php
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
class Address
|
||||
{
|
||||
/* @var ?string */
|
||||
public ?string $street;
|
||||
|
||||
/* @var ?string */
|
||||
public ?string $unit;
|
||||
|
||||
/* @var ?string */
|
||||
public ?string $city;
|
||||
|
||||
/* @var ?string */
|
||||
public ?string $state;
|
||||
|
||||
/* @var ?string */
|
||||
public ?string $postalCode;
|
||||
|
||||
/* @var ?string */
|
||||
public ?string $country;
|
||||
|
||||
/**
|
||||
* The Address helpser constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $inputs
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $inputs): void
|
||||
{
|
||||
$this->processAddress($inputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process user inputs to our Address object.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $inputs
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function processAddress(array $inputs): void
|
||||
{
|
||||
// TODO: attempt to determine how the address is formulated
|
||||
// could be just numerical indexed, or could be
|
||||
// named keys but not sure of names
|
||||
|
||||
$this->street = $this->resolveStreet($inputs);
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Helpers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
|
||||
/**
|
||||
* Attempt to determine what the street address
|
||||
* is in the given data.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $inputs
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function resolveStreet(array $inputs): ?string
|
||||
{
|
||||
$street = '';
|
||||
if (array_key_exists('street', $inputs)) {
|
||||
$street = $inputs['street'];
|
||||
} elseif (array_key_exists('street_1', $inputs)) {
|
||||
$street = $inputs['street_1'];
|
||||
} elseif (array_key_exists('street_address', $inputs)) {
|
||||
$street = $inputs['street_address'];
|
||||
} elseif (array_key_exists('line_1', $inputs)) {
|
||||
$street = $inputs['line_1'];
|
||||
} elseif (! empty($inputs[0])) {
|
||||
$street = $inputs[0];
|
||||
} elseif (array_key_exists('0', $inputs)) {
|
||||
$street = $inputs['0'];
|
||||
}
|
||||
|
||||
if (empty($street)) {
|
||||
$street = null;
|
||||
}
|
||||
|
||||
return $street;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to determine what the street address
|
||||
* unit is in the given data.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $inputs
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function resolveUnit(array $inputs): ?string
|
||||
{
|
||||
$unit = null;
|
||||
if (array_key_exists('unit', $inputs)) {
|
||||
$unit = $inputs['unit'];
|
||||
} elseif (array_key_exists('street_2', $inputs)) {
|
||||
$unit = $inputs['street_2'];
|
||||
} elseif (array_key_exists('line_2', $inputs)) {
|
||||
$unit = $inputs['line_2'];
|
||||
} elseif (! empty($inputs[1])) {
|
||||
$unit = $inputs[1];
|
||||
} elseif (array_key_exists('1', $inputs)) {
|
||||
$unit = $inputs['1'];
|
||||
}
|
||||
|
||||
if (empty($unit)) {
|
||||
$unit = null;
|
||||
}
|
||||
|
||||
return $unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to determine what the city is in the given data.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $inputs
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function resolveCity(array $inputs): ?string
|
||||
{
|
||||
$city = '';
|
||||
if (array_key_exists('city', $inputs)) {
|
||||
$city = $inputs['city'];
|
||||
} elseif (array_key_exists(2, $inputs)) {
|
||||
$city = $inputs[2];
|
||||
} elseif (array_key_exists('2', $inputs)) {
|
||||
$city = $inputs['2'];
|
||||
}
|
||||
|
||||
if (empty($city)) {
|
||||
$city = null;
|
||||
}
|
||||
|
||||
return $city;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to determine what the state is in the given data.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $inputs
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function resolveState(array $inputs): ?string
|
||||
{
|
||||
$numericKey = 3;
|
||||
if (empty($this->unit)) {
|
||||
$numericKey--;
|
||||
}
|
||||
|
||||
$state = '';
|
||||
if (array_key_exists('state', $inputs)) {
|
||||
$state = $inputs['state'];
|
||||
} elseif (array_key_exists('st', $inputs)) {
|
||||
$state = $inputs['st'];
|
||||
} elseif (array_key_exists($numericKey, $inputs)) {
|
||||
$state = $inputs[$numericKey];
|
||||
} elseif (array_key_exists("$numericKey", $inputs)) {
|
||||
$state = $inputs["$numericKey"];
|
||||
}
|
||||
|
||||
if (empty($state)) {
|
||||
$state = null;
|
||||
}
|
||||
|
||||
return $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to determine what the postal code is in the given data.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $inputs
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function resolvePostalCode(array $inputs): ?string
|
||||
{
|
||||
$numericKey = 4;
|
||||
if (empty($this->unit)) {
|
||||
$numericKey--;
|
||||
}
|
||||
|
||||
$postalCode = '';
|
||||
if (array_key_exists('postal_code', $inputs)) {
|
||||
$postalCode = $inputs['postal_code'];
|
||||
} elseif (array_key_exists('postalCode', $inputs)) {
|
||||
$postalCode = $inputs['postalCode'];
|
||||
} elseif (array_key_exists('postal', $inputs)) {
|
||||
$postalCode = $inputs['postal'];
|
||||
} elseif (array_key_exists('zipcode', $inputs)) {
|
||||
$postalCode = $inputs['zipcode'];
|
||||
} elseif (array_key_exists('zip_code', $inputs)) {
|
||||
$postalCode = $inputs['zip_code'];
|
||||
} elseif (array_key_exists('zipCode', $inputs)) {
|
||||
$postalCode = $inputs['zipCode'];
|
||||
} elseif (array_key_exists('zip', $inputs)) {
|
||||
$postalCode = $inputs['zip'];
|
||||
} elseif (array_key_exists($numericKey, $inputs)) {
|
||||
$postalCode = $inputs[$numericKey];
|
||||
} elseif (array_key_exists("$numericKey", $inputs)) {
|
||||
$postalCode = $inputs["$numericKey"];
|
||||
}
|
||||
|
||||
if (empty($postalCode)) {
|
||||
$postalCode = null;
|
||||
}
|
||||
|
||||
return $postalCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to determine what the country is in the given data.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $inputs
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function resolveCountry(array $inputs): ?string
|
||||
{
|
||||
$numericKey = 5;
|
||||
if (empty($this->unit)) {
|
||||
$numericKey--;
|
||||
}
|
||||
|
||||
$country = '';
|
||||
if (array_key_exists('country', $inputs)) {
|
||||
$country = $inputs['country'];
|
||||
} elseif (array_key_exists('st', $inputs)) {
|
||||
$country = $inputs['st'];
|
||||
} elseif (array_key_exists($numericKey, $inputs)) {
|
||||
$country = $inputs[$numericKey];
|
||||
} elseif (array_key_exists("$numericKey", $inputs)) {
|
||||
$country = $inputs["$numericKey"];
|
||||
}
|
||||
|
||||
if (empty($country)) {
|
||||
$country = null;
|
||||
}
|
||||
|
||||
return $country;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to convert this object to a string.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
$fullAddress = $this->street;
|
||||
if (! empty($this->unit)) {
|
||||
$fullAddress .= " {$this->unit}";
|
||||
}
|
||||
|
||||
if (! empty($this->city)) {
|
||||
$fullAddress .= ", {$this->city}";
|
||||
}
|
||||
|
||||
if (! empty($this->state)) {
|
||||
$fullAddress .= ", {$this->state}";
|
||||
}
|
||||
|
||||
if (! empty($this->postalCode)) {
|
||||
$fullAddress .= $this->postalCode;
|
||||
}
|
||||
|
||||
if (! empty($this->country)) {
|
||||
$fullAddress .= ", {$this->country}";
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $fullAddress;
|
||||
}
|
||||
}
|
18
src/composer.json
Normal file
18
src/composer.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
//...
|
||||
"autoload": {
|
||||
//...
|
||||
"files": [
|
||||
"helpers/constants/cache_ttl.php",
|
||||
"helpers/constants/http_status_codes.php",
|
||||
"helpers/global_functions.php"
|
||||
]
|
||||
},
|
||||
//...
|
||||
"scripts": {
|
||||
"post-autoload-dump": [
|
||||
//...
|
||||
"@php artisan ziggy:generate --ansi"
|
||||
],
|
||||
},
|
||||
}
|
@ -22,12 +22,13 @@ class CreateAddressesTable extends Migration
|
||||
$table->string('state');
|
||||
$table->string('postal_code'); // leave as string to accomodate 12345-6789 or Canada
|
||||
$table->string('country')->default('United States');
|
||||
$table->float('latitude', 12, 9)->index()->nullable();
|
||||
$table->float('longitude', 12, 9)->index()->nullable();
|
||||
$table->float('latitude', 12, 9)->nullable();
|
||||
$table->float('longitude', 12, 9)->nullable();
|
||||
$table->point('location')->nullable();
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
$table->timestamp('updated_at')->nullable()->useCurrentOnUpdate();
|
||||
|
||||
$table->index(['latitude', 'longitude']);
|
||||
$table->spatialIndex('location');
|
||||
});
|
||||
}
|
||||
|
@ -5,6 +5,10 @@ define('CACHE_TTL_FIFTEEN_MINUTES', 900);
|
||||
|
||||
define('CACHE_TTL_HALF_HOUR', 1800);
|
||||
define('CACHE_TTL_ONE_HOUR', 3600);
|
||||
define('CACHE_TTL_TWO_HOURS', 7200);
|
||||
define('CACHE_TTL_THREE_HOURS', 10800);
|
||||
define('CACHE_TTL_SIX_HOURS', 21600);
|
||||
define('CACHE_TTL_TWELVE_HOURS', 43200);
|
||||
|
||||
define('CACHE_TTL_ONE_DAY', 86400);
|
||||
|
||||
|
@ -17,7 +17,16 @@ if (! function_exists('snake2Title')) {
|
||||
}
|
||||
|
||||
if (! function_exists('carbon')) {
|
||||
function carbon(?string $timestring = null)
|
||||
/**
|
||||
* Return a Carbon object based on a given timestring.
|
||||
* It will attempt to find a timezone in the current
|
||||
* session but default to UTC.
|
||||
*
|
||||
* @param string|null $timestring
|
||||
*
|
||||
* @return \Carbon\Carbon
|
||||
*/
|
||||
function carbon(?string $timestring = null): \Carbon\Carbon
|
||||
{
|
||||
$carbon = Carbon\Carbon::now(session('timezone_name'));
|
||||
if (! empty($timestring)) {
|
||||
@ -28,7 +37,15 @@ if (! function_exists('carbon')) {
|
||||
}
|
||||
|
||||
if (! function_exists('jddayofweek')) {
|
||||
function jddayofweek(?int $intDay = null, int $mode = 0)
|
||||
/**
|
||||
* Returns the day of the week. Can return a string or an integer depending on the mode.
|
||||
*
|
||||
* @param int|null $intDay
|
||||
* @param int $mode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function jddayofweek(?int $intDay = null, int $mode = 0): string
|
||||
{
|
||||
if (is_null($intDay)) {
|
||||
$intDay = date('l');
|
||||
@ -41,3 +58,108 @@ if (! function_exists('jddayofweek')) {
|
||||
return ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][$intDay];
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('cel2Fah')) {
|
||||
/**
|
||||
* Convert from celsius to fahrenheit.
|
||||
*
|
||||
* @param float|int|string $celsius
|
||||
* @param int $precision
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
function cel2Fah($celsius, int $preceision = 0): float
|
||||
{
|
||||
return round((($celsius * (9/5)) + 32), $preceision);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('fah2Cel')) {
|
||||
/**
|
||||
* Convert from fahrenheit to celsius.
|
||||
*
|
||||
* @param float|int|string $fahrenheit
|
||||
* @param int $precision
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
function fah2Cel($fahrenheit, int $preceision = 1): float
|
||||
{
|
||||
return round(($fahrenheit - 32 * (5/9)), $preceision);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('meters2Miles')) {
|
||||
/**
|
||||
* Convert from meters to miles.
|
||||
*
|
||||
* @param float|int|string $meters
|
||||
* @param int $precision
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
function meters2Miles($meters, int $preceision = 1): float
|
||||
{
|
||||
return round(($meters * 0.00062137), $preceision);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('kilometers2Miles')) {
|
||||
/**
|
||||
* Convert from kilometers to meters.
|
||||
*
|
||||
* @param float|int|string $kilometers
|
||||
* @param int $precision
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
function kilometers2Miles($kilometers, int $preceision = 1): float
|
||||
{
|
||||
return round(($kilometers * 1.609), $preceision);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('m2Km')) {
|
||||
/**
|
||||
* Convert from meters to kilometers.
|
||||
*
|
||||
* @param float|int|string $meters
|
||||
* @param int $precision
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
function m2Km($meters, int $preceision = 1): float
|
||||
{
|
||||
return round(($meters / 1000), $preceision);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('mm2Inches')) {
|
||||
/**
|
||||
* Convert from milimeters to inches.
|
||||
*
|
||||
* @param float|int|string $milimeters
|
||||
* @param int $precision
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
function mm2Inches($milimeters, int $preceision = 1): float
|
||||
{
|
||||
return round(($milimeters / 25.4), $preceision);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('pa2Mbar')) {
|
||||
/**
|
||||
* Convert from pascals to milibars.
|
||||
*
|
||||
* @param float|int|string $pascals
|
||||
* @param int $precision
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
function pa2Mbar($pascals, int $preceision = 1): float
|
||||
{
|
||||
return round(($pascals / 100), $preceision);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
.card {
|
||||
@apply flex flex-col nm-flat-white dark:nm-flat-gray-700 border border-gray-100 dark:border-gray-800 overflow-hidden rounded-lg;
|
||||
@apply flex flex-col bg-white dark:bg-zinc-700 border border-gray-100 dark:border-gray-800 overflow-hidden rounded-lg;
|
||||
}
|
||||
|
||||
.card .card-header {
|
||||
|
@ -25,7 +25,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
import { defineComponent, ref } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@ -35,10 +35,10 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
}
|
||||
setup(props) {
|
||||
let show = ref(false)
|
||||
|
||||
return { show }
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<NotificationGroup group="error">
|
||||
<div class="fixed inset-0 flex items-start justify-end p-6 px-4 py-6 pointer-events-none z-50">
|
||||
<div class="w-full max-w-sm">
|
||||
<Notification
|
||||
v-slot="{ notifications }"
|
||||
enter="transform ease-out duration-300 transition"
|
||||
enter-from="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-4"
|
||||
enter-to="translate-y-0 opacity-100 sm:translate-x-0"
|
||||
leave="transition ease-in duration-500"
|
||||
leave-from="opacity-100"
|
||||
leave-to="opacity-0"
|
||||
move="transition duration-500"
|
||||
move-delay="delay-300"
|
||||
>
|
||||
<div class="flex w-full max-w-sm mx-auto mt-4 overflow-hidden bg-white rounded-lg shadow-md border border-gray-200"
|
||||
v-for="notification in notifications"
|
||||
:key="notification.id"
|
||||
>
|
||||
<div class="flex items-center justify-center w-12 bg-red-500">
|
||||
<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="w-6 h-6 text-white">
|
||||
<polygon points="7.86 2 16.14 2 22 7.86 22 16.14 16.14 22 7.86 22 2 16.14 2 7.86 7.86 2"></polygon>
|
||||
<line x1="15" y1="9" x2="9" y2="15"></line>
|
||||
<line x1="9" y1="9" x2="15" y2="15"></line>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="px-4 py-2 -mx-3">
|
||||
<div class="mx-3">
|
||||
<span class="font-semibold text-red-500">{{ notification.title }}</span>
|
||||
<p class="text-sm text-gray-600">{{ notification.text }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Notification>
|
||||
</div>
|
||||
</div>
|
||||
</NotificationGroup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
import Notifications from 'notiwind'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Notifications,
|
||||
},
|
||||
})
|
||||
</script>
|
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<NotificationGroup group="generic">
|
||||
<div class="fixed inset-0 flex items-start justify-end p-6 px-4 py-6 pointer-events-none z-50">
|
||||
<div class="w-full max-w-sm">
|
||||
<Notification
|
||||
v-slot="{ notifications }"
|
||||
enter="transform ease-out duration-300 transition"
|
||||
enter-from="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-4"
|
||||
enter-to="translate-y-0 opacity-100 sm:translate-x-0"
|
||||
leave="transition ease-in duration-500"
|
||||
leave-from="opacity-100"
|
||||
leave-to="opacity-0"
|
||||
move="transition duration-500"
|
||||
move-delay="delay-300"
|
||||
>
|
||||
<div class="flex w-full max-w-sm mx-auto mt-4 overflow-hidden bg-white rounded-lg shadow-md border border-gray-200"
|
||||
v-for="notification in notifications"
|
||||
:key="notification.id"
|
||||
>
|
||||
<div class="flex items-center justify-center w-12 bg-gray-500">
|
||||
<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="w-6 h-6 text-white">
|
||||
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="px-4 py-2 -mx-3">
|
||||
<div class="mx-3">
|
||||
<span class="font-semibold text-gray-500">{{ notification.title }}</span>
|
||||
<p class="text-sm text-gray-600">{{ notification.text }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Notification>
|
||||
</div>
|
||||
</div>
|
||||
</NotificationGroup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
import Notifications from 'notiwind'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Notifications,
|
||||
},
|
||||
})
|
||||
</script>
|
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<NotificationGroup group="success">
|
||||
<div class="fixed inset-0 flex items-start justify-end p-6 px-4 py-6 pointer-events-none z-50">
|
||||
<div class="w-full max-w-sm">
|
||||
<Notification
|
||||
v-slot="{ notifications }"
|
||||
enter="transform ease-out duration-300 transition"
|
||||
enter-from="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-4"
|
||||
enter-to="translate-y-0 opacity-100 sm:translate-x-0"
|
||||
leave="transition ease-in duration-500"
|
||||
leave-from="opacity-100"
|
||||
leave-to="opacity-0"
|
||||
move="transition duration-500"
|
||||
move-delay="delay-300"
|
||||
>
|
||||
<div class="flex w-full max-w-sm mx-auto mt-4 overflow-hidden bg-white rounded-lg shadow-md border border-gray-200"
|
||||
v-for="notification in notifications"
|
||||
:key="notification.id"
|
||||
>
|
||||
<div class="flex items-center justify-center w-12 bg-green-500">
|
||||
<svg class="w-6 h-6 text-white fill-current" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20 3.33331C10.8 3.33331 3.33337 10.8 3.33337 20C3.33337 29.2 10.8 36.6666 20 36.6666C29.2 36.6666 36.6667 29.2 36.6667 20C36.6667 10.8 29.2 3.33331 20 3.33331ZM16.6667 28.3333L8.33337 20L10.6834 17.65L16.6667 23.6166L29.3167 10.9666L31.6667 13.3333L16.6667 28.3333Z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="px-4 py-2 -mx-3">
|
||||
<div class="mx-3">
|
||||
<span class="font-semibold text-green-500">{{ notification.title }}</span>
|
||||
<p class="text-sm text-gray-600">{{ notification.text }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Notification>
|
||||
</div>
|
||||
</div>
|
||||
</NotificationGroup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
import Notifications from 'notiwind'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Notifications,
|
||||
},
|
||||
})
|
||||
</script>
|
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<NotificationGroup group="warning">
|
||||
<div class="fixed inset-0 flex items-start justify-end p-6 px-4 py-6 pointer-events-none z-50">
|
||||
<div class="w-full max-w-sm">
|
||||
<Notification
|
||||
v-slot="{ notifications }"
|
||||
enter="transform ease-out duration-300 transition"
|
||||
enter-from="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-4"
|
||||
enter-to="translate-y-0 opacity-100 sm:translate-x-0"
|
||||
leave="transition ease-in duration-500"
|
||||
leave-from="opacity-100"
|
||||
leave-to="opacity-0"
|
||||
move="transition duration-500"
|
||||
move-delay="delay-300"
|
||||
>
|
||||
<div class="flex w-full max-w-sm mx-auto mt-4 overflow-hidden bg-white rounded-lg shadow-md border border-gray-200"
|
||||
v-for="notification in notifications"
|
||||
:key="notification.id"
|
||||
>
|
||||
<div class="flex items-center justify-center w-12 bg-orange-500">
|
||||
<svg class="w-6 h-6 text-white fill-current" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20 3.33331C10.8 3.33331 3.33337 10.8 3.33337 20C3.33337 29.2 10.8 36.6666 20 36.6666C29.2 36.6666 36.6667 29.2 36.6667 20C36.6667 10.8 29.2 3.33331 20 3.33331ZM16.6667 28.3333L8.33337 20L10.6834 17.65L16.6667 23.6166L29.3167 10.9666L31.6667 13.3333L16.6667 28.3333Z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="px-4 py-2 -mx-3">
|
||||
<div class="mx-3">
|
||||
<span class="font-semibold text-orange-500">{{ notification.title }}</span>
|
||||
<p class="text-sm text-gray-600">{{ notification.text }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Notification>
|
||||
</div>
|
||||
</div>
|
||||
</NotificationGroup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from 'vue'
|
||||
import Notifications from 'notiwind'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Notifications,
|
||||
},
|
||||
})
|
||||
</script>
|
@ -46,7 +46,7 @@ export default defineComponent({
|
||||
"transition",
|
||||
]
|
||||
|
||||
let tiveClasses = [
|
||||
let activeClasses = [
|
||||
"border-transparent",
|
||||
"text-gray-600",
|
||||
"hover:text-gray-800",
|
||||
@ -58,7 +58,7 @@ export default defineComponent({
|
||||
]
|
||||
|
||||
if (props.active) {
|
||||
tiveClasses = [
|
||||
activeClasses = [
|
||||
"border-indigo-400",
|
||||
"text-indigo-700",
|
||||
"bg-indigo-50",
|
||||
@ -68,7 +68,7 @@ export default defineComponent({
|
||||
]
|
||||
}
|
||||
|
||||
defaultClasses = dClasses.concat(tiveClasses)
|
||||
defaultClasses = dClasses.concat(activeClasses)
|
||||
|
||||
for (let elm of props.class.split(" ")) {
|
||||
elm = elm.trim()
|
||||
|
@ -44,20 +44,20 @@ export default defineComponent({
|
||||
"rounded-lg",
|
||||
]
|
||||
|
||||
let tiveClasses = [
|
||||
"nm-flat-white",
|
||||
"hover:nm-concave-blue-300",
|
||||
let activeClasses = [
|
||||
"bg-white",
|
||||
"hover:bg-blue-300",
|
||||
"hover:text-white",
|
||||
]
|
||||
|
||||
if (props.active) {
|
||||
tiveClasses = [
|
||||
"nm-flat-blue-400",
|
||||
activeClasses = [
|
||||
"bg-blue-400",
|
||||
"text-white",
|
||||
]
|
||||
}
|
||||
|
||||
defaultClasses = dClasses.concat(tiveClasses)
|
||||
defaultClasses = dClasses.concat(activeClasses)
|
||||
|
||||
for (let elm of props.class.split(" ")) {
|
||||
elm = elm.trim()
|
||||
|
@ -3,9 +3,10 @@
|
||||
<Head :title="title" />
|
||||
|
||||
<div class="absolute top-0 mt-4 z-50">
|
||||
<success-notifications />
|
||||
<error-notifications />
|
||||
<generic-notifications />
|
||||
<generic-notifications></generic-notifications>
|
||||
<success-notifications></success-notifications>
|
||||
<warning-notifications></warning-notifications>
|
||||
<error-notifications></error-notifications>
|
||||
</div>
|
||||
|
||||
<jet-banner />
|
||||
@ -206,10 +207,6 @@
|
||||
Profile
|
||||
</jet-dropdown-link>
|
||||
|
||||
<jet-dropdown-link :href="route('profile.billing.show')">
|
||||
Billing
|
||||
</jet-dropdown-link>
|
||||
|
||||
<jet-dropdown-link :href="route('api-tokens.index')" v-if="$page.props.jetstream.hasApiFeatures">
|
||||
API Tokens
|
||||
</jet-dropdown-link>
|
||||
@ -237,17 +234,17 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue"
|
||||
import { Head, Link } from "@inertiajs/inertia-vue3"
|
||||
import SuccessNotifications from "@/Components/Notifications/SuccessNotifications.vue"
|
||||
import ErrorNotifications from "@/Components/Notifications/ErrorNotifications.vue"
|
||||
import GenericNotifications from "@/Components/Notifications/GenericNotifications.vue"
|
||||
import ApplicationMark from "@/Jetstream/ApplicationMark.vue"
|
||||
import ResponsiveNavLink from "@/Components/ResponsiveNavLink.vue"
|
||||
import SidenavLink from "@/Components/SidenavLink.vue"
|
||||
import JetBanner from "@/Jetstream/Banner.vue"
|
||||
import JetDropdown from "@/Jetstream/Dropdown.vue"
|
||||
import JetDropdownLink from "@/Jetstream/DropdownLink.vue"
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import { Head, Link } from '@inertiajs/inertia-vue3'
|
||||
import SuccessNotifications from '@/Components/Notifications/SuccessNotifications.vue'
|
||||
import ErrorNotifications from '@/Components/Notifications/ErrorNotifications.vue'
|
||||
import GenericNotifications from '@/Components/Notifications/GenericNotifications.vue'
|
||||
import ApplicationMark from '@/Jetstream/ApplicationMark.vue'
|
||||
import ResponsiveNavLink from '@/Components/ResponsiveNavLink.vue'
|
||||
import SidenavLink from '@/Components/SidenavLink.vue'
|
||||
import JetBanner from '@/Jetstream/Banner.vue'
|
||||
import JetDropdown from '@/Jetstream/Dropdown.vue'
|
||||
import JetDropdownLink from '@/Jetstream/DropdownLink.vue'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@ -268,23 +265,23 @@ export default defineComponent({
|
||||
JetDropdownLink,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showingNavigationDropdown: false,
|
||||
}
|
||||
setup(props) {
|
||||
let showingNavigationDropdown = ref(false)
|
||||
|
||||
return { showingNavigationDropdown }
|
||||
},
|
||||
|
||||
methods: {
|
||||
switchToTeam(team) {
|
||||
this.$inertia.put(route("current-team.update"), {
|
||||
"team_id": team.id
|
||||
this.$inertia.put(route('current-team.update'), {
|
||||
'team_id': team.id
|
||||
}, {
|
||||
preserveState: false
|
||||
})
|
||||
},
|
||||
|
||||
logout() {
|
||||
this.$inertia.post(route("logout"));
|
||||
this.$inertia.post(route('logout'));
|
||||
},
|
||||
}
|
||||
})
|
||||
|
@ -9,11 +9,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue"
|
||||
import AppLayout from "@/Layouts/AppLayout.vue"
|
||||
import Card from "@/Components/Card.vue"
|
||||
import { defineComponent, reactive, ref, computed, watch, onBeforeMount, onMounted, provide, inject } from 'vue'
|
||||
import AppLayout from '@/Layouts/AppLayout.vue'
|
||||
import Card from '@/Components/Card.vue'
|
||||
|
||||
export default defineComponent({
|
||||
emits: [],
|
||||
|
||||
props: {},
|
||||
|
||||
components: {
|
||||
@ -21,16 +23,38 @@ export default defineComponent({
|
||||
Card,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {}
|
||||
setup(props, { attrs, slots, emit, expose }) {
|
||||
let aVariable = reactive({})
|
||||
|
||||
// computed properties
|
||||
/*let compVariable = computed(() => {
|
||||
//return 'foo'
|
||||
})*/
|
||||
|
||||
// watchers
|
||||
/*watch(aVariable, (newValue, oldValue) => {
|
||||
//
|
||||
})*/
|
||||
|
||||
// lifecycle hooks
|
||||
onBeforeMount(() => {
|
||||
//
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
//
|
||||
})
|
||||
|
||||
// methods
|
||||
function myMethod() {
|
||||
aVariable.value = null
|
||||
}
|
||||
|
||||
return {
|
||||
aVariable,
|
||||
compVariable,
|
||||
myMethod,
|
||||
}
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
return {}
|
||||
},
|
||||
|
||||
computed: {},
|
||||
|
||||
methods: {},
|
||||
})
|
||||
</script>
|
||||
|
55
src/webpack.mix.js
Normal file
55
src/webpack.mix.js
Normal file
@ -0,0 +1,55 @@
|
||||
const mix = require('laravel-mix');
|
||||
const { exec } = require('child_process');
|
||||
|
||||
const shaCmd = "cat public/js/app.js | openssl dgst -sha512 -binary | openssl base64 -A";
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mix Asset Management
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Mix provides a clean, fluent API for defining some Webpack build steps
|
||||
| for your Laravel applications. By default, we are compiling the CSS
|
||||
| file for the application as well as bundling up all the JS files.
|
||||
|
|
||||
*/
|
||||
|
||||
mix.js('resources/js/app.js', 'public/js')
|
||||
.vue()
|
||||
.sourceMaps()
|
||||
.after(stats => {
|
||||
exec(shaCmd, (shaError, shaStdout, shaStderr) => {
|
||||
if (shaError) {
|
||||
console.error(`shaCmd error: ${shaError.message}`);
|
||||
return;
|
||||
}
|
||||
if (shaStderr) {
|
||||
console.error(`shaCmd stderr: ${shaStderr}`);
|
||||
return;
|
||||
}
|
||||
let sha512Hash = shaStdout;
|
||||
let sedCmd = `sed -i '/^APP_JS_INTEGRITY_HASH="*/c\APP_JS_INTEGRITY_HASH="sha512-${sha512Hash}"' .env`;
|
||||
|
||||
exec(sedCmd, (sedError, sedStdout, sedStderr) => {
|
||||
if (sedError) {
|
||||
console.error(`sedCmd error: ${sedError.message}`);
|
||||
return;
|
||||
}
|
||||
if (sedStderr) {
|
||||
console.error(`sedCmd stderr: ${sedStderr}`);
|
||||
return;
|
||||
}
|
||||
console.log('Replaced SHA512 hash for integrity attribute.');
|
||||
})
|
||||
})
|
||||
})
|
||||
.postCss('resources/css/app.css', 'public/css', [
|
||||
require('postcss-import'),
|
||||
require('tailwindcss'),
|
||||
])
|
||||
.sourceMaps()
|
||||
.webpackConfig(require('./webpack.config'));
|
||||
|
||||
if (mix.inProduction()) {
|
||||
mix.version();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user