resolving
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 5m14s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 17s
Build, Push and Deploy / deploy-staging (push) Successful in 41s
Build, Push and Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-04-27 08:58:08 +07:00
21707 changed files with 179487 additions and 297 deletions

4
.scribe/.filehashes Normal file
View File

@@ -0,0 +1,4 @@
# GENERATED. YOU SHOULDN'T MODIFY OR DELETE THIS FILE.
# Scribe uses this file to know when you change something manually in your docs.
.scribe/intro.md=4cce32d41499a35efb2ff125bcc4d59c
.scribe/auth.md=9bee2b1ef8a238b2e58613fa636d5f39

3
.scribe/auth.md Normal file
View File

@@ -0,0 +1,3 @@
# Authenticating requests
This API is not authenticated.

File diff suppressed because it is too large Load Diff

10920
.scribe/endpoints/00.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
# To include an endpoint that isn't a part of your Laravel app (or belongs to a vendor package),
# you can define it in a custom.*.yaml file, like this one.
# Each custom file should contain an array of endpoints. Here's an example:
# See https://scribe.knuckles.wtf/laravel/documenting/custom-endpoints#extra-sorting-groups-in-custom-endpoint-files for more options
#- httpMethods:
# - POST
# uri: api/doSomething/{param}
# metadata:
# groupName: The group the endpoint belongs to. Can be a new group or an existing group.
# groupDescription: A description for the group. You don't need to set this for every endpoint; once is enough.
# subgroup: You can add a subgroup, too.
# title: Do something
# description: 'This endpoint allows you to do something.'
# authenticated: false
# headers:
# Content-Type: application/json
# Accept: application/json
# urlParameters:
# param:
# name: param
# description: A URL param for no reason.
# required: true
# example: 2
# type: integer
# queryParameters:
# speed:
# name: speed
# description: How fast the thing should be done. Can be `slow` or `fast`.
# required: false
# example: fast
# type: string
# bodyParameters:
# something:
# name: something
# description: The things we should do.
# required: true
# example:
# - string 1
# - string 2
# type: 'string[]'
# responses:
# - status: 200
# description: 'When the thing was done smoothly.'
# content: # Your response content can be an object, an array, a string or empty.
# {
# "hey": "ho ho ho"
# }
# responseFields:
# hey:
# name: hey
# description: Who knows?
# type: string # This is optional

13
.scribe/intro.md Normal file
View File

@@ -0,0 +1,13 @@
# Introduction
<aside>
<strong>Base URL</strong>: <code>http://localhost:8080</code>
</aside>
This documentation aims to provide all the information you need to work with our API.
<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>

View File

@@ -14,6 +14,7 @@ RUN apk add --no-cache \
oniguruma-dev \
git \
curl \
postgresql-client \
nodejs \
npm \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \

View File

@@ -13,6 +13,7 @@ class WebController extends Controller
{
public function index()
{
return view('index');
$plans = Plan::where('status', 1)->get();
return view('index', compact('plans'));
}
}

259
config/scribe.php Normal file
View File

@@ -0,0 +1,259 @@
<?php
use Knuckles\Scribe\Config\AuthIn;
use Knuckles\Scribe\Config\Defaults;
use Knuckles\Scribe\Extracting\Strategies;
use function Knuckles\Scribe\Config\configureStrategy;
use function Knuckles\Scribe\Config\removeStrategies;
// Only the most common configs are shown. See the https://scribe.knuckles.wtf/laravel/reference/config for all.
return [
// The HTML <title> for the generated documentation.
'title' => config('app.name').' API Documentation',
// A short description of your API. Will be included in the docs webpage, Postman collection and OpenAPI spec.
'description' => '',
// Text to place in the "Introduction" section, right after the `description`. Markdown and HTML are supported.
'intro_text' => <<<'INTRO'
This documentation aims to provide all the information you need to work with our API.
<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>
INTRO,
// The base URL displayed in the docs.
// If you're using `laravel` type, you can set this to a dynamic string, like '{{ config("app.tenant_url") }}' to get a dynamic base URL.
'base_url' => config('app.url'),
// Routes to include in the docs
'routes' => [
[
'match' => [
// Match only routes whose paths match this pattern (use * as a wildcard to match any characters). Example: 'users/*'.
'prefixes' => ['api/*'],
// Match only routes whose domains match this pattern (use * as a wildcard to match any characters). Example: 'api.*'.
'domains' => ['*'],
],
// Include these routes even if they did not match the rules above.
'include' => [
// 'users.index', 'POST /new', '/auth/*'
],
// Exclude these routes even if they matched the rules above.
'exclude' => [
// 'GET /health', 'admin.*'
],
],
],
// The type of documentation output to generate.
// - "static" will generate a static HTMl page in the /public/docs folder,
// - "laravel" will generate the documentation as a Blade view, so you can add routing and authentication.
// - "external_static" and "external_laravel" do the same as above, but pass the OpenAPI spec as a URL to an external UI template
'type' => 'laravel',
// See https://scribe.knuckles.wtf/laravel/reference/config#theme for supported options
'theme' => 'default',
'static' => [
// HTML documentation, assets and Postman collection will be generated to this folder.
// Source Markdown will still be in resources/docs.
'output_path' => 'public/docs',
],
'laravel' => [
// Whether to automatically create a docs route for you to view your generated docs. You can still set up routing manually.
'add_routes' => true,
// URL path to use for the docs endpoint (if `add_routes` is true).
// By default, `/docs` opens the HTML page, `/docs.postman` opens the Postman collection, and `/docs.openapi` the OpenAPI spec.
'docs_url' => '/docs',
// Directory within `public` in which to store CSS and JS assets.
// By default, assets are stored in `public/vendor/scribe`.
// If set, assets will be stored in `public/{{assets_directory}}`
'assets_directory' => null,
// Middleware to attach to the docs endpoint (if `add_routes` is true).
'middleware' => [],
],
'external' => [
'html_attributes' => [],
],
'try_it_out' => [
// Add a Try It Out button to your endpoints so consumers can test endpoints right from their browser.
// Don't forget to enable CORS headers for your endpoints.
'enabled' => true,
// The base URL to use in the API tester. Leave as null to be the same as the displayed URL (`scribe.base_url`).
'base_url' => null,
// [Laravel Sanctum] Fetch a CSRF token before each request, and add it as an X-XSRF-TOKEN header.
'use_csrf' => false,
// The URL to fetch the CSRF token from (if `use_csrf` is true).
'csrf_url' => '/sanctum/csrf-cookie',
],
// How is your API authenticated? This information will be used in the displayed docs, generated examples and response calls.
'auth' => [
// Set this to true if ANY endpoints in your API use authentication.
'enabled' => false,
// Set this to true if your API should be authenticated by default. If so, you must also set `enabled` (above) to true.
// You can then use @unauthenticated or @authenticated on individual endpoints to change their status from the default.
'default' => false,
// Where is the auth value meant to be sent in a request?
'in' => AuthIn::BEARER->value,
// The name of the auth parameter (e.g. token, key, apiKey) or header (e.g. Authorization, Api-Key).
'name' => 'key',
// The value of the parameter to be used by Scribe to authenticate response calls.
// This will NOT be included in the generated documentation. If empty, Scribe will use a random value.
'use_value' => env('SCRIBE_AUTH_KEY'),
// Placeholder your users will see for the auth parameter in the example requests.
// Set this to null if you want Scribe to use a random value as placeholder instead.
'placeholder' => '{YOUR_AUTH_KEY}',
// Any extra authentication-related info for your users. Markdown and HTML are supported.
'extra_info' => 'You can retrieve your token by visiting your dashboard and clicking <b>Generate API token</b>.',
],
// Example requests for each endpoint will be shown in each of these languages.
// Supported options are: bash, javascript, php, python
// To add a language of your own, see https://scribe.knuckles.wtf/laravel/advanced/example-requests
// Note: does not work for `external` docs types
'example_languages' => [
'bash',
'javascript',
],
// Generate a Postman collection (v2.1.0) in addition to HTML docs.
// For 'static' docs, the collection will be generated to public/docs/collection.json.
// For 'laravel' docs, it will be generated to storage/app/scribe/collection.json.
// Setting `laravel.add_routes` to true (above) will also add a route for the collection.
'postman' => [
'enabled' => true,
'overrides' => [
// 'info.version' => '2.0.0',
],
],
// Generate an OpenAPI spec in addition to docs webpage.
// For 'static' docs, the collection will be generated to public/docs/openapi.yaml.
// For 'laravel' docs, it will be generated to storage/app/scribe/openapi.yaml.
// Setting `laravel.add_routes` to true (above) will also add a route for the spec.
'openapi' => [
'enabled' => true,
// The OpenAPI spec version to generate. Supported versions: '3.0.3', '3.1.0'.
// OpenAPI 3.1 is more compatible with JSON Schema and is becoming the dominant version.
// See https://spec.openapis.org/oas/v3.1.0 for details on 3.1 changes.
'version' => '3.0.3',
'overrides' => [
// 'info.version' => '2.0.0',
],
// Additional generators to use when generating the OpenAPI spec.
// Should extend `Knuckles\Scribe\Writing\OpenApiSpecGenerators\OpenApiGenerator`.
'generators' => [],
],
'groups' => [
// Endpoints which don't have a @group will be placed in this default group.
'default' => 'Endpoints',
// By default, Scribe will sort groups alphabetically, and endpoints in the order their routes are defined.
// You can override this by listing the groups, subgroups and endpoints here in the order you want them.
// See https://scribe.knuckles.wtf/blog/laravel-v4#easier-sorting and https://scribe.knuckles.wtf/laravel/reference/config#order for details
// Note: does not work for `external` docs types
'order' => [],
],
// Custom logo path. This will be used as the value of the src attribute for the <img> tag,
// so make sure it points to an accessible URL or path. Set to false to not use a logo.
// For example, if your logo is in public/img:
// - 'logo' => '../img/logo.png' // for `static` type (output folder is public/docs)
// - 'logo' => 'img/logo.png' // for `laravel` type
'logo' => false,
// Customize the "Last updated" value displayed in the docs by specifying tokens and formats.
// Examples:
// - {date:F j Y} => March 28, 2022
// - {git:short} => Short hash of the last Git commit
// Available tokens are `{date:<format>}` and `{git:<format>}`.
// The format you pass to `date` will be passed to PHP's `date()` function.
// The format you pass to `git` can be either "short" or "long".
// Note: does not work for `external` docs types
'last_updated' => 'Last updated: {date:F j, Y}',
'examples' => [
// Set this to any number to generate the same example values for parameters on each run,
'faker_seed' => 1234,
// With API resources and transformers, Scribe tries to generate example models to use in your API responses.
// By default, Scribe will try the model's factory, and if that fails, try fetching the first from the database.
// You can reorder or remove strategies here.
'models_source' => ['factoryCreate', 'factoryMake', 'databaseFirst'],
],
// The strategies Scribe will use to extract information about your routes at each stage.
// Use configureStrategy() to specify settings for a strategy in the list.
// Use removeStrategies() to remove an included strategy.
'strategies' => [
'metadata' => [
...Defaults::METADATA_STRATEGIES,
],
'headers' => [
...Defaults::HEADERS_STRATEGIES,
Strategies\StaticData::withSettings(data: [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
]),
],
'urlParameters' => [
...Defaults::URL_PARAMETERS_STRATEGIES,
],
'queryParameters' => [
...Defaults::QUERY_PARAMETERS_STRATEGIES,
],
'bodyParameters' => [
...Defaults::BODY_PARAMETERS_STRATEGIES,
],
'responses' => configureStrategy(
Defaults::RESPONSES_STRATEGIES,
Strategies\Responses\ResponseCalls::withSettings(
only: ['GET *'],
// Recommended: disable debug mode in response calls to avoid error stack traces in responses
config: [
'app.debug' => false,
]
)
),
'responseFields' => [
...Defaults::RESPONSE_FIELDS_STRATEGIES,
],
],
// For response calls, API resource responses and transformer responses,
// Scribe will try to start database transactions, so no changes are persisted to your database.
// Tell Scribe which connections should be transacted here. If you only use one db connection, you can leave this as is.
'database_connections_to_transact' => [config('database.default')],
'fractal' => [
// If you are using a custom serializer with league/fractal, you can specify it here.
'serializer' => null,
],
];

60
docker-compose.yml Normal file
View File

@@ -0,0 +1,60 @@
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: kulakpos_app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
volumes:
- .:/var/www/html
- ./entrypoint.sh:/entrypoint.sh
networks:
- kulakpos-network
depends_on:
- db
db:
image: postgres:15-alpine
container_name: kulakpos_db
restart: unless-stopped
tty: true
ports:
- "5433:5432"
environment:
POSTGRES_DB: kulakpos
POSTGRES_USER: postgres
POSTGRES_PASSWORD: gaspolvr46
volumes:
- dbdata:/var/lib/postgresql/data
- ./converted.sql:/docker-entrypoint-initdb.d/init.sql:ro
networks:
- kulakpos-network
nginx:
image: nginx:alpine
container_name: kulakpos_nginx
restart: unless-stopped
tty: true
ports:
- "8080:80"
volumes:
- .:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- kulakpos-network
depends_on:
- app
networks:
kulakpos-network:
driver: bridge
volumes:
dbdata:
driver: local

22
docker/nginx/default.conf Normal file
View File

@@ -0,0 +1,22 @@
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html/public;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}

84
entrypoint.sh Normal file → Executable file
View File

@@ -63,6 +63,24 @@ EOF
fi
fi
# LOAD environment variables from .env for use in this script
if [ -f .env ]; then
echo "Loading environment variables from .env..."
# Read .env file line by line and export each variable
while IFS= read -r line || [ -n "$line" ]; do
# Remove carriage return if present (Windows style)
line=$(echo "$line" | sed 's/\r$//')
# Skip comments and empty lines
case "$line" in
"#"*) continue ;;
"") continue ;;
esac
# Remove quotes from value and export
export "$(echo "$line" | sed 's/["'\'']//g')" 2>/dev/null || true
done < .env
fi
# Generate key if not present (only if APP_KEY is empty or missing)
echo "Checking .env for APP_KEY..."
if ! grep -E "APP_KEY=.{10,}" .env; then
@@ -111,12 +129,22 @@ if [ ! -f config/scribe.php ]; then
php artisan vendor:publish --tag=scribe-config --force
fi
# Skip Scribe generation if docs already exist to save time on restart
if [ -d resources/views/scribe ] && [ "$FORCE_REGENERATE_DOCS" != "true" ]; then
echo "✅ Scribe docs already exist, skipping generation..."
SKIP_SCRIBE=true
fi
# Generate OpenAPI/Swagger documentation
if [ "$APP_ENV" != "production" ] || [ "$AUTO_GENERATE_API_DOCS" = "true" ]; then
echo "Generating API documentation..."
# Generate Scribe documentation
if [ "$SKIP_SCRIBE" != "true" ]; then
echo "Generating Scribe documentation..."
php artisan scribe:generate --no-interaction || echo "⚠️ Scribe generation failed, check your API routes"
fi
# For OpenAPI/Swagger UI specifically
if [ -f public/docs/openapi.yaml ] || [ -f public/docs/collection.json ]; then
@@ -136,10 +164,14 @@ if [ -d vendor/knuckleswtf/scribe/dist ]; then
ln -sf ../vendor/knuckleswtf/scribe/dist public/vendor/scribe 2>/dev/null || true
fi
# FIX: Ensure all generated/downloaded files are fully readable and executable
echo "Setting correct ownership for web server..."
chown -R www-data:www-data vendor
chmod -R 755 vendor
# FIX: Ensure storage and bootstrap are writable (these are small)
echo "Setting correct ownership for storage and bootstrap..."
chown -R www-data:www-data storage bootstrap/cache
chmod -R 775 storage bootstrap/cache
# Note: We skip recursive chown on vendor because it's very slow on mounted volumes
# and usually not necessary for runtime.
# Verify vendor integrity at PHP level
echo "Checking vendor visibility and READABILITY for PHP..."
@@ -167,17 +199,51 @@ fi
if [ -f public/build/manifest.json ]; then
echo "✅ Vite manifest found at public/build/manifest.json"
else
echo "⚠️ Warning: Vite manifest not found! Assets may not load correctly."
echo "⚠️ Vite manifest not found! Attempting to build assets..."
if command -v npm >/dev/null 2>&1; then
if [ ! -d node_modules ]; then
echo "📦 node_modules missing. Installing..."
npm install --legacy-peer-deps --no-audit || echo "❌ npm install failed!"
fi
npm run build || echo "❌ npm run build failed!"
else
echo "❌ npm not found, cannot build assets automatically."
fi
if [ ! -f public/build/manifest.json ]; then
echo "⚠️ Still no Vite manifest! Assets may not load correctly."
echo "Current contents of public/build:"
ls -la public/build/ 2>/dev/null || echo "public/build directory does not exist"
fi
fi
# Optional: Run migrations if needed (with safety for production)
# if [ "$AUTO_MIGRATE" = "true" ] || [ "$APP_ENV" != "production" ]; then
# echo "Running migrations..."
# php artisan migrate --force
if [ "$AUTO_MIGRATE" = "true" ] || [ "$APP_ENV" != "production" ]; then
echo "Running migrations..."
php artisan migrate --force
# fi
# Optional: Seed if needed, but we have converted.sql
# php artisan db:seed --force
# Check if database has data (e.g., check users table)
# We use PGPASSWORD to avoid interactive prompt
export PGPASSWORD=$DB_PASSWORD
echo "Checking if database needs data import..."
USER_COUNT=$(psql -h $DB_HOST -U $DB_USERNAME -d $DB_DATABASE -t -c "SELECT count(*) FROM users;" 2>/dev/null | tr -d '[:space:]' || echo "0")
if [ "$USER_COUNT" = "0" ] || [ -z "$USER_COUNT" ]; then
if [ -f converted.sql ]; then
echo "📦 Database is empty. Importing data from converted.sql..."
psql -h $DB_HOST -U $DB_USERNAME -d $DB_DATABASE -f converted.sql > /dev/null
echo "✅ Data import complete."
else
echo "⚠️ converted.sql not found, skipping data import."
fi
else
echo "✅ Database already has data ($USER_COUNT users)."
fi
unset PGPASSWORD
fi
echo "========================================"
echo "Setup complete. Starting application..."

2
package-lock.json generated
View File

@@ -1,5 +1,5 @@
{
"name": "kulakpos_web",
"name": "html",
"lockfileVersion": 3,
"requires": true,
"packages": {

View File

@@ -0,0 +1,393 @@
/* Copied from https://github.com/slatedocs/slate/blob/c4b4c0b8f83e891ca9fab6bbe9a1a88d5fe41292/stylesheets/print.css and unminified */
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
html {
font-family: sans-serif;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%
}
body {
margin: 0
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block
}
audio,
canvas,
progress,
video {
display: inline-block;
vertical-align: baseline
}
audio:not([controls]) {
display: none;
height: 0
}
[hidden],
template {
display: none
}
a {
background-color: transparent
}
a:active,
a:hover {
outline: 0
}
abbr[title] {
border-bottom: 1px dotted
}
b,
strong {
font-weight: bold
}
dfn {
font-style: italic
}
h1 {
font-size: 2em;
margin: 0.67em 0
}
mark {
background: #ff0;
color: #000
}
small {
font-size: 80%
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline
}
sup {
top: -0.5em
}
sub {
bottom: -0.25em
}
img {
border: 0
}
svg:not(:root) {
overflow: hidden
}
figure {
margin: 1em 40px
}
hr {
box-sizing: content-box;
height: 0
}
pre {
overflow: auto
}
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em
}
button,
input,
optgroup,
select,
textarea {
color: inherit;
font: inherit;
margin: 0
}
button {
overflow: visible
}
button,
select {
text-transform: none
}
button,
html input[type="button"],
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button;
cursor: pointer
}
button[disabled],
html input[disabled] {
cursor: default
}
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0
}
input {
line-height: normal
}
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box;
padding: 0
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto
}
input[type="search"] {
-webkit-appearance: textfield;
box-sizing: content-box
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none
}
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em
}
legend {
border: 0;
padding: 0
}
textarea {
overflow: auto
}
optgroup {
font-weight: bold
}
table {
border-collapse: collapse;
border-spacing: 0
}
td,
th {
padding: 0
}
.content h1,
.content h2,
.content h3,
.content h4,
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 14px
}
.content h1,
.content h2,
.content h3,
.content h4 {
font-weight: bold
}
.content pre,
.content code {
font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif;
font-size: 12px;
line-height: 1.5
}
.content pre,
.content code {
word-break: break-all;
-webkit-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto
}
@font-face {
font-family: 'slate';
src: url(../fonts/slate.eot?-syv14m);
src: url(../fonts/slate.eot?#iefix-syv14m) format("embedded-opentype"), url(../fonts/slate.woff2?-syv14m) format("woff2"), url(../fonts/slate.woff?-syv14m) format("woff"), url(../fonts/slate.ttf?-syv14m) format("truetype"), url(../fonts/slate.svg?-syv14m#slate) format("svg");
font-weight: normal;
font-style: normal
}
.content aside.warning:before,
.content aside.notice:before,
.content aside.success:before {
font-family: 'slate';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1
}
.content aside.warning:before {
content: "\e600"
}
.content aside.notice:before {
content: "\e602"
}
.content aside.success:before {
content: "\e606"
}
.tocify,
.toc-footer,
.lang-selector,
.search,
#nav-button {
display: none
}
.tocify-wrapper>img {
margin: 0 auto;
display: block
}
.content {
font-size: 12px
}
.content pre,
.content code {
border: 1px solid #999;
border-radius: 5px;
font-size: 0.8em
}
.content pre code {
border: 0
}
.content pre {
padding: 1.3em
}
.content code {
padding: 0.2em
}
.content table {
border: 1px solid #999
}
.content table tr {
border-bottom: 1px solid #999
}
.content table td,
.content table th {
padding: 0.7em
}
.content p {
line-height: 1.5
}
.content a {
text-decoration: none;
color: #000
}
.content h1 {
font-size: 2.5em;
padding-top: 0.5em;
padding-bottom: 0.5em;
margin-top: 1em;
margin-bottom: 21px;
border: 2px solid #ccc;
border-width: 2px 0;
text-align: center
}
.content h2 {
font-size: 1.8em;
margin-top: 2em;
border-top: 2px solid #ccc;
padding-top: 0.8em
}
.content h1+h2,
.content h1+div+h2 {
border-top: none;
padding-top: 0;
margin-top: 0
}
.content h3,
.content h4 {
font-size: 0.8em;
margin-top: 1.5em;
margin-bottom: 0.8em;
text-transform: uppercase
}
.content h5,
.content h6 {
text-transform: uppercase
}
.content aside {
padding: 1em;
border: 1px solid #ccc;
border-radius: 5px;
margin-top: 1.5em;
margin-bottom: 1.5em;
line-height: 1.6
}
.content aside:before {
vertical-align: middle;
padding-right: 0.5em;
font-size: 14px
}

File diff suppressed because it is too large Load Diff

BIN
public/vendor/scribe/images/navbar.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

View File

@@ -0,0 +1,149 @@
document.addEventListener('DOMContentLoaded', function() {
const updateHash = function (id) {
window.location.hash = `#${id}`;
};
const navButton = document.getElementById('nav-button');
const menuWrapper = document.querySelector('.tocify-wrapper');
function toggleSidebar(event) {
event.preventDefault();
if (menuWrapper) {
menuWrapper.classList.toggle('open');
navButton.classList.toggle('open');
}
}
function closeSidebar() {
if (menuWrapper) {
menuWrapper.classList.remove('open');
navButton.classList.remove('open');
}
}
navButton.addEventListener('click', toggleSidebar);
window.hljs.highlightAll();
const wrapper = document.getElementById('toc');
// https://jets.js.org/
window.jets = new window.Jets({
// *OR - Selects elements whose values contains at least one part of search substring
searchSelector: '*OR',
searchTag: '#input-search',
contentTag: '#toc li',
didSearch: function(term) {
wrapper.classList.toggle('jets-searching', String(term).length > 0)
},
// map these accent keys to plain values
diacriticsMap: {
a: 'ÀÁÂÃÄÅàáâãäåĀāąĄ',
c: 'ÇçćĆčČ',
d: 'đĐďĎ',
e: 'ÈÉÊËèéêëěĚĒēęĘ',
i: 'ÌÍÎÏìíîïĪī',
l: 'łŁ',
n: 'ÑñňŇńŃ',
o: 'ÒÓÔÕÕÖØòóôõöøŌō',
r: 'řŘ',
s: 'ŠšśŚ',
t: 'ťŤ',
u: 'ÙÚÛÜùúûüůŮŪū',
y: 'ŸÿýÝ',
z: 'ŽžżŻźŹ'
}
});
function hashChange() {
const currentItems = document.querySelectorAll('.tocify-subheader.visible, .tocify-item.tocify-focus');
Array.from(currentItems).forEach((elem) => {
elem.classList.remove('visible', 'tocify-focus');
});
const currentTag = document.querySelector(`a[href="${window.location.hash}"]`);
if (currentTag) {
const parent = currentTag.closest('.tocify-subheader');
if (parent) {
parent.classList.add('visible');
}
const siblings = currentTag.closest('.tocify-header');
if (siblings) {
Array.from(siblings.querySelectorAll('.tocify-subheader')).forEach((elem) => {
elem.classList.add('visible');
});
}
currentTag.parentElement.classList.add('tocify-focus');
// wait for dom changes to be done
setTimeout(() => {
currentTag.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' });
// only close the sidebar on level-2 events
if (currentTag.parentElement.classList.contains('level-2')) {
closeSidebar();
}
}, 1500);
}
}
let languages = JSON.parse(document.body.getAttribute('data-languages'));
// Support a key => value object where the key is the name, or an array of strings where the value is the name
if (!Array.isArray(languages)) {
languages = Object.values(languages);
}
// if there is no language use the first one
const currentLanguage = window.localStorage.getItem('language') || languages[0];
const languageStyle = document.getElementById('language-style');
const langSelector = document.querySelectorAll('.lang-selector button.lang-button');
function setActiveLanguage(newLanguage) {
window.localStorage.setItem('language', newLanguage);
if (!languageStyle) {
return;
}
const newStyle = languages.map((language) => {
return language === newLanguage
// the current one should be visible
? `body .content .${language}-example pre { display: block; }`
// the inactive one should be hidden
: `body .content .${language}-example pre { display: none; }`;
}).join(`\n`);
Array.from(langSelector).forEach((elem) => {
elem.classList.toggle('active', elem.getAttribute('data-language-name') === newLanguage);
});
const activeHash = window.location.hash.slice(1);
languageStyle.innerHTML = newStyle;
setTimeout(() => {
updateHash(activeHash);
}, 200);
}
setActiveLanguage(currentLanguage);
Array.from(langSelector).forEach((elem) => {
elem.addEventListener('click', () => {
const newLanguage = elem.getAttribute('data-language-name');
setActiveLanguage(newLanguage);
});
});
window.addEventListener('hashchange', hashChange, false);
const divs = document.querySelectorAll('.content h1[id], .content h2[id]');
document.addEventListener('scroll', () => {
divs.forEach(item => {
const rect = item.getBoundingClientRect();
if (rect.top > 0 && rect.top < 150) {
const location = window.location.toString().split('#')[0];
history.replaceState(null, null, location + '#' + item.id);
hashChange();
}
});
});
hashChange();
});

View File

@@ -0,0 +1,289 @@
window.abortControllers = {};
function cacheAuthValue() {
// Whenever the auth header is set for one endpoint, cache it for the others
window.lastAuthValue = '';
let authInputs = document.querySelectorAll(`.auth-value`)
authInputs.forEach(el => {
el.addEventListener('input', (event) => {
window.lastAuthValue = event.target.value;
authInputs.forEach(otherInput => {
if (otherInput === el) return;
// Don't block the main thread
setTimeout(() => {
otherInput.value = window.lastAuthValue;
}, 0);
});
});
});
}
window.addEventListener('DOMContentLoaded', cacheAuthValue);
function getCookie(name) {
if (!document.cookie) {
return null;
}
const cookies = document.cookie.split(';')
.map(c => c.trim())
.filter(c => c.startsWith(name + '='));
if (cookies.length === 0) {
return null;
}
return decodeURIComponent(cookies[0].split('=')[1]);
}
function tryItOut(endpointId) {
document.querySelector(`#btn-tryout-${endpointId}`).hidden = true;
document.querySelector(`#btn-canceltryout-${endpointId}`).hidden = false;
const executeBtn = document.querySelector(`#btn-executetryout-${endpointId}`).hidden = false;
executeBtn.disabled = false;
// Show all input fields
document.querySelectorAll(`input[data-endpoint=${endpointId}],label[data-endpoint=${endpointId}]`)
.forEach(el => el.style.display = 'block');
if (document.querySelector(`#form-${endpointId}`).dataset.authed === "1") {
const authElement = document.querySelector(`#auth-${endpointId}`);
authElement && (authElement.hidden = false);
}
// Expand all nested fields
document.querySelectorAll(`#form-${endpointId} details`)
.forEach(el => el.open = true);
}
function cancelTryOut(endpointId) {
if (window.abortControllers[endpointId]) {
window.abortControllers[endpointId].abort();
delete window.abortControllers[endpointId];
}
document.querySelector(`#btn-tryout-${endpointId}`).hidden = false;
const executeBtn = document.querySelector(`#btn-executetryout-${endpointId}`);
executeBtn.hidden = true;
executeBtn.textContent = executeBtn.dataset.initialText;
document.querySelector(`#btn-canceltryout-${endpointId}`).hidden = true;
// Hide inputs
document.querySelectorAll(`input[data-endpoint=${endpointId}],label[data-endpoint=${endpointId}]`)
.forEach(el => el.style.display = 'none');
document.querySelectorAll(`#form-${endpointId} details`)
.forEach(el => el.open = false);
const authElement = document.querySelector(`#auth-${endpointId}`);
authElement && (authElement.hidden = true);
document.querySelector('#execution-results-' + endpointId).hidden = true;
document.querySelector('#execution-error-' + endpointId).hidden = true;
// Revert to sample code blocks
document.querySelector('#example-requests-' + endpointId).hidden = false;
document.querySelector('#example-responses-' + endpointId).hidden = false;
}
function makeAPICall(method, path, body = {}, query = {}, headers = {}, endpointId = null) {
console.log({endpointId, path, body, query, headers});
if (!(body instanceof FormData) && typeof body !== "string") {
body = JSON.stringify(body)
}
const url = new URL(window.tryItOutBaseUrl + '/' + path.replace(/^\//, ''));
// We need this function because if you try to set an array or object directly to a URLSearchParams object,
// you'll get [object Object] or the array.toString()
function addItemToSearchParamsObject(key, value, searchParams) {
if (Array.isArray(value)) {
value.forEach((v, i) => {
// Append {filters: [first, second]} as filters[0]=first&filters[1]second
addItemToSearchParamsObject(key + '[' + i + ']', v, searchParams);
})
} else if (typeof value === 'object' && value !== null) {
Object.keys(value).forEach((i) => {
// Append {filters: {name: first}} as filters[name]=first
addItemToSearchParamsObject(key + '[' + i + ']', value[i], searchParams);
});
} else {
searchParams.append(key, value);
}
}
Object.keys(query)
.forEach(key => addItemToSearchParamsObject(key, query[key], url.searchParams));
window.abortControllers[endpointId] = new AbortController();
return fetch(url, {
method,
headers,
body: method === 'GET' ? undefined : body,
signal: window.abortControllers[endpointId].signal,
referrer: window.tryItOutBaseUrl,
mode: 'cors',
credentials: 'same-origin',
})
.then(response => Promise.all([response.status, response.statusText, response.text(), response.headers]));
}
function hideCodeSamples(endpointId) {
document.querySelector('#example-requests-' + endpointId).hidden = true;
document.querySelector('#example-responses-' + endpointId).hidden = true;
}
function handleResponse(endpointId, response, status, headers) {
hideCodeSamples(endpointId);
// Hide error views
document.querySelector('#execution-error-' + endpointId).hidden = true;
const responseContentEl = document.querySelector('#execution-response-content-' + endpointId);
// Check if the response contains Laravel's dd() default dump output
const isLaravelDump = response.includes('Sfdump');
// If it's a Laravel dd() dump, use innerHTML to render it safely
if (isLaravelDump) {
responseContentEl.innerHTML = response === '' ? responseContentEl.dataset.emptyResponseText : response;
} else {
// Otherwise, stick to textContent for regular responses
responseContentEl.textContent = response === '' ? responseContentEl.dataset.emptyResponseText : response;
}
// Prettify it if it's JSON
let isJson = false;
try {
const jsonParsed = JSON.parse(response);
if (jsonParsed !== null) {
isJson = true;
response = JSON.stringify(jsonParsed, null, 4);
responseContentEl.textContent = response;
}
} catch (e) {
}
isJson && window.hljs.highlightElement(responseContentEl);
const statusEl = document.querySelector('#execution-response-status-' + endpointId);
statusEl.textContent = ` (${status})`;
document.querySelector('#execution-results-' + endpointId).hidden = false;
statusEl.scrollIntoView({behavior: "smooth", block: "center"});
}
function handleError(endpointId, err) {
hideCodeSamples(endpointId);
// Hide response views
document.querySelector('#execution-results-' + endpointId).hidden = true;
// Show error views
let errorMessage = err.message || err;
const $errorMessageEl = document.querySelector('#execution-error-message-' + endpointId);
$errorMessageEl.textContent = errorMessage + $errorMessageEl.textContent;
const errorEl = document.querySelector('#execution-error-' + endpointId);
errorEl.hidden = false;
errorEl.scrollIntoView({behavior: "smooth", block: "center"});
}
async function executeTryOut(endpointId, form) {
const executeBtn = document.querySelector(`#btn-executetryout-${endpointId}`);
executeBtn.textContent = executeBtn.dataset.loadingText;
executeBtn.disabled = true;
executeBtn.scrollIntoView({behavior: "smooth", block: "center"});
let body;
let setter;
if (form.dataset.hasfiles === "1") {
body = new FormData();
setter = (name, value) => body.append(name, value);
} else if (form.dataset.isarraybody === "1") {
body = [];
setter = (name, value) => _.set(body, name, value);
} else {
body = {};
setter = (name, value) => _.set(body, name, value);
}
const bodyParameters = form.querySelectorAll('input[data-component=body]');
bodyParameters.forEach(el => {
let value = el.value;
if (el.type === 'number' && typeof value === 'string') {
value = parseFloat(value);
}
if (el.type === 'file' && el.files[0]) {
setter(el.name, el.files[0]);
return;
}
if (el.type !== 'radio') {
if (value === "" && el.required === false) {
// Don't include empty optional values in the request
return;
}
setter(el.name, value);
return;
}
if (el.checked) {
value = (value === 'false') ? false : true;
setter(el.name, value);
}
});
const query = {};
const queryParameters = form.querySelectorAll('input[data-component=query]');
queryParameters.forEach(el => {
if (el.type !== 'radio' || (el.type === 'radio' && el.checked)) {
if (el.value === '') {
// Don't include empty values in the request
return;
}
_.set(query, el.name, el.value);
}
});
let path = form.dataset.path;
const urlParameters = form.querySelectorAll('input[data-component=url]');
urlParameters.forEach(el => (path = path.replace(new RegExp(`\\{${el.name}\\??}`), el.value)));
const headers = Object.fromEntries(Array.from(form.querySelectorAll('input[data-component=header]'))
.map(el => [el.name, el.value]));
// When using FormData, the browser sets the correct content-type + boundary
let method = form.dataset.method;
if (body instanceof FormData) {
delete headers['Content-Type'];
// When using FormData with PUT or PATCH, use method spoofing so PHP can access the post body
if (['PUT', 'PATCH'].includes(form.dataset.method)) {
method = 'POST';
setter('_method', form.dataset.method);
}
}
let preflightPromise = Promise.resolve();
if (window.useCsrf && window.csrfUrl) {
preflightPromise = makeAPICall('GET', window.csrfUrl).then(() => {
headers['X-XSRF-TOKEN'] = getCookie('XSRF-TOKEN');
});
}
return preflightPromise.then(() => makeAPICall(method, path, body, query, headers, endpointId))
.then(([responseStatus, statusText, responseContent, responseHeaders]) => {
handleResponse(endpointId, responseContent, responseStatus, responseHeaders)
})
.catch(err => {
if (err.name === "AbortError") {
console.log("Request cancelled");
return;
}
console.log("Error while making request: ", err);
handleError(endpointId, err);
})
.finally(() => {
executeBtn.disabled = false;
executeBtn.textContent = executeBtn.dataset.initialText;
});
}

View File

@@ -458,7 +458,49 @@ export default function App() {
<h2 className="text-3xl font-extrabold text-slate-900 mb-4 tracking-tight">Investasi Transparan UMKM</h2>
<p className="text-lg text-slate-600">Skema harga yang ramah di kantong tanpa biaya tersembunyi. Skalakan sesuai pertumbuhan bisnis Anda.</p>
</div>
<div className="grid md:grid-cols-3 gap-8 max-w-6xl mx-auto">
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8 max-w-6xl mx-auto">
{(window.plans && window.plans.length > 0) ? (
window.plans.map((plan, idx) => {
const isFeatured = window.plans.length === 3 ? idx === 1 : idx === window.plans.length - 1;
const features = typeof plan.features === 'string' ? JSON.parse(plan.features) : (plan.features || {});
return (
<div key={plan.id} className={`${isFeatured ? 'bg-teal-900 text-white transform md:-translate-y-4 shadow-2xl' : 'bg-white text-slate-900 border-slate-200 shadow-sm'} rounded-3xl p-8 border flex flex-col relative`}>
{isFeatured && <div className="bg-red-600 text-white px-4 py-1.5 rounded-full text-[10px] font-black uppercase w-max mb-4">Paling Laris</div>}
<h3 className={`text-xl font-extrabold mb-2 ${isFeatured ? 'text-white' : 'text-slate-900'}`}>{plan.subscriptionName}</h3>
<div className={`text-4xl font-black mb-6 pb-6 border-b ${isFeatured ? 'text-teal-400 border-teal-800' : 'text-slate-900 border-slate-100'}`}>
Rp {Number(plan.offerPrice || plan.subscriptionPrice).toLocaleString('id-ID')}
<span className={`text-sm font-medium ${isFeatured ? 'text-white' : 'text-slate-500'}`}> /{plan.duration === 'Monthly' ? 'bln' : (plan.duration === 'Yearly' ? 'thn' : plan.duration)}</span>
</div>
<ul className="space-y-4 mb-8 flex-1">
{Object.values(features).map((feat, fidx) => (
<li key={fidx} className="flex gap-2 text-sm font-medium">
{feat[1] === 'True' || feat[1] === true || feat[1] === '1' ? (
<CheckCircle className={`w-5 h-5 ${isFeatured ? 'text-teal-400' : 'text-teal-500'}`} />
) : (
<X className="w-5 h-5 opacity-50" />
)}
{feat[0]}
</li>
))}
</ul>
<button
type="button"
onClick={() => {
setSelectedPlan({ name: plan.subscriptionName, price: Number(plan.offerPrice || plan.subscriptionPrice) });
setCurrentPage('checkout');
window.scrollTo(0, 0);
}}
className={`w-full py-3 rounded-xl font-bold transition-all ${isFeatured ? 'bg-teal-500 text-teal-950 hover:bg-teal-400' : 'border-2 hover:border-teal-600 text-slate-700 hover:text-teal-600'}`}
>
Pilih {plan.subscriptionName}
</button>
</div>
);
})
) : (
/* Fallback if no plans in DB */
<>
{/* Basic */}
<div className="bg-white rounded-3xl p-8 border border-slate-200 flex flex-col shadow-sm">
<h3 className="text-xl font-extrabold text-slate-900 mb-2">Basic</h3>
@@ -467,7 +509,6 @@ export default function App() {
{["POS Full Features", "Inventory Management", "Finance & Accounting", "Purchase Management", "Warehouse Management", "3rd Party Management"].map(f => (
<li key={f} className="flex gap-2 text-sm font-medium"><CheckCircle className="w-5 h-5 text-teal-500" />{f}</li>
))}
<li className="flex gap-2 text-sm font-medium italic opacity-50"><X className="w-5 h-5" /> Multi-branch Allowed</li>
</ul>
<button
type="button"
@@ -507,6 +548,8 @@ export default function App() {
</ul>
<button className="w-full py-3 rounded-xl border-2 font-bold hover:bg-slate-50 transition-colors">Konsultasi Sales</button>
</div>
</>
)}
</div>
</div>
</section>

View File

@@ -6,6 +6,10 @@
<meta name="description" content="Kulakpos.id - Solusi Kasir Pintar (SaaS POS) Terlengkap dengan Teknologi AI Assistance untuk UMKM Naik Kelas.">
<title>KulakPOS | Solusi Kasir Pintar Berbasis AI</title>
@vite('resources/js/app.jsx')
<script>
window.plans = {!! json_encode($plans) !!};
</script>
<meta name="diagnostic" content="v2-dynamic-plans">
</head>
<body>
<div id="app"></div>

File diff suppressed because it is too large Load Diff

0
vendor/ageekdev/laravel-barcode/LICENSE.md vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/composer.json vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/config/barcode.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/AbstractGenerator.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Barcode.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/BarcodeBar.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/BarcodeManager.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/BarcodeServiceProvider.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Contracts/Factory.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Contracts/ImageType.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Drivers/DynamicHTML.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Drivers/HTML.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Drivers/JPG.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Drivers/PNG.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Drivers/SVG.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Enums/BarcodeType.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Enums/Type.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Exceptions/BarcodeException.php vendored Normal file → Executable file
View File

View File

View File

View File

View File

View File

0
vendor/ageekdev/laravel-barcode/src/Facades/Barcode.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Helpers/BarcodeHelper.php vendored Normal file → Executable file
View File

View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCodabar.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode11.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode128.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode128A.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode128B.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode128C.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode32.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode39.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode39Checksum.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode39Extended.php vendored Normal file → Executable file
View File

View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeCode93.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeEan13.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeEan8.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeEanUpcBase.php vendored Normal file → Executable file
View File

View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeInterface.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeInterleaved25.php vendored Normal file → Executable file
View File

View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeKix.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeMsi.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeMsiChecksum.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypePharmacode.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypePharmacodeTwoCode.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypePlanet.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypePostnet.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeRms4cc.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeStandard2of5.php vendored Normal file → Executable file
View File

View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeUpcA.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeUpcE.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeUpcExtension2.php vendored Normal file → Executable file
View File

0
vendor/ageekdev/laravel-barcode/src/Types/TypeUpcExtension5.php vendored Normal file → Executable file
View File

0
vendor/anandsiddharth/laravel-paytm-wallet/LICENSE vendored Normal file → Executable file
View File

0
vendor/anandsiddharth/laravel-paytm-wallet/README.md vendored Normal file → Executable file
View File

0
vendor/anandsiddharth/laravel-paytm-wallet/composer.json vendored Normal file → Executable file
View File

0
vendor/anandsiddharth/laravel-paytm-wallet/lib/encdec_paytm.php vendored Normal file → Executable file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

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