Initial commit
This commit is contained in:
73
resources/views/auth/login.blade.php
Normal file
73
resources/views/auth/login.blade.php
Normal file
@@ -0,0 +1,73 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Login') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('login') }}">
|
||||
@csrf
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
|
||||
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
|
||||
|
||||
<label class="form-check-label" for="remember">
|
||||
{{ __('Remember Me') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-0">
|
||||
<div class="col-md-8 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{{ __('Login') }}
|
||||
</button>
|
||||
|
||||
@if (Route::has('password.request'))
|
||||
<a class="btn btn-link" href="{{ route('password.request') }}">
|
||||
{{ __('Forgot Your Password?') }}
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
49
resources/views/auth/passwords/confirm.blade.php
Normal file
49
resources/views/auth/passwords/confirm.blade.php
Normal file
@@ -0,0 +1,49 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Confirm Password') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
{{ __('Please confirm your password before continuing.') }}
|
||||
|
||||
<form method="POST" action="{{ route('password.confirm') }}">
|
||||
@csrf
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
|
||||
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-0">
|
||||
<div class="col-md-8 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{{ __('Confirm Password') }}
|
||||
</button>
|
||||
|
||||
@if (Route::has('password.request'))
|
||||
<a class="btn btn-link" href="{{ route('password.request') }}">
|
||||
{{ __('Forgot Your Password?') }}
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
47
resources/views/auth/passwords/email.blade.php
Normal file
47
resources/views/auth/passwords/email.blade.php
Normal file
@@ -0,0 +1,47 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Reset Password') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
@if (session('status'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('password.email') }}">
|
||||
@csrf
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-0">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{{ __('Send Password Reset Link') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
65
resources/views/auth/passwords/reset.blade.php
Normal file
65
resources/views/auth/passwords/reset.blade.php
Normal file
@@ -0,0 +1,65 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Reset Password') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('password.update') }}">
|
||||
@csrf
|
||||
|
||||
<input type="hidden" name="token" value="{{ $token }}">
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus>
|
||||
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
|
||||
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-0">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{{ __('Reset Password') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
77
resources/views/auth/register.blade.php
Normal file
77
resources/views/auth/register.blade.php
Normal file
@@ -0,0 +1,77 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Register') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('register') }}">
|
||||
@csrf
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="name" class="col-md-4 col-form-label text-md-end">{{ __('Name') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>
|
||||
|
||||
@error('name')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">
|
||||
|
||||
@error('email')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
|
||||
|
||||
@error('password')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-0">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{{ __('Register') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
28
resources/views/auth/verify.blade.php
Normal file
28
resources/views/auth/verify.blade.php
Normal file
@@ -0,0 +1,28 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Verify Your Email Address') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
@if (session('resent'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ __('A fresh verification link has been sent to your email address.') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{ __('Before proceeding, please check your email for a verification link.') }}
|
||||
{{ __('If you did not receive the email') }},
|
||||
<form class="d-inline" method="POST" action="{{ route('verification.resend') }}">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-link p-0 m-0 align-baseline">{{ __('click here to request another') }}</button>.
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
46
resources/views/comments/create.blade.php
Normal file
46
resources/views/comments/create.blade.php
Normal file
@@ -0,0 +1,46 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-5">
|
||||
<h2>{{ isset($comment) ? 'Edit comment' : 'Manager Comment Section' }}</h2>
|
||||
@include('commons.notifications')
|
||||
<form action="{{ isset($comment) ? route('comments.update', $comment->id) : route('comments.store') }}" method="POST">
|
||||
<input type="hidden" name="user_id" value="{{ \Auth::user()->id }}">
|
||||
@csrf
|
||||
@if (isset($comment_body))
|
||||
@method('PUT')
|
||||
@endif
|
||||
<div class="card w-100">
|
||||
<div class="card-body">
|
||||
<h3>Project Details</h3>
|
||||
<h5 class="card-title">{{ $project_arr->project->name }}</h5>
|
||||
<p class="card-text">{{ $project_arr->project->description }} </p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<h3>Latest Update</h3>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Status Description</th>
|
||||
<th scope="col">Current Status</th>
|
||||
<th scope="col">Date Updated</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ $project_arr->description }}</td>
|
||||
<td>{{ $project_arr->status }}</td>
|
||||
<td>{{ $project_arr->created_at }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr>
|
||||
<div class="mb-3">
|
||||
<label for="commnetBody" class="form-label">Comment Body</label>
|
||||
<textarea class="form-control" id="commnetBody" name="comment_body" rows="4" required>{{ $comment->body ?? '' }}</textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Create comment</button>
|
||||
</form>
|
||||
</div>
|
||||
@endsection
|
||||
51
resources/views/comments/index.blade.php
Normal file
51
resources/views/comments/index.blade.php
Normal file
@@ -0,0 +1,51 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-10">
|
||||
@include('commons.notifications')
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Projects') }}</div>
|
||||
<div class="card-body">
|
||||
@if (session('status'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="float-end">
|
||||
<a href="/projects/create" class="btn btn-primary btn-sm">Add Projects</a>
|
||||
</div>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Description</th>
|
||||
<th scope="col">Status</th>
|
||||
<th scope="col">Date Created</th>
|
||||
<th scope="col">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $count = 1; ?>
|
||||
@foreach($projects as $row)
|
||||
<tr>
|
||||
<th scope="row">{{ $count }}</th>
|
||||
<td>{{ $row->name }}</td>
|
||||
<td>{{ $row->description }}</td>
|
||||
<td>{{ $row->status }}</td>
|
||||
<td>{{ $row->created_at }}</td>
|
||||
<td><a href="{{ url('project-status/add_status', $row->id)}}" class="btn btn-link">Add Status</a></td>
|
||||
</tr>
|
||||
<?php $count++; ?>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
18
resources/views/commons/notifications.blade.php
Normal file
18
resources/views/commons/notifications.blade.php
Normal file
@@ -0,0 +1,18 @@
|
||||
@if ($errors->any())
|
||||
<ul class="alert alert-danger" style="padding-left:10px; list-style-type: none;">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{!! $error !!}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
<!-- color: #fff; -->
|
||||
@if(Session::has('success_message'))
|
||||
<div style="text-align: center" class="alert alert-success notification-alert" style="">
|
||||
{{ Session::get('success_message') }}
|
||||
</div>
|
||||
@elseif(Session::has('error_message'))
|
||||
<div style="text-align: center" class="alert alert-danger notification-alert" style="">
|
||||
{{ Session::get('error_message') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
31
resources/views/dashboard/add_status.blade.php
Normal file
31
resources/views/dashboard/add_status.blade.php
Normal file
@@ -0,0 +1,31 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="container mt-5">
|
||||
<h2>{{ 'Add Project Status' }}</h2>
|
||||
@include('commons.notifications')
|
||||
<form action="{{ isset($project_status) ? route('project-status.update', $project_status->id) : route('project-status.store') }}" method="POST">
|
||||
<input type="hidden" name="assignee_id" value="{{ \Auth::user()->id }}">
|
||||
<input type="hidden" name="project_id" value="{{ $project->id }}">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="description" class="form-label">Description</label>
|
||||
<textarea class="form-control" name="description" id="description" rows="4" required></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="status" class="form-label">Status</label>
|
||||
<select class="form-select" id="status" name="status" required>
|
||||
<option value="" disabled>-- Select Status--</option>
|
||||
<option value="Pending">Pending</option>
|
||||
<option value="In Progress">In Progress</option>
|
||||
<option value="Completed">Completed</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">{{ 'Add Status' }}</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
67
resources/views/dashboard/details.blade.php
Normal file
67
resources/views/dashboard/details.blade.php
Normal file
@@ -0,0 +1,67 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h2>{{ $service->name }} — Subscriber Log</h2>
|
||||
<p class="text-muted mb-0">Schema Type: {{ strtoupper($service->schema_type) }} | Last Synced: {{ $service->last_synced_at ?? 'Never' }}</p>
|
||||
</div>
|
||||
<a href="{{ route('dashboard.index') }}" class="btn btn-outline-secondary">Back to Dashboard</a>
|
||||
</div>
|
||||
|
||||
<!-- Search Bar -->
|
||||
<form method="GET" action="{{ route('services.details', $service->id) }}" class="mb-4">
|
||||
<div class="input-group">
|
||||
<input type="text" name="search" class="form-control" placeholder="Search by phone number, content etc..." value="{{ request('search') }}">
|
||||
<button class="btn btn-primary" type="submit">Search</button>
|
||||
@if(request('search'))
|
||||
<a href="{{ route('services.details', $service->id) }}" class="btn btn-outline-dark">Reset</a>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Subscribers Table -->
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0 align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Phone Number</th>
|
||||
<th>Subscribed Content</th>
|
||||
<th>Status</th>
|
||||
<th>Join Date</th>
|
||||
<th>Last Synced</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($subscribers as $sub)
|
||||
<tr>
|
||||
<td class="fw-bold">{{ $sub->phone_number }}</td>
|
||||
<td><span class="badge bg-info text-dark">{{ $sub->content_name }}</span></td>
|
||||
<td>
|
||||
<span class="badge {{ $sub->status === 'active' ? 'bg-success' : 'bg-danger' }}">
|
||||
{{ ucfirst($sub->status) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ $sub->join_date ?? 'N/A' }}</td>
|
||||
<td class="text-muted small">{{ $sub->updated_at }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="text-center py-4 text-muted">No subscribers found.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pagination Links -->
|
||||
<div class="mt-4">
|
||||
{{ $subscribers->withQueryString()->links() }}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
57
resources/views/dashboard/index.blade.php
Normal file
57
resources/views/dashboard/index.blade.php
Normal file
@@ -0,0 +1,57 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-4">
|
||||
<h2 class="mb-4">Subscriptions Overview</h2>
|
||||
|
||||
<!-- Grand Totals Section -->
|
||||
<div class="row mb-5">
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-primary text-white shadow-sm">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title text-uppercase text-white-50">Total Subscribers (All Services)</h6>
|
||||
<h2 id="grand-total" class="mb-0">
|
||||
<span class="spinner-border spinner-border-sm" role="status"></span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-success text-white shadow-sm">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title text-uppercase text-white-50">Total Active</h6>
|
||||
<h2 id="grand-active" class="mb-0">
|
||||
<span class="spinner-border spinner-border-sm" role="status"></span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-secondary text-white shadow-sm">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title text-uppercase text-white-50">Total Inactive</h6>
|
||||
<h2 id="grand-inactive" class="mb-0">
|
||||
<span class="spinner-border spinner-border-sm" role="status"></span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mb-3 text-muted">Service Breakdown</h4>
|
||||
|
||||
<!-- Dynamic Service Cards Container -->
|
||||
<div class="row" id="service-cards-container">
|
||||
<!-- jQuery will inject the individual service cards here -->
|
||||
<div class="col-12 text-center py-5" id="loading-services">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
<p class="text-muted mt-2">Aggregating cross-service metrics...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@push('scripts')
|
||||
<script src="{{ asset('public/assets/js/dashboard.js') }}"></script>
|
||||
@endpush
|
||||
23
resources/views/home.blade.php
Normal file
23
resources/views/home.blade.php
Normal file
@@ -0,0 +1,23 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Dashboard') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
@if (session('status'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{ __('You are logged in!') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
81
resources/views/layouts/app.blade.php
Normal file
81
resources/views/layouts/app.blade.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<!doctype html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- CSRF Token -->
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>Click Content Management</title>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="dns-prefetch" href="//fonts.bunny.net">
|
||||
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
|
||||
|
||||
<!-- Scripts -->
|
||||
<link rel="stylesheet" href="{{ url('public/assets/libs/bootstrap/css/bootstrap5.3.2.css') }}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
|
||||
@stack('styles')
|
||||
<script>
|
||||
var base_url = "{!! url('/') !!}";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="#">CML</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="/">Home</a>
|
||||
</li>
|
||||
<!-- <li class="nav-item">
|
||||
<a class="nav-link" href="">Projects</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="">Project Statuses</a>
|
||||
</li>
|
||||
-->
|
||||
</ul>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" id="userDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
User Profile
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown">
|
||||
<li><a class="dropdown-item" href="#">My Profile</a></li>
|
||||
<li><a class="dropdown-item" href="#">Settings</a></li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('logout') }}"
|
||||
onclick="event.preventDefault();
|
||||
document.getElementById('logout-form').submit();">
|
||||
{{ __('Logout') }}
|
||||
</a>
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
|
||||
@csrf
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="py-4">
|
||||
@yield('content')
|
||||
</main>
|
||||
</div>
|
||||
@stack('modals')
|
||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
||||
<script src="{{ url('public/assets/libs/bootstrap/js/bootstrap5.3.2.js') }}" defer></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
@stack('scripts')
|
||||
</body>
|
||||
</html>
|
||||
51
resources/views/scraps.php
Normal file
51
resources/views/scraps.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{{ url('/') }}">Project Status Reporting</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<!-- Left Side Of Navbar -->
|
||||
<ul class="navbar-nav me-auto">
|
||||
|
||||
</ul>
|
||||
|
||||
<!-- Right Side Of Navbar -->
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<!-- Authentication Links -->
|
||||
@guest
|
||||
@if (Route::has('login'))
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@if (Route::has('register'))
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
|
||||
</li>
|
||||
@endif
|
||||
@else
|
||||
<li class="nav-item dropdown">
|
||||
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
|
||||
{{ Auth::user()->name }}
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
<a class="dropdown-item" href="{{ route('logout') }}"
|
||||
onclick="event.preventDefault();
|
||||
document.getElementById('logout-form').submit();">
|
||||
{{ __('Logout') }}
|
||||
</a>
|
||||
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
|
||||
@csrf
|
||||
</form>
|
||||
</div>
|
||||
</li>
|
||||
@endguest
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
198
resources/views/services/create.blade.php
Normal file
198
resources/views/services/create.blade.php
Normal file
@@ -0,0 +1,198 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h5 class="mb-0">Add New Subscription Service</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
{{-- Success Message --}}
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form action="{{ route('services.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="name" class="form-label">Service Name</label>
|
||||
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ old('name') }}" placeholder="e.g., Live Scores" required>
|
||||
@error('name')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="schema_type" class="form-label">Schema Type</label>
|
||||
<select class="form-select @error('schema_type') is-invalid @enderror" id="schema_type" name="schema_type" required>
|
||||
<option value="" disabled selected>Select schema format...</option>
|
||||
<option value="type_a" {{ old('schema_type') == 'type_a' ? 'selected' : '' }}>Type A (msisdn, is_active)</option>
|
||||
<option value="type_b" {{ old('schema_type') == 'type_b' ? 'selected' : '' }}>Type B (cell_number, sub_state)</option>
|
||||
</select>
|
||||
@error('schema_type')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h6 class="mb-3 text-muted">Database Connection</h6>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-8">
|
||||
<label for="db_host" class="form-label">Host / IP Address</label>
|
||||
<input type="text" class="form-control @error('db_host') is-invalid @enderror" id="db_host" name="db_host" value="{{ old('db_host') }}" required>
|
||||
@error('db_host')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="db_port" class="form-label">Port</label>
|
||||
<input type="number" class="form-control @error('db_port') is-invalid @enderror" id="db_port" name="db_port" value="{{ old('db_port', 3306) }}" required>
|
||||
@error('db_port')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<label for="db_name" class="form-label">Database Name</label>
|
||||
<input type="text" class="form-control @error('db_name') is-invalid @enderror" id="db_name" name="db_name" value="{{ old('db_name') }}" required>
|
||||
@error('db_name')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<label for="db_user" class="form-label">Database Username</label>
|
||||
<input type="text" class="form-control @error('db_user') is-invalid @enderror" id="db_user" name="db_user" value="{{ old('db_user') }}" required>
|
||||
@error('db_user')<div class="invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="db_password" class="form-label">Database Password</label>
|
||||
<div class="input-group">
|
||||
<input type="password" class="form-control @error('db_password') is-invalid @enderror" id="db_password" name="db_password" required>
|
||||
<button class="btn btn-outline-secondary" type="button" id="togglePassword">Show</button>
|
||||
</div>
|
||||
@error('db_password')<div class="d-block invalid-feedback">{{ $message }}</div>@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add this placeholder for the AJAX response just above the buttons -->
|
||||
<div id="test-connection-alert" class="alert d-none mb-4" role="alert"></div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<button type="button" id="testConnectionBtn" class="btn btn-outline-info">
|
||||
<span class="spinner-border spinner-border-sm d-none me-1" id="testSpinner" role="status" aria-hidden="true"></span>
|
||||
Test Connection
|
||||
</button>
|
||||
|
||||
<div>
|
||||
<button type="submit" class="btn btn-primary" id="saveServiceBtn" disabled>
|
||||
Save Subscription Service
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<small class="text-muted d-block text-end mt-1" id="saveHint">
|
||||
You must successfully test the connection before saving.
|
||||
</small>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Selectors for connection fields
|
||||
const connectionInputs = '#db_host, #db_port, #db_name, #db_user, #db_password';
|
||||
|
||||
// 1. Automatically re-disable the save button if ANY connection field is edited
|
||||
$(connectionInputs).on('input change', function() {
|
||||
$('#saveServiceBtn').prop('disabled', true);
|
||||
$('#saveHint').text('Connection parameters changed. Re-testing required before saving.')
|
||||
.removeClass('text-success')
|
||||
.addClass('text-muted');
|
||||
});
|
||||
|
||||
// 2. Toggle password visibility
|
||||
$('#togglePassword').on('click', function() {
|
||||
const passwordInput = $('#db_password');
|
||||
const type = passwordInput.attr('type') === 'password' ? 'text' : 'password';
|
||||
passwordInput.attr('type', type);
|
||||
$(this).text(type === 'password' ? 'Show' : 'Hide');
|
||||
});
|
||||
|
||||
// 3. Test Connection AJAX Logic
|
||||
$('#testConnectionBtn').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
let btn = $(this);
|
||||
let spinner = $('#testSpinner');
|
||||
let alertBox = $('#test-connection-alert');
|
||||
let saveBtn = $('#saveServiceBtn');
|
||||
let saveHint = $('#saveHint');
|
||||
|
||||
let payload = {
|
||||
db_host: $('#db_host').val(),
|
||||
db_port: $('#db_port').val(),
|
||||
db_name: $('#db_name').val(),
|
||||
db_user: $('#db_user').val(),
|
||||
db_password: $('#db_password').val(),
|
||||
_token: $('input[name="_token"]').val()
|
||||
};
|
||||
|
||||
if (!payload.db_host || !payload.db_name || !payload.db_user || !payload.db_password) {
|
||||
alertBox.removeClass('d-none alert-success alert-warning')
|
||||
.addClass('alert-danger')
|
||||
.text('Please fill out all database fields before testing.');
|
||||
return;
|
||||
}
|
||||
|
||||
btn.prop('disabled', true);
|
||||
spinner.removeClass('d-none');
|
||||
alertBox.addClass('d-none');
|
||||
|
||||
$.ajax({
|
||||
url: "{{ route('services.test') }}",
|
||||
method: 'POST',
|
||||
data: payload,
|
||||
success: function(response) {
|
||||
alertBox.removeClass('d-none alert-danger alert-warning')
|
||||
.addClass('alert-success')
|
||||
.text(response.message);
|
||||
|
||||
// ENABLE SAVE BUTTON
|
||||
saveBtn.prop('disabled', false);
|
||||
saveHint.text('Connection verified. Ready to save.')
|
||||
.removeClass('text-muted')
|
||||
.addClass('text-success');
|
||||
},
|
||||
error: function(xhr) {
|
||||
let errorMessage = xhr.responseJSON && xhr.responseJSON.message
|
||||
? xhr.responseJSON.message
|
||||
: 'An unexpected error occurred.';
|
||||
|
||||
alertBox.removeClass('d-none alert-success alert-warning')
|
||||
.addClass('alert-danger')
|
||||
.text(errorMessage);
|
||||
|
||||
// KEEP SAVE BUTTON DISABLED
|
||||
saveBtn.prop('disabled', true);
|
||||
saveHint.text('Connection failed. Fix credentials and test again.')
|
||||
.removeClass('text-success')
|
||||
.addClass('text-muted');
|
||||
},
|
||||
complete: function() {
|
||||
btn.prop('disabled', false);
|
||||
spinner.addClass('d-none');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
176
resources/views/welcome.blade.php
Normal file
176
resources/views/welcome.blade.php
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user