Skip to content

Commit

Permalink
Feature: CustomerQuestion
Browse files Browse the repository at this point in the history
  • Loading branch information
MilesChou committed Jul 10, 2023
1 parent 9f58877 commit 2e50f34
Show file tree
Hide file tree
Showing 26 changed files with 748 additions and 18 deletions.
2 changes: 2 additions & 0 deletions app/Http/Controllers/Admin/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\Product;
use App\Models\CustomerQuestion;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\View as ViewFactory;

Expand All @@ -16,6 +17,7 @@ public function dashboard(): View
'productsCount' => Product::count(),
'ordersCount' => Order::where('status', 'PENDING')->count(),
'readyToShipCount' => Order::where('status', 'READY TO SHIP')->count(),
'customerQueryCount' => CustomerQuestion::whereNUll('reply')->count(),
]);
}
}
27 changes: 27 additions & 0 deletions app/Http/Controllers/Admin/CustomerQuestion/MessDelete.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace App\Http\Controllers\Admin\CustomerQuestion;

use App\Models\CustomerQuestion;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use RealRashid\SweetAlert\Facades\Alert;

class MessDelete
{
public function __invoke(Request $request): RedirectResponse
{
$ids = $request->get('ids');

$questions = CustomerQuestion::whereIn('id', $ids)->get(['id']);

foreach ($questions as $order) {
$order->delete();
}

Alert::toast('Removed', 'success');

return Redirect::route('customerQuestion.adminView');
}
}
24 changes: 24 additions & 0 deletions app/Http/Controllers/Admin/CustomerQuestion/Reply.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace App\Http\Controllers\Admin\CustomerQuestion;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\ReplyCustomerQuestionRequest;
use App\Models\CustomerQuestion;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Redirect;

/**
* 管理者回應客戶的問題
*/
class Reply extends Controller
{
public function __invoke(CustomerQuestion $question, ReplyCustomerQuestionRequest $request): RedirectResponse
{
$question->update([
'reply' => $request->reply,
]);

return Redirect::route('customerQuestion.adminView');
}
}
19 changes: 19 additions & 0 deletions app/Http/Controllers/Admin/CustomerQuestion/ReplyView.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Controllers\Admin\CustomerQuestion;

use App\Models\CustomerQuestion;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\View as ViewFactory;

class ReplyView
{
public function __invoke($id): View
{
$question = CustomerQuestion::where('id', $id)
->with('user', 'product.productImage')
->first();

return ViewFactory::make('admin.customer.reply', compact('question'));
}
}
38 changes: 38 additions & 0 deletions app/Http/Controllers/Api/CustomerQuestionApi.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\CustomerQuestion;
use Yajra\DataTables\DataTables;

class CustomerQuestionApi extends Controller
{
public function __invoke()
{
$questions = CustomerQuestion::latest()->get();

return DataTables::of($questions)
->addColumn('select', function ($row) {
$item = '<input type="checkbox" name="ids[]" class="selectbox" value="' . $row->id . '">
';
return $item;
})
->addColumn('created_at', function ($row) {
return date('d/m/Y h:i A', strtotime($row->created_at));
})
->addColumn('reply', function ($row) {
$class = $row->reply ? 'text-danger' : 'text-danger';
$val = $row->reply ?? '<p class="' . $class . '">pending</p>';
return $val;
})
->addColumn('action', function ($row) {
$item = '<a href="/admin/customer-question/' . $row->id . '/reply" class="btn btn-sm btn-success">Reply</a>
';
return $item;
})

->rawColumns(['select', 'action', 'reply'])
->make(true);
}
}
28 changes: 28 additions & 0 deletions app/Http/Controllers/User/CustomerQuestion/Destroy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Http\Controllers\User\CustomerQuestion;

use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use RealRashid\SweetAlert\Facades\Alert;

/**
* DELETE /customer-question/{id}
*/
class Destroy
{
public function __invoke($id): RedirectResponse
{
/** @var User $user */
$user = Auth::user();
$user->questions()
->where('id', $id)
->delete();

Alert::toast('Deleted!', 'success');

return Redirect::route('customerQuestion.index');
}
}
26 changes: 26 additions & 0 deletions app/Http/Controllers/User/CustomerQuestion/Index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace App\Http\Controllers\User\CustomerQuestion;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\View as ViewFactory;

class Index extends Controller
{
public function __invoke(): View
{
/** @var User $user */
$user = Auth::user();

$questions = $user->questions()
->with('product')
->paginate(20);

return ViewFactory::make('customer-question.index')->with([
'questions' => $questions,
]);
}
}
32 changes: 32 additions & 0 deletions app/Http/Controllers/User/CustomerQuestion/Store.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Http\Controllers\User\CustomerQuestion;

use App\Models\CustomerQuestion;
use App\Models\Product;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;

/**
* POST /customer-question
*/
class Store
{
public function __invoke(Request $request): RedirectResponse
{
$request->validate([
'question' => 'required|max:255',
]);
//product imported to redirect to its path
$product = Product::findOrFail($request->product_id);

$question = new CustomerQuestion();
$question->user_id = auth()->user()->id;
$question->product_id = $request->product_id;
$question->question = $request->question;
$question->save();

return Redirect::to($product->path());
}
}
6 changes: 6 additions & 0 deletions app/Http/Controllers/User/ShowProduct.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ public function __invoke($id): View
->with('productImage')
->first();

$questions = $product
->getQuestions()
->with('user')
->paginate(6);

$mightAlsoLike = Product::where('id', '!=', $product->id)
->inRandomOrder()
->with('productImage')
Expand All @@ -28,6 +33,7 @@ public function __invoke($id): View

return ViewFactory::make('shop.show')->with([
'product' => $product,
'questions' => $questions,
'mightAlsoLike' => $mightAlsoLike
]);
}
Expand Down
23 changes: 23 additions & 0 deletions app/Http/Requests/Admin/ReplyCustomerQuestionRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App\Http\Requests\Admin;

use Illuminate\Foundation\Http\FormRequest;

/**
* @property string reply
*/
class ReplyCustomerQuestionRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}

public function rules(): array
{
return [
'reply' => 'required|max:255',
];
}
}
36 changes: 36 additions & 0 deletions app/Models/CustomerQuestion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
* @property int id
* @property int user_id
* @property int product_id
* @property string question
* @property string reply
* @property Carbon created_at
* @property Carbon updated_at
* @property Product product
* @property User user
*/
class CustomerQuestion extends Model
{
use HasFactory;

protected $guarded = [];

public function product(): BelongsTo
{
return $this->belongsTo(Product::class);
}

public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
7 changes: 6 additions & 1 deletion app/Models/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\URL;
Expand Down Expand Up @@ -54,6 +54,11 @@ public function getImage(): HasMany
return $this->productImage();
}

public function getQuestions(): HasMany
{
return $this->hasMany(CustomerQuestion::class);
}

public function scopeMightAlsoLike($query)
{
return $query->inRandomOrder()->with('first_image')->take(4);
Expand Down
5 changes: 5 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,9 @@ public function orders(): HasMany
{
return $this->hasMany(Order::class);
}

public function questions(): HasMany
{
return $this->hasMany(CustomerQuestion::class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCustomerQuestionsTable extends Migration
{
public function up(): void
{
Schema::create('customer_questions', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('product_id');
$table->string('question');
$table->string('reply')->nullable();
$table->timestamps();
});
}

public function down(): void
{
Schema::dropIfExists('customer_questions');
}
}
Loading

0 comments on commit 2e50f34

Please sign in to comment.