Sync
@@ -14,7 +14,7 @@ public static function getSiteSummary($parent_categories, $user_prompt, $model_m
|
||||
|
||||
$category_list = implode('|', $parent_categories->pluck('name')->toArray());
|
||||
|
||||
$system_prompt = "Based on the website content containing an AI tool, return a valid JSON containing:\n{\n\"is_ai_tool\":(true|false),\n\"ai_tool_name\":\"(AI Tool Name)\",\n\"is_app_web_both\":\"(app|web|both)\",\n\"tagline\":\"(One line tagline in 6-8 words)\",\n\"summary\": \"(Summary of AI tool in 2-3 parapgraphs, 140-180 words using grade 8 US english)\",\n\"pricing_type\": \"(Free|Free Trial|Freemium|Subscription|Usage Based)\",\n\"main_category\": \"(AI Training|Art|Audio|Avatars|Business|Chatbots|Coaching|Content Generation|Data|Dating|Design|Dev|Education|Emailing|Finance|Gaming|GPTs|Health|Legal|Marketing|Music|Networking|Personal Assistance|Planning|Podcasting|Productivity|Project Management|Prompting|Reporting|Research|Sales|Security|SEO|Shopping|Simulation|Social|Speech|Support|Task|Testing|Training|Translation|UI\/UX|Video|Workflow|Writing)\",\n\"keywords\":[\"(Identify relevant keywords for this AI Tool, 1-2 words each, at least)\"],\n\"qna\":[{\"q\":\"Typical FAQ that readers want to know, up to 5 questions\",\"a\":\"Answer of the question\"}]\n}";
|
||||
$system_prompt = "Based on the website content containing an AI tool, return a valid JSON containing:\n{\n\"is_ai_tool\":(true|false),\n\"ai_tool_name\":\"(AI Tool Name)\",\n\"is_app_web_both\":\"(app|web|both)\",\n\"tagline\":\"(One line tagline in 6-8 words)\",\n\"summary\": \"(Summary of AI tool in 2-3 parapgraphs, 200-240 words using grade 8 US english, start with AI tool name)\",\n\"pricing_type\": \"(Free|Free Trial|Freemium|Subscription|Usage Based)\",\n\"main_category\": \"(AI Training|Art|Audio|Avatars|Business|Chatbots|Coaching|Content Generation|Data|Dating|Design|Dev|Education|Emailing|Finance|Gaming|GPTs|Health|Legal|Marketing|Music|Networking|Personal Assistance|Planning|Podcasting|Productivity|Project Management|Prompting|Reporting|Research|Sales|Security|SEO|Shopping|Simulation|Social|Speech|Support|Task|Testing|Training|Translation|UI\/UX|Video|Workflow|Writing)\",\n\"keywords\":[\"(Identify relevant keywords for this AI Tool, 1-2 words each, at least)\"],\n\"qna\":[{\"q\":\"Typical FAQ that readers want to know, up to 5 questions\",\"a\":\"Answer of the question\"}]\n}";
|
||||
|
||||
return self::getChatCompletion($user_prompt, $system_prompt, $openai_config, $model_max_tokens, $timeout);
|
||||
}
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
require 'string_helper.php';
|
||||
require 'geo_helper.php';
|
||||
require 'proxy_helper.php';
|
||||
require 'route_helper.php';
|
||||
|
||||
13
app/Helpers/Global/route_helper.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
if (! function_exists('get_route_search_result')) {
|
||||
|
||||
function get_route_search_result($query)
|
||||
{
|
||||
|
||||
return route('front.search.results',
|
||||
[
|
||||
'query' => strtolower(urlencode($query)),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
if (! function_exists('epoch_now_timestamp')) {
|
||||
function epoch_now_timestamp()
|
||||
if (! function_exists('dmy')) {
|
||||
function dmy(Carbon $carbon)
|
||||
{
|
||||
return (int) round(microtime(true) * 1000);
|
||||
|
||||
return $carbon->format('d M Y');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('epoch_now_timestamp')) {
|
||||
function epoch_now_timestamp($multiplier = 1000)
|
||||
{
|
||||
return (int) round(microtime(true) * $multiplier);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('add_params_to_url')) {
|
||||
function add_params_to_url(string $url, array $newParams): string
|
||||
{
|
||||
$url = parse_url($url);
|
||||
parse_str($url['query'] ?? '', $existingParams);
|
||||
|
||||
$newQuery = array_merge($existingParams, $newParams);
|
||||
|
||||
$newUrl = $url['scheme'].'://'.$url['host'].($url['path'] ?? '');
|
||||
if ($newQuery) {
|
||||
$newUrl .= '?'.http_build_query($newQuery);
|
||||
}
|
||||
|
||||
if (isset($url['fragment'])) {
|
||||
$newUrl .= '#'.$url['fragment'];
|
||||
}
|
||||
|
||||
return $newUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +206,34 @@ function str_first_sentence($str)
|
||||
|
||||
}
|
||||
|
||||
if (! function_exists('str_extract_sentences')) {
|
||||
function str_extract_sentences($str, $count = 1)
|
||||
{
|
||||
// Split the string at ., !, or ?, including the punctuation in the result
|
||||
$sentences = preg_split('/([.!?])\s*/', $str, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
$extractedSentences = [];
|
||||
$currentSentence = '';
|
||||
|
||||
foreach ($sentences as $key => $sentence) {
|
||||
if ($key % 2 == 0) {
|
||||
// This is a sentence fragment
|
||||
$currentSentence = $sentence;
|
||||
} else {
|
||||
// This is a punctuation mark
|
||||
$currentSentence .= $sentence;
|
||||
$extractedSentences[] = trim($currentSentence);
|
||||
|
||||
if (count($extractedSentences) >= $count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $extractedSentences;
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('unslug')) {
|
||||
function unslug($slug, $delimiter = '-')
|
||||
{
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
namespace App\Http\Controllers\Front;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AiTool;
|
||||
use App\Models\Category;
|
||||
use Artesaos\SEOTools\Facades\SEOMeta;
|
||||
use Artesaos\SEOTools\Facades\SEOTools;
|
||||
use Illuminate\Http\Request;
|
||||
use JsonLd\Context;
|
||||
@@ -36,7 +38,7 @@ public function discover(Request $request, $category_slug = null)
|
||||
SEOTools::opengraph();
|
||||
SEOTools::jsonLd();
|
||||
SEOTools::setTitle($category->name.' AI Tools', false);
|
||||
//SEOTools::setDescription($description);
|
||||
//SEOTools::setDescription($description);
|
||||
} else {
|
||||
$breadcrumbs = collect([
|
||||
['name' => 'Home', 'url' => route('front.home')],
|
||||
@@ -65,6 +67,15 @@ public function discover(Request $request, $category_slug = null)
|
||||
'itemListElement' => $listItems,
|
||||
]);
|
||||
|
||||
return view('front.discover', compact('breadcrumbs', 'breadcrumb_context', 'category'));
|
||||
$ai_tools = AiTool::when(! is_null($category), function ($query) use ($category) {
|
||||
$query->where('category_id', $category->id);
|
||||
})
|
||||
->orderBy('updated_at', 'DESC')->paginate(6);
|
||||
|
||||
if ($ai_tools->count() <= 0) {
|
||||
SEOMeta::setRobots('noindex');
|
||||
}
|
||||
|
||||
return view('front.discover', compact('breadcrumbs', 'breadcrumb_context', 'category', 'ai_tools'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\Front;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AiTool;
|
||||
use Artesaos\SEOTools\Facades\SEOMeta;
|
||||
use Artesaos\SEOTools\Facades\SEOTools;
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
@@ -12,7 +13,9 @@ class FrontHomeController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
return view('front.home');
|
||||
$latest_ai_tools = AiTool::orderBy('created_at', 'DESC')->take(12)->get();
|
||||
|
||||
return view('front.home', compact('latest_ai_tools'));
|
||||
}
|
||||
|
||||
public function terms(Request $request)
|
||||
|
||||
@@ -2,9 +2,107 @@
|
||||
|
||||
namespace App\Http\Controllers\Front;
|
||||
|
||||
use App\Helpers\FirstParty\Aictio\Aictio;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\SearchEmbedding;
|
||||
use App\Models\SearchResult;
|
||||
use Artesaos\SEOTools\Facades\SEOTools;
|
||||
use Illuminate\Http\Request;
|
||||
use JsonLd\Context;
|
||||
|
||||
class FrontSearchController extends Controller
|
||||
{
|
||||
//
|
||||
public function search(Request $request)
|
||||
{
|
||||
if (is_empty($request->input('query'))) {
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
return redirect()->to(get_route_search_result($request->input('query')));
|
||||
}
|
||||
|
||||
public function searchResult(Request $request, $query)
|
||||
{
|
||||
if ($request->input('page') > 10) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
if (is_empty(trim($query))) {
|
||||
return abort(404);
|
||||
}
|
||||
|
||||
$query = trim($query);
|
||||
|
||||
$pagination_results = 10;
|
||||
|
||||
$search_result = SearchResult::where('query', $query)
|
||||
->orderBy('id', 'desc')
|
||||
->first();
|
||||
|
||||
$embedding = null;
|
||||
|
||||
if (! is_null($search_result) && ! is_null($search_result->embedding)) {
|
||||
$embedding = $search_result->embedding;
|
||||
$search_result->increment('counts');
|
||||
} else {
|
||||
$embedding = Aictio::getVectorEmbedding($query);
|
||||
|
||||
$search_result = new SearchResult;
|
||||
$search_result->query = $query;
|
||||
$search_result->counts = 1;
|
||||
$search_result->embedding = $embedding;
|
||||
|
||||
if ($search_result->save()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$results = SearchEmbedding::query()
|
||||
->with('ai_tool')
|
||||
->selectRaw('DISTINCT ON (ai_tool_id) ai_tool_id, embedding <-> ? AS distance', [$embedding])
|
||||
->orderBy('ai_tool_id')
|
||||
->orderByRaw('embedding <-> ? ASC', [$embedding])
|
||||
->whereRaw('embedding <-> ? < 0.65', [$embedding])
|
||||
->where('ai_tool_id', '!=', null)
|
||||
->paginate($pagination_results);
|
||||
|
||||
//dd($results->toArray());
|
||||
|
||||
if ($results->total() < $pagination_results) {
|
||||
// TODO: Signal Serp Crawling Engine
|
||||
}
|
||||
|
||||
$query = strtolower(urldecode($query));
|
||||
|
||||
session()->put('query', $query);
|
||||
|
||||
SEOTools::metatags();
|
||||
SEOTools::twitter();
|
||||
SEOTools::opengraph();
|
||||
SEOTools::jsonLd();
|
||||
SEOTools::setTitle(ucwords($query).' AI Tool');
|
||||
|
||||
$breadcrumbs = collect([
|
||||
['name' => 'Home', 'url' => route('front.home')],
|
||||
['name' => 'AI Tool Search', 'url' => null],
|
||||
['name' => ucwords($query), 'url' => null],
|
||||
]);
|
||||
|
||||
// breadcrumb json ld
|
||||
$listItems = [];
|
||||
|
||||
foreach ($breadcrumbs as $index => $breadcrumb) {
|
||||
$listItems[] = [
|
||||
'name' => $breadcrumb['name'],
|
||||
'url' => $breadcrumb['url'],
|
||||
];
|
||||
}
|
||||
|
||||
$breadcrumb_context = Context::create('breadcrumb_list', [
|
||||
'itemListElement' => $listItems,
|
||||
]);
|
||||
|
||||
return view('front.search_results', compact('results', 'query', 'breadcrumbs', 'breadcrumb_context'));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
81
app/Http/Controllers/Front/FrontToolController.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Front;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\JsonLd\FAQPage;
|
||||
use App\Models\AiTool;
|
||||
use Illuminate\Http\Request;
|
||||
use JsonLd\Context;
|
||||
use Artesaos\SEOTools\Facades\SEOTools;
|
||||
|
||||
class FrontToolController extends Controller
|
||||
{
|
||||
public function show(Request $request, $ai_tool_slug)
|
||||
{
|
||||
$ai_tool = AiTool::where('slug', $ai_tool_slug)->first();
|
||||
|
||||
if (is_null($ai_tool)) {
|
||||
return abort(404);
|
||||
}
|
||||
|
||||
$ai_tool->load('category');
|
||||
|
||||
$breadcrumbs = collect([
|
||||
['name' => 'Home', 'url' => route('front.home')],
|
||||
['name' => 'AI Tools', 'url' => route('front.discover.home')],
|
||||
['name' => $ai_tool->category->name, 'url' => route('front.discover.category', ['category_slug' => $ai_tool->category->slug])],
|
||||
['name' => $ai_tool->tool_name, 'url' => null],
|
||||
]);
|
||||
|
||||
// breadcrumb json ld
|
||||
$listItems = [];
|
||||
|
||||
foreach ($breadcrumbs as $index => $breadcrumb) {
|
||||
$listItems[] = [
|
||||
'name' => $breadcrumb['name'],
|
||||
'url' => $breadcrumb['url'],
|
||||
];
|
||||
}
|
||||
|
||||
$breadcrumb_context = Context::create('breadcrumb_list', [
|
||||
'itemListElement' => $listItems,
|
||||
]);
|
||||
|
||||
$applicationCategory = '';
|
||||
|
||||
if ($ai_tool->is_app_web_both == 'both') {
|
||||
$applicationCategory = 'App & Web Application';
|
||||
} else {
|
||||
$applicationCategory = ucwords($ai_tool->is_app_web_both).' Application';
|
||||
}
|
||||
|
||||
$qnaMainEntity = [];
|
||||
|
||||
foreach ($ai_tool->qna as $qna) {
|
||||
$qnaMainEntity[] = [
|
||||
'@type' => 'Question',
|
||||
'name' => $qna->q,
|
||||
'acceptedAnswer' => [
|
||||
'@type' => 'Answer',
|
||||
'text' => $qna->a,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
$faqData = [
|
||||
'mainEntity' => $qnaMainEntity,
|
||||
];
|
||||
|
||||
$faq_context = Context::create(FAQPage::class, $faqData);
|
||||
|
||||
SEOTools::metatags();
|
||||
SEOTools::twitter()->addImage($ai_tool->screenshot_img);
|
||||
SEOTools::opengraph()->addImage($ai_tool->screenshot_img);
|
||||
SEOTools::jsonLd()->addImage($ai_tool->screenshot_img);
|
||||
|
||||
//dd($faq_context);
|
||||
|
||||
return view('front.aitool', compact('ai_tool', 'breadcrumb_context', 'breadcrumbs', 'faq_context'));
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
use App\Helpers\FirstParty\OSSUploader\OSSUploader;
|
||||
use App\Models\AiTool;
|
||||
use App\Models\BusinessProfile;
|
||||
use App\Models\SerpUrl;
|
||||
use App\Models\UrlToCrawl;
|
||||
use Exception;
|
||||
use Image;
|
||||
@@ -13,25 +11,21 @@
|
||||
|
||||
class GetAIToolScreenshotTask
|
||||
{
|
||||
|
||||
public static function handle($url_to_crawl_id, $ai_tool_id)
|
||||
{
|
||||
$url_to_crawl = UrlToCrawl::find($url_to_crawl_id);
|
||||
|
||||
if (is_null($url_to_crawl))
|
||||
{
|
||||
return ;
|
||||
if (is_null($url_to_crawl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ai_tool = AiTool::find($ai_tool_id);
|
||||
|
||||
if (is_null($ai_tool))
|
||||
{
|
||||
return ;
|
||||
if (is_null($ai_tool)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36";
|
||||
|
||||
$userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36';
|
||||
|
||||
$browsershot = Browsershot::url($url_to_crawl->url)
|
||||
->timeout(30)
|
||||
|
||||
@@ -23,25 +23,29 @@ public static function handle(int $url_to_crawl_id)
|
||||
return null;
|
||||
}
|
||||
|
||||
$enable_proxy = false;
|
||||
|
||||
$url_to_crawl->is_crawling = true;
|
||||
$url_to_crawl->save();
|
||||
$url_to_crawl->refresh();
|
||||
|
||||
try {
|
||||
$user_agent = config('platform.proxy.user_agent');
|
||||
// try {
|
||||
$user_agent = config('platform.proxy.user_agent');
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'User-Agent' => $user_agent,
|
||||
$response = Http::withHeaders([
|
||||
'User-Agent' => $user_agent,
|
||||
])
|
||||
->withOptions([
|
||||
'proxy' => ($enable_proxy) ? get_smartproxy_rotating_server() : null,
|
||||
'timeout' => 10,
|
||||
'verify' => false,
|
||||
])
|
||||
->withOptions([
|
||||
'proxy' => get_smartproxy_rotating_server(),
|
||||
'timeout' => 10,
|
||||
'verify' => false,
|
||||
])
|
||||
->get($url_to_crawl->url);
|
||||
->get($url_to_crawl->url);
|
||||
|
||||
if ($response->successful()) {
|
||||
$raw_html = $response->body();
|
||||
if ($response->successful()) {
|
||||
$raw_html = $response->body();
|
||||
if ($enable_proxy)
|
||||
{
|
||||
$cost = calculate_smartproxy_cost(round(strlen($raw_html) / 1024, 2), 'rotating_global');
|
||||
|
||||
$service_cost_usage = new ServiceCostUsage;
|
||||
@@ -51,17 +55,19 @@ public static function handle(int $url_to_crawl_id)
|
||||
$service_cost_usage->reference_2 = strval($url_to_crawl_id);
|
||||
$service_cost_usage->output = self::getMarkdownFromHtml($raw_html);
|
||||
$service_cost_usage->save();
|
||||
|
||||
} else {
|
||||
$raw_html = null;
|
||||
$response->throw();
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
} else {
|
||||
$raw_html = null;
|
||||
//throw $e;
|
||||
$response->throw();
|
||||
}
|
||||
|
||||
// } catch (Exception $e) {
|
||||
// $raw_html = null;
|
||||
// //throw $e;
|
||||
// }
|
||||
|
||||
if (! is_empty($raw_html)) {
|
||||
$url_to_crawl->output_type = 'markdown';
|
||||
$url_to_crawl->output = self::getMarkdownFromHtml($raw_html);
|
||||
|
||||
@@ -65,23 +65,28 @@ public static function handle(int $url_to_crawl_id)
|
||||
$ai_tool->url_to_crawl_id = $url_to_crawl->id;
|
||||
}
|
||||
|
||||
$ai_tool->external_url = $url_to_crawl->url;
|
||||
|
||||
// Tool Name
|
||||
if ((isset($url_meta_response->output->tool_name)) && (! is_empty($url_meta_response->output->tool_name))) {
|
||||
$ai_tool->tool_name = $url_meta_response->output->tool_name;
|
||||
if ((isset($url_meta_response->output->ai_tool_name)) && (! is_empty($url_meta_response->output->ai_tool_name))) {
|
||||
$ai_tool->tool_name = $url_meta_response->output->ai_tool_name;
|
||||
$ai_tool->slug = epoch_now_timestamp(1).'-'.str_slug($url_meta_response->output->ai_tool_name);
|
||||
} else {
|
||||
throw new Exception('OpenAI::getSiteSummary failed, no tool name');
|
||||
}
|
||||
|
||||
// Is AI Tool
|
||||
if ((isset($url_meta_response->output->is_ai_tool)) && (! is_null($url_meta_response->output->is_at_tool)) && is_bool($url_meta_response->output->is_ai_tool)) {
|
||||
if ((isset($url_meta_response->output->is_ai_tool)) && (! is_null($url_meta_response->output->is_ai_tool)) && is_bool($url_meta_response->output->is_ai_tool)) {
|
||||
$ai_tool->is_ai_tool = $url_meta_response->output->is_ai_tool;
|
||||
} else {
|
||||
$ai_tool->is_ai_tool = true;
|
||||
}
|
||||
|
||||
// Is App/Web/Both
|
||||
if ((isset($url_meta_response->output->is_app_web_both)) && (is_array($url_meta_response->output->is_app_web_both)) && in_array($url_meta_response->output->is_app_web_both, ['app', 'web', 'both'])) {
|
||||
if ((isset($url_meta_response->output->is_app_web_both)) && (! is_empty($url_meta_response->output->is_app_web_both)) && in_array($url_meta_response->output->is_app_web_both, ['app', 'web', 'both'])) {
|
||||
$ai_tool->is_app_web_both = $url_meta_response->output->is_app_web_both;
|
||||
} else {
|
||||
$ai_tool->is_app_web_both = 'web';
|
||||
}
|
||||
|
||||
// Tagline
|
||||
@@ -130,9 +135,8 @@ public static function handle(int $url_to_crawl_id)
|
||||
|
||||
$query = $ai_tool->tool_name;
|
||||
|
||||
if (!is_empty($ai_tool->tagline))
|
||||
{
|
||||
$query .= ": " . $ai_tool->tagline;
|
||||
if (! is_empty($ai_tool->tagline)) {
|
||||
$query .= ': '.$ai_tool->tagline;
|
||||
}
|
||||
|
||||
StoreSearchEmbeddingJob::dispatch(
|
||||
@@ -176,8 +180,7 @@ public static function handle(int $url_to_crawl_id)
|
||||
|
||||
// Q&A
|
||||
if ((isset($url_meta_response->output->qna)) && (is_array($url_meta_response->output->qna))) {
|
||||
foreach ($url_meta_response->output->qna as $qna)
|
||||
{
|
||||
foreach ($url_meta_response->output->qna as $qna) {
|
||||
$q = $qna->q;
|
||||
$a = $qna->a;
|
||||
|
||||
@@ -187,7 +190,7 @@ public static function handle(int $url_to_crawl_id)
|
||||
'qna',
|
||||
$ai_tool->category_id,
|
||||
$ai_tool->id,
|
||||
($qna->q . " " . $qna->a)
|
||||
($qna->q.' '.$qna->a)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
17
app/JsonLd/FAQPage.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\JsonLd;
|
||||
|
||||
use JsonLd\ContextTypes\AbstractContext;
|
||||
|
||||
class FAQPage extends AbstractContext
|
||||
{
|
||||
protected $structure = [
|
||||
'mainEntity' => [],
|
||||
];
|
||||
|
||||
protected function setMainEntityAttribute($value)
|
||||
{
|
||||
return (array) $value;
|
||||
}
|
||||
}
|
||||
77
app/JsonLd/SoftwareApplication.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\JsonLd;
|
||||
|
||||
use JsonLd\ContextTypes\AbstractContext;
|
||||
use JsonLd\ContextTypes\ImageObject;
|
||||
|
||||
class SoftwareApplication extends AbstractContext
|
||||
{
|
||||
/**
|
||||
* Property structure
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $structure = [
|
||||
'name' => null,
|
||||
'description' => null,
|
||||
'url' => null,
|
||||
'applicationCategory' => null,
|
||||
'screenshot' => ImageObject::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Set the name attribute.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function setNameAttribute($value)
|
||||
{
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the description attribute.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function setDescriptionAttribute($value)
|
||||
{
|
||||
return $this->truncate($value, 260);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the url attribute.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function setUrlAttribute($value)
|
||||
{
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the application category attribute.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function setApplicationCategoryAttribute($value)
|
||||
{
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the screenshot attribute.
|
||||
*
|
||||
* @param ImageObject|array $value
|
||||
* @return ImageObject
|
||||
*/
|
||||
protected function setScreenshotAttribute($value)
|
||||
{
|
||||
return new ImageObject([$value]);
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,14 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* Class AiTool
|
||||
*
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $category_id
|
||||
* @property int $url_to_crawl_id
|
||||
@@ -27,56 +29,72 @@
|
||||
* @property string|null $qna
|
||||
* @property Carbon|null $created_at
|
||||
* @property Carbon|null $updated_at
|
||||
*
|
||||
* @property Category $category
|
||||
* @property UrlToCrawl $url_to_crawl
|
||||
* @property Collection|SearchEmbedding[] $search_embeddings
|
||||
* @property Collection|AiToolKeyword[] $ai_tool_keywords
|
||||
*
|
||||
* @package App\Models
|
||||
*/
|
||||
class AiTool extends Model
|
||||
{
|
||||
protected $table = 'ai_tools';
|
||||
protected $table = 'ai_tools';
|
||||
|
||||
protected $casts = [
|
||||
'category_id' => 'int',
|
||||
'url_to_crawl_id' => 'int',
|
||||
'is_ai_tool' => 'bool',
|
||||
'qna' => 'object'
|
||||
];
|
||||
protected $casts = [
|
||||
'category_id' => 'int',
|
||||
'url_to_crawl_id' => 'int',
|
||||
'view_count' => 'int',
|
||||
'is_ai_tool' => 'bool',
|
||||
'qna' => 'object',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'category_id',
|
||||
'url_to_crawl_id',
|
||||
'screenshot_img',
|
||||
'is_ai_tool',
|
||||
'tool_name',
|
||||
'is_app_web_both',
|
||||
'tagline',
|
||||
'summary',
|
||||
'pricing_type',
|
||||
'keyword_string',
|
||||
'qna'
|
||||
];
|
||||
protected $fillable = [
|
||||
'category_id',
|
||||
'url_to_crawl_id',
|
||||
'screenshot_img',
|
||||
'is_ai_tool',
|
||||
'tool_name',
|
||||
'slug',
|
||||
'is_app_web_both',
|
||||
'tagline',
|
||||
'summary',
|
||||
'pricing_type',
|
||||
'keyword_string',
|
||||
'view_count',
|
||||
'qna',
|
||||
'external_url
|
||||
',
|
||||
];
|
||||
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(Category::class);
|
||||
}
|
||||
protected function screenshotImg(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: function ($value = null) {
|
||||
if (! is_empty($value)) {
|
||||
|
||||
public function url_to_crawl()
|
||||
{
|
||||
return $this->belongsTo(UrlToCrawl::class);
|
||||
}
|
||||
return Storage::disk(config('platform.uploads.ai_tools.screenshot.driver'))->url(config('platform.uploads.ai_tools.screenshot.path').$value);
|
||||
}
|
||||
|
||||
public function search_embeddings()
|
||||
{
|
||||
return $this->hasMany(SearchEmbedding::class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function ai_tool_keywords()
|
||||
{
|
||||
return $this->hasMany(AiToolKeyword::class);
|
||||
}
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(Category::class);
|
||||
}
|
||||
|
||||
public function url_to_crawl()
|
||||
{
|
||||
return $this->belongsTo(UrlToCrawl::class);
|
||||
}
|
||||
|
||||
public function search_embeddings()
|
||||
{
|
||||
return $this->hasMany(SearchEmbedding::class);
|
||||
}
|
||||
|
||||
public function keywords()
|
||||
{
|
||||
return $this->hasMany(AiToolKeyword::class);
|
||||
}
|
||||
}
|
||||
|
||||
41
app/Models/SearchResult.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Created by Reliese Model.
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Pgvector\Laravel\Vector;
|
||||
|
||||
/**
|
||||
* Class SearchResult
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $query
|
||||
* @property USER-DEFINED|null $embedding
|
||||
* @property Carbon|null $indexed_at
|
||||
* @property int $counts
|
||||
* @property string $country_iso
|
||||
* @property Carbon|null $created_at
|
||||
* @property Carbon|null $updated_at
|
||||
*/
|
||||
class SearchResult extends Model
|
||||
{
|
||||
protected $table = 'search_results';
|
||||
|
||||
protected $casts = [
|
||||
'embedding' => Vector::class,
|
||||
'indexed_at' => 'datetime',
|
||||
'counts' => 'int',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'query',
|
||||
'embedding',
|
||||
'indexed_at',
|
||||
'counts',
|
||||
];
|
||||
}
|
||||
@@ -29,7 +29,7 @@ class ServiceCostUsage extends Model
|
||||
|
||||
protected $casts = [
|
||||
'cost' => 'float',
|
||||
'output' => 'binary',
|
||||
'output' => 'object',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"laravel/tinker": "^2.8",
|
||||
"laravel/ui": "^4.0",
|
||||
"league/flysystem-aws-s3-v3": "^3.0",
|
||||
"league/html-to-markdown": "^5.1",
|
||||
"masterminds/html5": "^2.8",
|
||||
"mews/purifier": "^3.4",
|
||||
"pfaciana/tiny-html-minifier": "^3.0",
|
||||
|
||||
91
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2b41c19d85eb74a7fb7b976437ef4861",
|
||||
"content-hash": "84f90f6b5010de195dcd0fead0d21daf",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alaminfirdows/laravel-editorjs",
|
||||
@@ -3516,6 +3516,95 @@
|
||||
},
|
||||
"time": "2023-07-08T06:26:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/html-to-markdown",
|
||||
"version": "5.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/html-to-markdown.git",
|
||||
"reference": "0b4066eede55c48f38bcee4fb8f0aa85654390fd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/0b4066eede55c48f38bcee4fb8f0aa85654390fd",
|
||||
"reference": "0b4066eede55c48f38bcee4fb8f0aa85654390fd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-xml": "*",
|
||||
"php": "^7.2.5 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikehaertl/php-shellcommand": "^1.1.0",
|
||||
"phpstan/phpstan": "^1.8.8",
|
||||
"phpunit/phpunit": "^8.5 || ^9.2",
|
||||
"scrutinizer/ocular": "^1.6",
|
||||
"unleashedtech/php-coding-standard": "^2.7 || ^3.0",
|
||||
"vimeo/psalm": "^4.22 || ^5.0"
|
||||
},
|
||||
"bin": [
|
||||
"bin/html-to-markdown"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\HTMLToMarkdown\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Nick Cernis",
|
||||
"email": "nick@cern.is",
|
||||
"homepage": "http://modernnerd.net",
|
||||
"role": "Original Author"
|
||||
}
|
||||
],
|
||||
"description": "An HTML-to-markdown conversion helper for PHP",
|
||||
"homepage": "https://github.com/thephpleague/html-to-markdown",
|
||||
"keywords": [
|
||||
"html",
|
||||
"markdown"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/thephpleague/html-to-markdown/issues",
|
||||
"source": "https://github.com/thephpleague/html-to-markdown/tree/5.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.colinodell.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.paypal.me/colinpodell/10.00",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/colinodell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/league/html-to-markdown",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-12T21:21:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/mime-type-detection",
|
||||
"version": "1.14.0",
|
||||
|
||||
@@ -6,4 +6,42 @@
|
||||
'api_key' => env('OPENAI_API_KEY'),
|
||||
],
|
||||
|
||||
// GPT 4
|
||||
'openai-gpt-4-turbo' => [
|
||||
'tokens' => 128000,
|
||||
'model' => 'gpt-4-1106-preview',
|
||||
'input_cost_per_thousand_tokens' => 0.01,
|
||||
'output_cost_per_thousand_tokens' => 0.03,
|
||||
],
|
||||
|
||||
'openai-gpt-4' => [
|
||||
'tokens' => 8192,
|
||||
'model' => 'gpt-4-0613',
|
||||
'input_cost_per_thousand_tokens' => 0.03,
|
||||
'output_cost_per_thousand_tokens' => 0.06,
|
||||
],
|
||||
|
||||
// GPT 3.5
|
||||
|
||||
'openai-gpt-3-5-turbo-1106' => [
|
||||
'tokens' => 16385,
|
||||
'model' => 'gpt-3.5-turbo-1106',
|
||||
'input_cost_per_thousand_tokens' => 0.0010,
|
||||
'output_cost_per_thousand_tokens' => 0.002,
|
||||
],
|
||||
|
||||
'openai-3-5-turbo' => [
|
||||
'tokens' => 4096,
|
||||
'model' => 'gpt-3.5-turbo',
|
||||
'input_cost_per_thousand_tokens' => 0.0015,
|
||||
'output_cost_per_thousand_tokens' => 0.002,
|
||||
],
|
||||
|
||||
'openai-3-5-turbo-16k' => [
|
||||
'tokens' => 16385,
|
||||
'model' => 'gpt-3.5-turbo-16k',
|
||||
'input_cost_per_thousand_tokens' => 0.003,
|
||||
'output_cost_per_thousand_tokens' => 0.004,
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -11,9 +11,12 @@
|
||||
'defaults' => [
|
||||
'title' => 'AI Buddy Tools', // set false to total remove
|
||||
'titleBefore' => false, // Put defaults.title before page title, like 'It's Over 9000! - Dashboard'
|
||||
'description' => 'The leading AI tools directory and search engine, Discover the best AI tools, apps and services list and take your business to the next level.', // set false to total remove
|
||||
'description' => 'Your friendly AI tool directory platform. Discover AI Tools for any task!', // set false to total remove
|
||||
'separator' => ' - ',
|
||||
'keywords' => [],
|
||||
'keywords' => [
|
||||
'ai tools directory',
|
||||
'yellow page ai tools',
|
||||
],
|
||||
'canonical' => 'full', // Set to null or 'full' to use Url::full(), set to 'current' to use Url::current(), set false to total remove
|
||||
'robots' => false, // Set to 'all', 'none' or any combination of index/noindex and follow/nofollow
|
||||
],
|
||||
@@ -36,12 +39,16 @@
|
||||
* The default configurations to be used by the opengraph generator.
|
||||
*/
|
||||
'defaults' => [
|
||||
'title' => 'AI Buddy Tools', // set false to total remove
|
||||
'description' => 'The leading AI tools directory and search engine, Discover the best AI tools, apps and services list and take your business to the next level.', // set false to total remove
|
||||
'url' => false, // Set null for using Url::current(), set false to total remove
|
||||
'title' => 'AI Buddy Tool', // set false to total remove
|
||||
'description' => 'Your friendly AI tool directory platform. Discover AI Tools for any task!', // set false to total remove
|
||||
'url' => null, // Set null for using Url::current(), set false to total remove
|
||||
'type' => false,
|
||||
'site_name' => false,
|
||||
'images' => [],
|
||||
'site_name' => 'AI Buddy Tool',
|
||||
'images' => [
|
||||
'https://cdn.aibuddytool.com/aibuddytool-og.webp',
|
||||
'https://cdn.aibuddytool.com/aibuddytool-og.png',
|
||||
'https://cdn.aibuddytool.com/aibuddytool-og.jpg'
|
||||
],
|
||||
],
|
||||
],
|
||||
'twitter' => [
|
||||
@@ -58,11 +65,15 @@
|
||||
* The default configurations to be used by the json-ld generator.
|
||||
*/
|
||||
'defaults' => [
|
||||
'title' => 'AI Buddy Tools', // set false to total remove
|
||||
'description' => 'The leading AI tools directory and search engine, Discover the best AI tools, apps and services list and take your business to the next level.', // set false to total remove
|
||||
'url' => false, // Set to null or 'full' to use Url::full(), set to 'current' to use Url::current(), set false to total remove
|
||||
'title' => 'AI Buddy Tool', // set false to total remove
|
||||
'description' => 'Your friendly AI tool directory platform. Discover AI Tools for any task!', // set false to total remove
|
||||
'url' => 'current', // Set to null or 'full' to use Url::full(), set to 'current' to use Url::current(), set false to total remove
|
||||
'type' => 'WebPage',
|
||||
'images' => [],
|
||||
'images' => [
|
||||
'https://cdn.aibuddytool.com/aibuddytool-og.webp',
|
||||
'https://cdn.aibuddytool.com/aibuddytool-og.png',
|
||||
'https://cdn.aibuddytool.com/aibuddytool-og.jpg'
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -17,10 +17,14 @@ public function up(): void
|
||||
$table->foreignId('category_id');
|
||||
$table->foreignId('url_to_crawl_id');
|
||||
|
||||
$table->string('view_count')->default(0);
|
||||
|
||||
$table->string('screenshot_img')->nullable();
|
||||
|
||||
$table->boolean('is_ai_tool')->default(true);
|
||||
$table->string('tool_name');
|
||||
$table->string('slug');
|
||||
$table->string('external_url');
|
||||
|
||||
$table->string('is_app_web_both');
|
||||
$table->text('tagline')->nullable();
|
||||
@@ -32,6 +36,9 @@ public function up(): void
|
||||
|
||||
$table->foreign('category_id')->references('id')->on('categories');
|
||||
$table->foreign('url_to_crawl_id')->references('id')->on('url_to_crawls');
|
||||
|
||||
$table->index('view_count');
|
||||
$table->index('slug');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ public function up(): void
|
||||
|
||||
$table->foreign('category_id')->references('id')->on('categories');
|
||||
$table->foreign('ai_tool_id')->references('id')->on('ai_tools');
|
||||
|
||||
$table->index('ai_tool_id');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
@@ -25,7 +26,11 @@ public function up(): void
|
||||
|
||||
$table->foreign('ai_tool_id')->references('id')->on('ai_tools');
|
||||
$table->foreign('category_id')->references('id')->on('categories');
|
||||
|
||||
});
|
||||
|
||||
DB::statement('CREATE INDEX search_embeddings_embedding_idx ON search_embeddings USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('search_results', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('query');
|
||||
$table->vector('embedding', 384)->nullable();
|
||||
$table->datetime('indexed_at')->nullable();
|
||||
$table->bigInteger('counts')->default(1);
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
DB::statement('CREATE INDEX search_results_embedding_idx ON search_results USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('search_results');
|
||||
}
|
||||
};
|
||||
@@ -45,8 +45,8 @@ public function run(): void
|
||||
['name' => 'Content Generation', 'emoji' => '📝', 'is_top' => true],
|
||||
['name' => 'Support', 'emoji' => '🛠️', 'is_top' => false],
|
||||
['name' => 'Health', 'emoji' => '🍏', 'is_top' => false],
|
||||
['name' => 'Networking', 'emoji' => '🔗', 'is_top' => false],
|
||||
['name' => 'Personal Assistance', 'emoji' => '🤝', 'is_top' => false],
|
||||
['name' => 'Networking', 'emoji' => '🤝', 'is_top' => false],
|
||||
['name' => 'Personal Assistance', 'emoji' => '📱', 'is_top' => false],
|
||||
['name' => 'Planning', 'emoji' => '📅', 'is_top' => false],
|
||||
['name' => 'Project Management', 'emoji' => '📈', 'is_top' => false],
|
||||
['name' => 'Reporting', 'emoji' => '📑', 'is_top' => false],
|
||||
|
||||
BIN
public/ai-buddy-tool-logo-1024x1024.png
Normal file
|
After Width: | Height: | Size: 423 KiB |
59
public/ai-buddy-tool-logo-1024x1024.svg
Normal file
@@ -0,0 +1,59 @@
|
||||
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_i_69_81)">
|
||||
<path d="M76 350.806C76 287.944 127.091 236.984 190.116 236.984H834.868C897.893 236.984 948.984 287.944 948.984 350.806V845.932C948.984 908.794 897.893 959.754 834.868 959.754H190.116C127.091 959.754 76 908.794 76 845.932V350.806Z" fill="url(#paint0_linear_69_81)"/>
|
||||
</g>
|
||||
<g filter="url(#filter1_i_69_81)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M834.868 288.204H190.116C155.452 288.204 127.352 316.232 127.352 350.806V845.932C127.352 880.506 155.452 908.534 190.116 908.534H834.868C869.532 908.534 897.632 880.506 897.632 845.932V350.806C897.632 316.232 869.532 288.204 834.868 288.204ZM190.116 236.984C127.091 236.984 76 287.944 76 350.806V845.932C76 908.794 127.091 959.754 190.116 959.754H834.868C897.893 959.754 948.984 908.794 948.984 845.932V350.806C948.984 287.944 897.893 236.984 834.868 236.984H190.116Z" fill="#4C1683"/>
|
||||
</g>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M470.947 703.166C461.179 683.45 437.427 675.461 417.891 685.318C398.356 695.176 390.438 719.145 400.205 738.861C422.942 784.752 474.419 800.832 514.669 800.832C554.92 800.832 606.397 784.752 629.132 738.861C638.9 719.145 630.983 695.176 611.447 685.318C591.911 675.461 568.16 683.45 558.392 703.166C554.765 710.485 540.327 721.013 514.669 721.013C489.012 721.013 474.573 710.485 470.947 703.166Z" fill="url(#paint1_linear_69_81)"/>
|
||||
<path d="M805.301 517.82C805.301 579.139 755.592 628.848 694.273 628.848C632.954 628.848 583.245 579.139 583.245 517.82C583.245 456.501 632.954 406.792 694.273 406.792C755.592 406.792 805.301 456.501 805.301 517.82Z" fill="#4C1683"/>
|
||||
<path d="M441.739 517.82C441.739 579.139 392.03 628.848 330.711 628.848C269.392 628.848 219.684 579.139 219.684 517.82C219.684 456.501 269.392 406.792 330.711 406.792C392.03 406.792 441.739 456.501 441.739 517.82Z" fill="#4F1689"/>
|
||||
<path d="M766.114 518.908C766.114 557.984 734.437 589.661 695.361 589.661C656.286 589.661 624.608 557.984 624.608 518.908C624.608 479.832 656.286 448.155 695.361 448.155C734.437 448.155 766.114 479.832 766.114 518.908Z" fill="url(#paint2_radial_69_81)"/>
|
||||
<path d="M400.376 518.908C400.376 557.984 368.699 589.661 329.623 589.661C290.547 589.661 258.87 557.984 258.87 518.908C258.87 479.832 290.547 448.155 329.623 448.155C368.699 448.155 400.376 479.832 400.376 518.908Z" fill="url(#paint3_radial_69_81)"/>
|
||||
<path d="M491.18 218.192H436.449L448.051 184.106H478.317L433.549 65H487.901L554.612 236.984H498.242L491.18 218.192ZM421.569 236.984H367.721L427.496 72.7762L452.213 141.077L421.569 236.984Z" fill="#4C1683"/>
|
||||
<path d="M567.98 200.306H584.752V101.548H567.98V65H657.264V101.548H640.492V200.306H657.264V236.984H567.98V200.306Z" fill="#4C1683"/>
|
||||
<defs>
|
||||
<filter id="filter0_i_69_81" x="76" y="236.984" width="872.984" height="722.77" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="19.1"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0897572 0 0 0 0 0.669632 0 0 0 0 0.852751 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_69_81"/>
|
||||
</filter>
|
||||
<filter id="filter1_i_69_81" x="76" y="236.984" width="872.984" height="722.77" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="19.1"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0897572 0 0 0 0 0.669632 0 0 0 0 0.852751 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_69_81"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_69_81" x1="948.984" y1="575.605" x2="76" y2="575.605" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F1EBFF"/>
|
||||
<stop offset="0.213542" stop-color="#F6F9FF"/>
|
||||
<stop offset="0.5" stop-color="#FDFDFD"/>
|
||||
<stop offset="0.776042" stop-color="#F3F5FB"/>
|
||||
<stop offset="1" stop-color="#F7F5FC"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_69_81" x1="131.42" y1="198.15" x2="882.425" y2="913.703" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3088FF"/>
|
||||
<stop offset="0.479167" stop-color="#6213B1"/>
|
||||
<stop offset="1" stop-color="#2C1B3D"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="paint2_radial_69_81" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(695.361 518.908) rotate(90) scale(70.753 70.7531)">
|
||||
<stop stop-color="#EDEDED"/>
|
||||
<stop offset="0.0001" stop-color="#FFFFF3"/>
|
||||
<stop offset="1" stop-color="#F3D223"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint3_radial_69_81" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(329.623 518.908) rotate(90) scale(70.753 70.7531)">
|
||||
<stop stop-color="#EDEDED"/>
|
||||
<stop offset="0.0001" stop-color="#FFFFF3"/>
|
||||
<stop offset="1" stop-color="#F3D223"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
BIN
public/ai-buddy-tool-logo-512x512.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
64
public/ai-buddy-tool-logo-512x512.svg
Normal file
@@ -0,0 +1,64 @@
|
||||
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_69_69)">
|
||||
<g filter="url(#filter0_i_69_69)">
|
||||
<path d="M38 174.903C38 143.472 63.5456 117.992 95.0578 117.992H417.434C448.946 117.992 474.492 143.472 474.492 174.903V422.466C474.492 453.897 448.946 479.377 417.434 479.377H95.0578C63.5456 479.377 38 453.897 38 422.466V174.903Z" fill="url(#paint0_linear_69_69)"/>
|
||||
</g>
|
||||
<g filter="url(#filter1_i_69_69)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M417.434 143.602H95.0578C77.7261 143.602 63.676 157.616 63.676 174.903V422.466C63.676 439.753 77.7261 453.767 95.0578 453.767H417.434C434.766 453.767 448.816 439.753 448.816 422.466V174.903C448.816 157.616 434.766 143.602 417.434 143.602ZM95.0578 117.992C63.5456 117.992 38 143.472 38 174.903V422.466C38 453.897 63.5456 479.377 95.0578 479.377H417.434C448.946 479.377 474.492 453.897 474.492 422.466V174.903C474.492 143.472 448.946 117.992 417.434 117.992H95.0578Z" fill="#4C1683"/>
|
||||
</g>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M235.473 351.083C230.589 341.225 218.714 337.23 208.946 342.159C199.178 347.088 195.219 359.073 200.103 368.93C211.471 391.876 237.209 399.916 257.335 399.916C277.46 399.916 303.198 391.876 314.566 368.93C319.45 359.073 315.491 347.088 305.724 342.159C295.956 337.23 284.08 341.225 279.196 351.083C277.383 354.742 270.163 360.007 257.335 360.007C244.506 360.007 237.287 354.742 235.473 351.083Z" fill="url(#paint1_linear_69_69)"/>
|
||||
<path d="M402.65 258.41C402.65 289.069 377.796 313.924 347.136 313.924C316.477 313.924 291.623 289.069 291.623 258.41C291.623 227.75 316.477 202.896 347.136 202.896C377.796 202.896 402.65 227.75 402.65 258.41Z" fill="#4C1683"/>
|
||||
<path d="M220.869 258.41C220.869 289.069 196.015 313.924 165.355 313.924C134.696 313.924 109.842 289.069 109.842 258.41C109.842 227.75 134.696 202.896 165.355 202.896C196.015 202.896 220.869 227.75 220.869 258.41Z" fill="#4F1689"/>
|
||||
<path d="M383.057 258.954C383.057 278.492 367.219 294.331 347.681 294.331C328.143 294.331 312.304 278.492 312.304 258.954C312.304 239.416 328.143 223.578 347.681 223.578C367.219 223.578 383.057 239.416 383.057 258.954Z" fill="url(#paint2_radial_69_69)"/>
|
||||
<path d="M200.188 258.954C200.188 278.492 184.349 294.331 164.811 294.331C145.273 294.331 129.435 278.492 129.435 258.954C129.435 239.416 145.273 223.578 164.811 223.578C184.349 223.578 200.188 239.416 200.188 258.954Z" fill="url(#paint3_radial_69_69)"/>
|
||||
<path d="M245.59 108.596H218.224L224.025 91.553H239.158L216.774 32H243.95L277.306 117.992H249.121L245.59 108.596ZM210.784 117.992H183.86L213.748 35.8881L226.106 70.0387L210.784 117.992Z" fill="#4C1683"/>
|
||||
<path d="M283.99 99.6532H292.376V50.2741H283.99V32H328.632V50.2741H320.246V99.6532H328.632V117.992H283.99V99.6532Z" fill="#4C1683"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_i_69_69" x="38" y="117.992" width="436.492" height="361.385" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="9.55"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0897572 0 0 0 0 0.669632 0 0 0 0 0.852751 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_69_69"/>
|
||||
</filter>
|
||||
<filter id="filter1_i_69_69" x="38" y="117.992" width="436.492" height="361.385" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset/>
|
||||
<feGaussianBlur stdDeviation="9.55"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0897572 0 0 0 0 0.669632 0 0 0 0 0.852751 0 0 0 0.25 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_69_69"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_69_69" x1="474.492" y1="287.302" x2="38" y2="287.302" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F1EBFF"/>
|
||||
<stop offset="0.213542" stop-color="#F6F9FF"/>
|
||||
<stop offset="0.5" stop-color="#FDFDFD"/>
|
||||
<stop offset="0.776042" stop-color="#F3F5FB"/>
|
||||
<stop offset="1" stop-color="#F7F5FC"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_69_69" x1="65.7102" y1="98.5751" x2="441.212" y2="456.351" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3088FF"/>
|
||||
<stop offset="0.479167" stop-color="#6213B1"/>
|
||||
<stop offset="1" stop-color="#2C1B3D"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="paint2_radial_69_69" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(347.681 258.954) rotate(90) scale(35.3765)">
|
||||
<stop stop-color="#EDEDED"/>
|
||||
<stop offset="0.0001" stop-color="#FFFFF3"/>
|
||||
<stop offset="1" stop-color="#F3D223"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint3_radial_69_69" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(164.811 258.954) rotate(90) scale(35.3765)">
|
||||
<stop stop-color="#EDEDED"/>
|
||||
<stop offset="0.0001" stop-color="#FFFFF3"/>
|
||||
<stop offset="1" stop-color="#F3D223"/>
|
||||
</radialGradient>
|
||||
<clipPath id="clip0_69_69">
|
||||
<rect width="512" height="512" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
BIN
public/aibuddytool-og.jpg
Normal file
|
After Width: | Height: | Size: 235 KiB |
BIN
public/aibuddytool-og.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
public/aibuddytool-og.webp
Normal file
|
After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 62 KiB |
BIN
public/android-chrome-maskable-192x192.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/android-chrome-maskable-512x512.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 561 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
public/featured-on-aibuddytool-1-1000.png
Normal file
|
After Width: | Height: | Size: 212 KiB |
BIN
public/featured-on-aibuddytool-1-1000.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
@@ -1 +1 @@
|
||||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
||||
{"name":"AI Buddy Tool","short_name":"AI Buddy","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
||||
9
resources/js/FrontApp.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "App",
|
||||
};
|
||||
</script>
|
||||
<style></style>
|
||||
@@ -1 +1,57 @@
|
||||
import * as bootstrap from "~bootstrap";
|
||||
import "@tabler/core/src/js/tabler.js";
|
||||
|
||||
import "./bootstrap";
|
||||
|
||||
import { createApp, defineAsyncComponent } from "vue";
|
||||
|
||||
import FrontApp from "@/FrontApp.vue";
|
||||
|
||||
const app = createApp({ FrontApp });
|
||||
const vueComponents = import.meta.glob("@/vue/**/*.vue", {
|
||||
eager: false,
|
||||
});
|
||||
|
||||
console.log(vueComponents);
|
||||
|
||||
import.meta.glob(["../images/**", "../fonts/**"]);
|
||||
|
||||
import { createPinia } from "pinia";
|
||||
app.use(createPinia());
|
||||
|
||||
import axios from "./plugins/axios";
|
||||
import VueAxios from "vue-axios";
|
||||
app.use(VueAxios, axios);
|
||||
|
||||
import auth from "./plugins/auth";
|
||||
app.use(auth);
|
||||
|
||||
import eventBus from "./plugins/event-bus";
|
||||
app.use(eventBus);
|
||||
|
||||
import Vue3Toastify from "vue3-toastify";
|
||||
import "../css/toastify.css";
|
||||
app.use(Vue3Toastify);
|
||||
|
||||
import { Ziggy as ZiggyRoute } from "./ziggy";
|
||||
import { ZiggyVue } from "ziggy-js/dist/vue";
|
||||
app.use(ZiggyVue, ZiggyRoute);
|
||||
|
||||
window.Ziggy = ZiggyRoute;
|
||||
|
||||
Object.entries({ ...vueComponents }).forEach(([path, definition]) => {
|
||||
// Get name of component, based on filename
|
||||
// "./components/Fruits.vue" will become "Fruits"
|
||||
const componentName = path
|
||||
.split("/")
|
||||
.pop()
|
||||
.replace(/\.\w+$/, "")
|
||||
.replace(/([a-z])([A-Z])/g, "$1-$2")
|
||||
.toLowerCase();
|
||||
// console.log(componentName);
|
||||
// console.log(typeof definition);
|
||||
|
||||
// Register component on this Vue instance
|
||||
app.component(componentName, defineAsyncComponent(definition));
|
||||
});
|
||||
|
||||
app.mount("#app");
|
||||
|
||||
75
resources/js/vue/GetEmbedCode.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="d-grid gap-2 mx-auto" style="width: 250px">
|
||||
<img
|
||||
style="width: 250px; height: auto"
|
||||
:src="imgSrc"
|
||||
alt="Featured banner"
|
||||
/>
|
||||
<button @click="getEmbedCode" class="btn btn-sm btn-outline-primary px-3">
|
||||
Get HTML embed code
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { toast } from "vue3-toastify";
|
||||
export default {
|
||||
name: "GetEmbedCode",
|
||||
mixins: [],
|
||||
components: {},
|
||||
props: ["url", "name"],
|
||||
data: () => ({
|
||||
imgSrc: "https://cdn.aibuddytool.com/featured-on-aibuddytool-1-1000.webp",
|
||||
showToast: false,
|
||||
}),
|
||||
computed: {
|
||||
embedCode() {
|
||||
return (
|
||||
"<!-- " +
|
||||
this.name +
|
||||
' featured by AiBuddyTool.com --><a href="' +
|
||||
this.url +
|
||||
'" target="_blank"><img alt="' +
|
||||
this.name +
|
||||
'" style="width: 250px; height: auto" src="' +
|
||||
this.imgSrc +
|
||||
'"></a>'
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getEmbedCode() {
|
||||
const el = document.createElement("textarea");
|
||||
el.value = this.embedCode;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(el);
|
||||
|
||||
toast(
|
||||
"Copied! Paste the HTML embed code at the bottom of your business website footer.",
|
||||
{
|
||||
position: "bottom-center",
|
||||
type: "success",
|
||||
timeout: 3000,
|
||||
closeOnClick: true,
|
||||
pauseOnFocusLoss: true,
|
||||
pauseOnHover: true,
|
||||
draggable: true,
|
||||
draggablePercent: 0.6,
|
||||
showCloseButtonOnHover: false,
|
||||
hideProgressBar: false,
|
||||
closeButton: true,
|
||||
icon: true,
|
||||
rtl: false,
|
||||
},
|
||||
);
|
||||
},
|
||||
},
|
||||
mounted() {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -1,4 +1,4 @@
|
||||
const Ziggy = {"url":"https:\/\/aibuddytool.test","port":null,"defaults":{},"routes":{"debugbar.openhandler":{"uri":"_debugbar\/open","methods":["GET","HEAD"]},"debugbar.clockwork":{"uri":"_debugbar\/clockwork\/{id}","methods":["GET","HEAD"]},"debugbar.assets.css":{"uri":"_debugbar\/assets\/stylesheets","methods":["GET","HEAD"]},"debugbar.assets.js":{"uri":"_debugbar\/assets\/javascript","methods":["GET","HEAD"]},"debugbar.cache.delete":{"uri":"_debugbar\/cache\/{key}\/{tags?}","methods":["DELETE"]},"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"ignition.healthCheck":{"uri":"_ignition\/health-check","methods":["GET","HEAD"]},"ignition.executeSolution":{"uri":"_ignition\/execute-solution","methods":["POST"]},"ignition.updateConfig":{"uri":"_ignition\/update-config","methods":["POST"]},"api.auth.login.post":{"uri":"api\/login","methods":["POST"]},"api.auth.logout.post":{"uri":"api\/logout","methods":["POST"]},"api.admin.post.get":{"uri":"api\/admin\/post\/{id}","methods":["GET","HEAD"]},"api.admin.country-locales":{"uri":"api\/admin\/country-locales","methods":["GET","HEAD"]},"api.admin.categories":{"uri":"api\/admin\/categories\/{country_locale_slug}","methods":["GET","HEAD"]},"api.admin.authors":{"uri":"api\/admin\/authors","methods":["GET","HEAD"]},"api.admin.upload.cloud.image":{"uri":"api\/admin\/image\/upload","methods":["POST"]},"api.admin.post.upsert":{"uri":"api\/admin\/admin\/post\/upsert","methods":["POST"]},"feeds.main":{"uri":"posts.rss","methods":["GET","HEAD"]},"login":{"uri":"login","methods":["GET","HEAD"]},"logout":{"uri":"logout","methods":["POST"]},"register":{"uri":"register","methods":["GET","HEAD"]},"password.request":{"uri":"password\/reset","methods":["GET","HEAD"]},"password.email":{"uri":"password\/email","methods":["POST"]},"password.reset":{"uri":"password\/reset\/{token}","methods":["GET","HEAD"]},"password.update":{"uri":"password\/reset","methods":["POST"]},"password.confirm":{"uri":"password\/confirm","methods":["GET","HEAD"]},"dashboard":{"uri":"admin","methods":["GET","HEAD"]},"admin.changelog":{"uri":"admin\/changelog","methods":["GET","HEAD"]},"about":{"uri":"admin\/about","methods":["GET","HEAD"]},"users.index":{"uri":"admin\/users","methods":["GET","HEAD"]},"posts.manage":{"uri":"admin\/posts","methods":["GET","HEAD"]},"posts.manage.edit":{"uri":"admin\/posts\/edit\/{post_id}","methods":["GET","HEAD"]},"posts.manage.delete":{"uri":"admin\/posts\/delete\/{post_id}","methods":["GET","HEAD"]},"posts.manage.indexing":{"uri":"admin\/posts\/indexing\/{post_id}","methods":["GET","HEAD"]},"posts.manage.new":{"uri":"admin\/posts\/new","methods":["GET","HEAD"]},"profile.show":{"uri":"admin\/profile","methods":["GET","HEAD"]},"profile.update":{"uri":"admin\/profile","methods":["PUT"]},"front.home":{"uri":"\/","methods":["GET","HEAD"]},"front.discover.home":{"uri":"discover","methods":["GET","HEAD"]},"front.discover.category":{"uri":"discover\/{category_slug}","methods":["GET","HEAD"]},"front.terms":{"uri":"terms","methods":["GET","HEAD"]},"front.privacy":{"uri":"privacy","methods":["GET","HEAD"]},"front.disclaimer":{"uri":"disclaimer","methods":["GET","HEAD"]}}};
|
||||
const Ziggy = {"url":"https:\/\/aibuddytool.test","port":null,"defaults":{},"routes":{"debugbar.openhandler":{"uri":"_debugbar\/open","methods":["GET","HEAD"]},"debugbar.clockwork":{"uri":"_debugbar\/clockwork\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"debugbar.assets.css":{"uri":"_debugbar\/assets\/stylesheets","methods":["GET","HEAD"]},"debugbar.assets.js":{"uri":"_debugbar\/assets\/javascript","methods":["GET","HEAD"]},"debugbar.cache.delete":{"uri":"_debugbar\/cache\/{key}\/{tags?}","methods":["DELETE"],"parameters":["key","tags"]},"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"ignition.healthCheck":{"uri":"_ignition\/health-check","methods":["GET","HEAD"]},"ignition.executeSolution":{"uri":"_ignition\/execute-solution","methods":["POST"]},"ignition.updateConfig":{"uri":"_ignition\/update-config","methods":["POST"]},"api.auth.login.post":{"uri":"api\/login","methods":["POST"]},"api.auth.logout.post":{"uri":"api\/logout","methods":["POST"]},"api.admin.post.get":{"uri":"api\/admin\/post\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"api.admin.country-locales":{"uri":"api\/admin\/country-locales","methods":["GET","HEAD"]},"api.admin.categories":{"uri":"api\/admin\/categories\/{country_locale_slug}","methods":["GET","HEAD"],"parameters":["country_locale_slug"]},"api.admin.authors":{"uri":"api\/admin\/authors","methods":["GET","HEAD"]},"api.admin.upload.cloud.image":{"uri":"api\/admin\/image\/upload","methods":["POST"]},"api.admin.post.upsert":{"uri":"api\/admin\/admin\/post\/upsert","methods":["POST"]},"feeds.main":{"uri":"posts.rss","methods":["GET","HEAD"]},"login":{"uri":"login","methods":["GET","HEAD"]},"logout":{"uri":"logout","methods":["POST"]},"register":{"uri":"register","methods":["GET","HEAD"]},"password.request":{"uri":"password\/reset","methods":["GET","HEAD"]},"password.email":{"uri":"password\/email","methods":["POST"]},"password.reset":{"uri":"password\/reset\/{token}","methods":["GET","HEAD"],"parameters":["token"]},"password.update":{"uri":"password\/reset","methods":["POST"]},"password.confirm":{"uri":"password\/confirm","methods":["GET","HEAD"]},"dashboard":{"uri":"admin","methods":["GET","HEAD"]},"admin.changelog":{"uri":"admin\/changelog","methods":["GET","HEAD"]},"about":{"uri":"admin\/about","methods":["GET","HEAD"]},"users.index":{"uri":"admin\/users","methods":["GET","HEAD"]},"posts.manage":{"uri":"admin\/posts","methods":["GET","HEAD"]},"posts.manage.edit":{"uri":"admin\/posts\/edit\/{post_id}","methods":["GET","HEAD"],"parameters":["post_id"]},"posts.manage.delete":{"uri":"admin\/posts\/delete\/{post_id}","methods":["GET","HEAD"],"parameters":["post_id"]},"posts.manage.indexing":{"uri":"admin\/posts\/indexing\/{post_id}","methods":["GET","HEAD"],"parameters":["post_id"]},"posts.manage.new":{"uri":"admin\/posts\/new","methods":["GET","HEAD"]},"profile.show":{"uri":"admin\/profile","methods":["GET","HEAD"]},"profile.update":{"uri":"admin\/profile","methods":["PUT"]},"front.home":{"uri":"\/","methods":["GET","HEAD"]},"front.discover.home":{"uri":"discover","methods":["GET","HEAD"]},"front.discover.category":{"uri":"discover\/{category_slug}","methods":["GET","HEAD"],"parameters":["category_slug"]},"front.search.post":{"uri":"ai-search","methods":["POST"]},"front.search.results":{"uri":"ai-search\/{query}","methods":["GET","HEAD"],"parameters":["query"]},"front.aitool.show":{"uri":"ai-tool\/{ai_tool_slug}","methods":["GET","HEAD"],"parameters":["ai_tool_slug"]},"front.terms":{"uri":"terms","methods":["GET","HEAD"]},"front.privacy":{"uri":"privacy","methods":["GET","HEAD"]},"front.disclaimer":{"uri":"disclaimer","methods":["GET","HEAD"]}}};
|
||||
|
||||
if (typeof window !== 'undefined' && typeof window.Ziggy !== 'undefined') {
|
||||
Object.assign(Ziggy.routes, window.Ziggy.routes);
|
||||
|
||||
@@ -26,4 +26,4 @@ ## **5. Agreement**
|
||||
|
||||
## **6. Contact**
|
||||
|
||||
If you have any questions regarding this disclaimer, contact us via email: support@aibuddytool.com
|
||||
If you have any questions regarding this disclaimer, contact us via email: contact@aibuddytool.com
|
||||
|
||||
@@ -238,4 +238,4 @@ ## Contact Us
|
||||
|
||||
Don't hesitate to contact us if you have any questions.
|
||||
|
||||
-Via Email: support@aibuddytool.com
|
||||
-Via Email: contact@aibuddytool.com
|
||||
|
||||
@@ -160,7 +160,7 @@ ## Agreement to Arbitrate
|
||||
|
||||
## Notice of Dispute
|
||||
|
||||
In the event of a dispute, you or aibuddytool.com must give the other a Notice of Dispute, which is a written statement that sets forth the name, address, and contact information of the party giving it, the facts giving rise to the dispute, and the relief requested. You must send any Notice of Dispute via email to: support@aibuddytool.com. aibuddytool.com will send any Notice of Dispute to you by mail to your address if we have it, or otherwise to your email address. You and aibuddytool.com will attempt to resolve any dispute through informal negotiation within sixty (60) days from the date the Notice of Dispute is sent. After sixty (60) days, you or aibuddytool.com may commence arbitration.
|
||||
In the event of a dispute, you or aibuddytool.com must give the other a Notice of Dispute, which is a written statement that sets forth the name, address, and contact information of the party giving it, the facts giving rise to the dispute, and the relief requested. You must send any Notice of Dispute via email to: contact@aibuddytool.com. aibuddytool.com will send any Notice of Dispute to you by mail to your address if we have it, or otherwise to your email address. You and aibuddytool.com will attempt to resolve any dispute through informal negotiation within sixty (60) days from the date the Notice of Dispute is sent. After sixty (60) days, you or aibuddytool.com may commence arbitration.
|
||||
|
||||
## Binding Arbitration
|
||||
|
||||
@@ -198,4 +198,4 @@ ## Contact Us
|
||||
|
||||
Don't hesitate to contact us if you have any questions.
|
||||
|
||||
- Via Email: support@aibuddytool.com
|
||||
- Via Email: contact@aibuddytool.com
|
||||
|
||||
@@ -52,7 +52,7 @@ $green: #198754;
|
||||
$teal: #20c997;
|
||||
$cyan: #0dcaf0;
|
||||
$highlighter-yellow: #ccf62b;
|
||||
$highlighter-pink: #ff90ea;
|
||||
$highlighter-pink: #feacf5;
|
||||
$highlighter-orange: #ff962a;
|
||||
$highlighter-blue: #507fff;
|
||||
$highlighter-purple: #952fff;
|
||||
@@ -314,7 +314,7 @@ $cyans: (
|
||||
// fusv-enable
|
||||
|
||||
// scss-docs-start theme-color-variables
|
||||
$primary: $highlighter-blue;
|
||||
$primary: $highlighter-purple;
|
||||
$secondary: $gray-600;
|
||||
$success: $green;
|
||||
$info: $cyan;
|
||||
@@ -347,4 +347,3 @@ $highlighter-colors: (
|
||||
);
|
||||
|
||||
$theme-colors: map-merge($theme-colors, $highlighter-colors);
|
||||
$link-color: $highlighter-purple;
|
||||
|
||||
160
resources/views/front/aitool.blade.php
Normal file
@@ -0,0 +1,160 @@
|
||||
@extends('front.layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container-lg pt-3">
|
||||
<div class="mb-3">
|
||||
@include('front.partials.breadcrumbs')
|
||||
<h1 class="fw-bold mb-0">{{ $ai_tool->tool_name }}</h1>
|
||||
<h2 class="text-secondary"><span class="h6">{{ $ai_tool->tagline }}</span></h2>
|
||||
</div>
|
||||
<div class="row mb-3 g-3">
|
||||
<div class="col-12 col-sm-7 col-md-8 col-lg-8 col-xl-9">
|
||||
<div class="mb-3">
|
||||
<ul class="nav nav-underline gap-4 h5">
|
||||
@if (!is_empty($ai_tool->screenshot_img))
|
||||
<li class="nav-item">
|
||||
<a class="text-decoration-none nav-link active instant-scroll" aria-current="page"
|
||||
href="#screenshot">Screenshot</a>
|
||||
</li>
|
||||
@endif
|
||||
<li class="nav-item">
|
||||
<a title="Details about {{ $ai_tool->category->name }} AI tool: {{ $ai_tool->tool_name }}"
|
||||
class="text-decoration-none nav-link instant-scroll" href="#details">Details</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a title="Embed {{ $ai_tool->tool_name }}" class="text-decoration-none nav-link instant-scroll"
|
||||
href="#embed">Embed</a>
|
||||
</li>
|
||||
@if (count($ai_tool->qna) > 0)
|
||||
<li class="nav-item">
|
||||
<a title="Frequently asked questions about the AI tool {{ $ai_tool->tool_name }}"
|
||||
class="text-decoration-none nav-link instant-scroll" href="#faq">FAQ</a>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@if (!is_empty($ai_tool->screenshot_img))
|
||||
<div id="screenshot" class="ratio ratio-16x9 mb-5">
|
||||
<figure class="text-center">
|
||||
<img class="img-fluid rounded-3 shadow mb-2" src="{{ $ai_tool->screenshot_img }}"
|
||||
alt="Screenshot of {{ $ai_tool->tool_name }} website">
|
||||
<figcaption class="small text-secondary">Screenshot of {{ $ai_tool->tool_name }} ({{ get_domain_from_url($ai_tool->external_url) }}) website
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div id="embed">
|
||||
|
||||
<div class="card border-2 border-primary mb-4">
|
||||
<div class="card-body text-center">
|
||||
|
||||
<div class="mb-3">This AI tool, <span
|
||||
class="fw-semibold">{{ $ai_tool->tool_name }}</span>
|
||||
was first featured in AiBuddyTool.com
|
||||
on {{ dmy($ai_tool->created_at) }}.</div>
|
||||
|
||||
<get-embed-code name="{{ $ai_tool->tool_name }}"
|
||||
url="{{ route('front.aitool.show', ['ai_tool_slug' => $ai_tool->slug, 'ref' => get_domain_from_url($ai_tool->external_url)]) }}"></get-embed-code>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="details" class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h3 class="mb-2 fw-bold h5 text-primary">{{ $ai_tool->tool_name }} summary by AIToolBuddy</h3>
|
||||
<div>{!! $ai_tool->summary !!}</div>
|
||||
<br>
|
||||
|
||||
<h3 class="mb-2 fw-bold h5 text-primary">Details</h3>
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Pricing Structure</th>
|
||||
<td>{{ $ai_tool->pricing_type }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">AI Tool Platform</th>
|
||||
<td>
|
||||
@if ($ai_tool->is_app_web_both == 'both')
|
||||
App & Web
|
||||
@else
|
||||
{{ ucwords($ai_tool->is_app_web_both) }} Only
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<h3 class="mb-2 fw-bold h5 text-primary">{{ $ai_tool->tool_name }} Features</h3>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
@foreach ($ai_tool->keywords as $keyword)
|
||||
<a href="{{ get_route_search_result($keyword->value_lowercased) }}"
|
||||
class="btn btn-outline-dark btn-sm border-2 px-2 py-1 rounded-pill text-decoration-none text-nowrap">{{ $keyword->value }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (count($ai_tool->qna) > 0)
|
||||
<div id="faq" class="mb-4">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h3 class="mb-2 fw-bold h5 text-primary">Frequently Asked Questions about
|
||||
{{ $ai_tool->tool_name }}</h3>
|
||||
|
||||
<div class="accordion" id="accordionAiToolFaq">
|
||||
|
||||
@foreach ($ai_tool->qna as $key => $faq)
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed fw-semibold" type="button"
|
||||
data-bs-toggle="collapse" data-bs-target="#collapse{{ $key }}"
|
||||
{{ $key == 0 ? 'aria-expanded="true"' : '' }}
|
||||
aria-controls="collapse{{ $key }}">
|
||||
{{ $faq->q }}
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapse{{ $key }}"
|
||||
class="accordion-collapse collapse {{ $key == 0 ? 'show' : '' }}"
|
||||
data-bs-parent="#accordionAiToolFaq">
|
||||
<div class="accordion-body">
|
||||
{!! $faq->a !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-sm-5 col-md-4 col-lg-4 col-xl-3">
|
||||
|
||||
<div class="d-grid">
|
||||
<a class="btn btn-primary breathing-effect text-decoration-none px-4 mb-4" href="{{ add_params_to_url($ai_tool->external_url, ['ref' => 'aibuddytool.com']) }}">Visit {{ $ai_tool->tool_name }} page ({{ get_domain_from_url($ai_tool->external_url) }})</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@include('front.partials.sidebar')
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('top_head')
|
||||
{!! $faq_context !!}
|
||||
@endpush
|
||||
@@ -10,6 +10,12 @@
|
||||
Discover over <span class="bg-highlighter-yellow fw-bold px-2">{{ $tools_count }} AI Tools</span> Today
|
||||
@endif
|
||||
</h1>
|
||||
<div class="row justify-content-center">
|
||||
|
||||
<div class="col-12 col-md-9 col-lg-8 col-xl-7 mx-auto mb-4">
|
||||
@include('front.partials.search')
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-lg pb-5">
|
||||
@@ -19,15 +25,20 @@
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#collapseCategory" aria-controls="collapseCategory">
|
||||
<span class="h5 fw-bold mb-0">Filter by Category ({{ $parent_categories->count() }})</span>
|
||||
<span class="h5 mb-0">Filter by {{ $parent_categories->count() }} AI Tool Categories </span>
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseCategory" class="accordion-collapse collapse" data-bs-parent="#accordionCategory">
|
||||
<div class="accordion-body">
|
||||
<div class="accordion-body d-inline-flex justify-content-center flex-wrap gap-1">
|
||||
<h3 class="d-inline mb-0">
|
||||
<a href="{{ route('front.discover.home') }}"
|
||||
class="btn btn-outline-dark text-decoration-none btn-sm border-2 fw-bold mb-0 rounded-pill px-3 {{ is_null($category) ? 'active' : '' }}">All
|
||||
Categories</a>
|
||||
</h3>
|
||||
@foreach ($parent_categories as $parent_category)
|
||||
<h3 class="d-inline">
|
||||
<h3 class="d-inline mb-0">
|
||||
<a href="{{ route('front.discover.category', ['category_slug' => $parent_category->slug]) }}"
|
||||
class="btn btn-outline-dark text-decoration-none btn-sm border-2 fw-bold mb-1 rounded-pill px-3 {{ !is_null($category) && $category->slug == $parent_category->slug ? 'active' : '' }}">{{ $parent_category->name }}
|
||||
class="btn btn-outline-dark text-decoration-none btn-sm border-2 fw-bold mb-0 rounded-pill px-3 {{ !is_null($category) && $category->slug == $parent_category->slug ? 'active' : '' }}">{{ $parent_category->name }}
|
||||
{{ $parent_category->emoji }}</a>
|
||||
</h3>
|
||||
@endforeach
|
||||
@@ -36,12 +47,46 @@ class="btn btn-outline-dark text-decoration-none btn-sm border-2 fw-bold mb-1 ro
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row justify-content-center g-3">
|
||||
@for ($i = 1; $i <= 18; $i++)
|
||||
<div class="col-6 col-lg-4">
|
||||
@include('front.partials.ai-tool-card')
|
||||
@if ($ai_tools->count() > 0)
|
||||
<div class="row justify-content-center g-3 mb-4">
|
||||
@foreach ($ai_tools as $ai_tool)
|
||||
<div class="col-6 col-lg-4">
|
||||
@include('front.partials.ai-tool-card')
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<div class="card">
|
||||
<div class="card-body text-center p-5">
|
||||
<p class="h4 fw-bold">😱 Yikes!</p>
|
||||
<p class="h5 mb-3">This is embarassing, there are no AI tools in this category yet.<br> We will find
|
||||
more AI to add here. In the meantime:</p>
|
||||
<a class="btn btn-primary btn-lg rounded-pill px-4 text-decoration-none"
|
||||
href="{{ route('front.discover.home') }}">See more AI Tools</a>
|
||||
|
||||
</div>
|
||||
@endfor
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="mb-2">
|
||||
@if ($ai_tools instanceof \Illuminate\Pagination\LengthAwarePaginator)
|
||||
@if ($ai_tools->hasPages())
|
||||
<div class="d-flex justify-content-center">
|
||||
{{ $ai_tools->onEachSide(1)->links('pagination::bootstrap-5-pagination-limit-10') }}
|
||||
</div>
|
||||
@endif
|
||||
@elseif ($ai_tools instanceof \Illuminate\Pagination\CursorPaginator)
|
||||
@if ($ai_tools->hasPages())
|
||||
<div class="d-flex justify-content-center">
|
||||
{{ $ai_tools->links('pagination::simple-bootstrap-5') }}
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
<div class="d-flex justify-content-center text-center text-secondary">
|
||||
<small>Use <b>Search</b> to discover AI tools by brand, task or features.</small>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
@extends('front.layouts.app')
|
||||
|
||||
@section('content')
|
||||
<h1 class="display-5 text-body-emphasis font-family-zilla-slab">
|
||||
Discover Art AI Tools Today
|
||||
</h1>
|
||||
@endsection
|
||||
@@ -8,42 +8,43 @@ class="bg-highlighter-pink fw-bold px-2">Any Task</span>
|
||||
</h1>
|
||||
<h2 class="lead h4 mb-4">Curating over 750+ AI tools and growing 🛠️</h2>
|
||||
|
||||
<div class="col-12 col-md-9 col-lg-8 col-xl-7 mx-auto mb-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-md-9 col-lg-8 col-xl-7 mx-auto mb-4">
|
||||
@include('front.partials.search')
|
||||
</div>
|
||||
|
||||
<form class="form-inline d-flex justify-content-center border rounded-pill p-2">
|
||||
<input class="form-control form-control-lg border-0 rounded-pill" type="search" placeholder="Search AI Tools"
|
||||
aria-label="Search">
|
||||
<button class="btn btn-lg btn-primary bg-gradient text-white rounded-pill ms-2 text-nowrap px-4 fw-bold"
|
||||
type="submit">Search with AI ✨</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-9 col-lg-9 col-xl-9 mx-auto">
|
||||
Filter by
|
||||
@foreach ($top_parent_categories as $category)
|
||||
<a href="{{ route('front.discover.category', ['category_slug' => $category->slug]) }}"
|
||||
class="btn btn-outline-dark text-decoration-none border-2 fw-bold mb-1 rounded-pill px-3">{{ $category->name }}
|
||||
{{ $category->emoji }}</a>
|
||||
@endforeach
|
||||
<a href="{{ route('front.discover.home') }}"
|
||||
class="btn btn-outline-dark text-decoration-none border-2 fw-bold mb-1 rounded-pill px-3">and
|
||||
{{ $non_top_parent_categories->count() }} more top categories!</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container-lg">
|
||||
<p class="text-center h3 fw-bold mb-3">Featured AI Tools</p>
|
||||
<div class="row justify-content-center g-3">
|
||||
@for ($i = 1; $i <= 18; $i++)
|
||||
<div class="col-6 col-lg-4">
|
||||
@include('front.partials.ai-tool-card')
|
||||
<div class="col-12 col-md-9 col-lg-9 col-xl-9 mx-auto">
|
||||
<div class="d-inline-flex justify-content-center flex-wrap gap-1">
|
||||
<span class="align-self-center">Filter by</span>
|
||||
@foreach ($top_parent_categories as $category)
|
||||
<a href="{{ route('front.discover.category', ['category_slug' => $category->slug]) }}"
|
||||
class="btn btn-outline-dark text-decoration-none border-2 fw-bold rounded-pill px-3">{{ $category->name }}
|
||||
{{ $category->emoji }}</a>
|
||||
@endforeach
|
||||
<a href="{{ route('front.discover.home') }}"
|
||||
class="btn btn-outline-dark text-decoration-none border-2 fw-bold rounded-pill px-3">and
|
||||
{{ $non_top_parent_categories->count() }} more top categories!</a>
|
||||
</div>
|
||||
@endfor
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@if ($latest_ai_tools->count() > 0)
|
||||
<div class="container-lg">
|
||||
<p class="text-center h3 fw-bold mb-3">Featured AI Tools</p>
|
||||
<div class="row justify-content-center g-3">
|
||||
@foreach ($latest_ai_tools as $ai_tool)
|
||||
<div class="col-6 col-lg-4">
|
||||
@include('front.partials.ai-tool-card', ['ai_tool' => $ai_tool])
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="container-lg mt-3 mb-3 text-center">
|
||||
<a class="btn btn-primary rounded-pill px-4 breathing-effect btn-lg text-decoration-none bg-gradient"
|
||||
href="{{ route('front.discover.home') }}">Discover {{ $tools_count }} More AI Tools</a>
|
||||
|
||||
@@ -13,15 +13,14 @@
|
||||
<meta property="fb:app_id" content="{{ config('seotools.fb_app_id') }}" />
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}">
|
||||
<link rel="icon" href="{{ asset('ai-buddy-tool-logo-512x512.svg') }}" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('apple-touch-icon.png') }}">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ asset('favicon-32x32.png') }}">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ asset('favicon-16x16.png') }}">
|
||||
<link rel="manifest" href="{{ asset('site.webmanifest') }}">
|
||||
|
||||
@vite('resources/sass/app-front.scss')
|
||||
|
||||
@stack('top_head')
|
||||
|
||||
<!-- Custom styles for this Page-->
|
||||
@yield('custom_styles')
|
||||
|
||||
@@ -31,19 +30,23 @@
|
||||
|
||||
<body>
|
||||
|
||||
@include('googletagmanager::body')
|
||||
<div id="app">
|
||||
|
||||
@include('front.layouts.navigation')
|
||||
@include('googletagmanager::body')
|
||||
|
||||
@yield('content')
|
||||
@include('front.layouts.navigation')
|
||||
|
||||
@include('front.layouts.footer')
|
||||
@yield('content')
|
||||
|
||||
<!-- Core plugin JavaScript-->
|
||||
@vite('resources/js/app-front.js')
|
||||
@include('front.layouts.footer')
|
||||
|
||||
<!-- Page level custom scripts -->
|
||||
@yield('custom_scripts')
|
||||
<!-- Core plugin JavaScript-->
|
||||
@vite('resources/js/app-front.js')
|
||||
|
||||
<!-- Page level custom scripts -->
|
||||
@yield('custom_scripts')
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<div class="container-fluid shadow-sm">
|
||||
<header class="d-flex flex-wrap align-items-center justify-content-center py-3">
|
||||
<header class="d-flex flex-wrap align-items-center justify-content-center py-2">
|
||||
<div class="col-auto">
|
||||
|
||||
<a href="{{ route('front.home') }}" class="btn btn-link d-inline-flex text-decoration-none text-center">
|
||||
<p class="display-6 mb-0 font-family-black-ops-one">
|
||||
<a href="{{ route('front.home') }}" class="btn btn-link d-inline-flex text-decoration-none hover-grow text-center gap-2">
|
||||
<img class="align-self-center" style="height:50px; width:auto;" src="{{ asset('ai-buddy-tool-logo-512x512.svg') }}" alt="AIBuddyTool.com Logo">
|
||||
<p class="align-self-center display-6 mb-0 font-family-zilla-slab fw-bold">
|
||||
{{ config('app.name') }}
|
||||
</p>
|
||||
</a>
|
||||
|
||||
@@ -1,22 +1,48 @@
|
||||
<div class="card border-0 shadow hover-grow">
|
||||
<div class="ratio ratio-16x9">
|
||||
<a href="#">
|
||||
<img class="card-img-top" src="https://placekitten.com/g/1024/576">
|
||||
<div class="card border-0 shadow hover-grow" style="height: 100%;">
|
||||
<div class="ratio ratio-16x9 shadow">
|
||||
<a href="{{ route('front.aitool.show', ['ai_tool_slug' => $ai_tool->slug]) }}">
|
||||
<img class="card-img-top" src="{{ $ai_tool->screenshot_img }}">
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<a class="fw-bold" href="#">
|
||||
<h3 class="h5 fw-bold line-clamp-1">Yada {{ $i }}</h3>
|
||||
<a class="fw-bold" href="{{ route('front.aitool.show', ['ai_tool_slug' => $ai_tool->slug]) }}">
|
||||
<h3 class="h5 fw-bold line-clamp-1">{{ $ai_tool->tool_name }}</h3>
|
||||
</a>
|
||||
<p class="line-clamp-2">Rewin.ai is an AI tool that helps content creators generate unique and engaging scripts
|
||||
for their chicken rice that is very tasty.</p>
|
||||
|
||||
<div class="d-flex">
|
||||
<a class="btn btn-outline-dark btn-sm border-2 px-2 py-1 rounded-pill text-decoration-none">Light</a>
|
||||
<p class="line-clamp-2 mb-2">{!! str_first_sentence($ai_tool->summary) !!}</p>
|
||||
|
||||
<div class="mb-3 d-flex gap-1">
|
||||
<span class="badge rounded-pill text-bg-highlighter-yellow">
|
||||
<i class="bi bi-currency-dollar"></i> {{ $ai_tool->pricing_type }}
|
||||
</span>
|
||||
<span class="badge rounded-pill text-bg-highlighter-orange">
|
||||
<i class="bi bi-globe"></i>
|
||||
@if ($ai_tool->is_app_web_both == 'both')
|
||||
App & Web
|
||||
@else
|
||||
{{ ucwords($ai_tool->is_app_web_both) }}
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
@foreach ($ai_tool->keywords as $keyword)
|
||||
@if ($loop->iteration <= 3)
|
||||
<a href="{{ get_route_search_result($keyword->value_lowercased) }}"
|
||||
class="btn btn-outline-dark btn-sm border-2 px-2 py-1 rounded-pill text-decoration-none text-nowrap">{{ $keyword->value }}</a>
|
||||
@else
|
||||
<a href="{{ route('front.discover.home') }}"
|
||||
class="btn btn-outline-dark btn-sm border-2 px-2 py-1 rounded-pill text-decoration-none text-nowrap">
|
||||
+ {{ $ai_tool->keywords->count() - 3 }} more
|
||||
</a>
|
||||
@break
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,8 +5,17 @@
|
||||
@if ($loop->last)
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ $breadcrumb['name'] }}</li>
|
||||
@else
|
||||
<li class="breadcrumb-item"><a href="{{ $breadcrumb['url'] }}">{{ $breadcrumb['name'] }}</a></li>
|
||||
@if (!is_empty($breadcrumb['url']))
|
||||
<li class="breadcrumb-item text-primary"><a
|
||||
href="{{ $breadcrumb['url'] }}">{{ $breadcrumb['name'] }}</a></li>
|
||||
@else
|
||||
<li class="breadcrumb-item text-secondary">{{ $breadcrumb['name'] }}</li>
|
||||
@endif
|
||||
@endif
|
||||
@endforeach
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
@push('top_head')
|
||||
{!! $breadcrumb_context !!}
|
||||
@endpush
|
||||
|
||||
8
resources/views/front/partials/search.blade.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<form action="{{ route('front.search.post') }}" method="POST"
|
||||
class="form-inline d-flex justify-content-center border rounded-pill p-2">
|
||||
@csrf
|
||||
<input class="form-control form-control-lg border-0 rounded-pill" type="search" placeholder="Search AI Tools"
|
||||
name="query" value="{{ session()->get('query') }}" aria-label="Search">
|
||||
<button class="btn btn-lg btn-primary bg-gradient text-white rounded-pill ms-2 text-nowrap px-4 fw-bold"
|
||||
type="submit">Search with Buddy AI ✨</button>
|
||||
</form>
|
||||
34
resources/views/front/partials/sidebar.blade.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<aside class="p-4 mb-3 bg-white border-primary text-secondary rounded-3 shadow-sm">
|
||||
<p class="h4 font-family-roboto-condensed fw-bold text-primary">About aibuddytool.com</p>
|
||||
<p class="mb-0">
|
||||
AI Buddy Tool is your go-to platform for exploring the world of artificial intelligence. Centered around
|
||||
<b>Buddy AI</b>, our intuitive AI-powered search assistant, we make discovering and understanding AI tools
|
||||
effortless and engaging. Whether you're a tech enthusiast or a curious explorer, our platform simplifies AI,
|
||||
offering you a seamless experience in finding the perfect AI solutions for your needs. Join us to unlock AI's
|
||||
potential and see how it can transform your world. 🌟🤖💡
|
||||
</p>
|
||||
</aside>
|
||||
|
||||
<aside class="mb-3">
|
||||
<div class="text-secondary small mb-1">Our sponsors</div>
|
||||
<div style="--bs-aspect-ratio: 66.67%;" class="ratio ratio-1x1 rounded-2 shadow-sm">
|
||||
<a target="_blank" href="https://futurewalker.co?utm_source=external&utm_medium=sidebar&utm_campaign=aibuddytool&ref=aibuddytool">
|
||||
<img class="img-fluid rounded-2" src="https://cdn.futurewalker.co/futurewalker-600x400-banner.webp" alt="Futurewalker.co: 1 minute AI + tech news bites worth every second">
|
||||
|
||||
</a>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<aside class="mb-3">
|
||||
<form action="{{ route('front.search.post') }}" method="POST"
|
||||
class="form-inline d-flex justify-content-center">
|
||||
@csrf
|
||||
<input class="form-control form-control-lg " type="search" placeholder="Search AI Tools"
|
||||
name="query" value="{{ session()->get('query') }}" aria-label="Search">
|
||||
<button class="btn btn-outline-primary bg-gradient ms-2 text-nowrap px-2 fw-bold border-2"
|
||||
type="submit">
|
||||
<i class="bi bi-search"></i><br>
|
||||
Search
|
||||
</button>
|
||||
</form>
|
||||
</aside>
|
||||
110
resources/views/front/search_results.blade.php
Normal file
@@ -0,0 +1,110 @@
|
||||
@extends('front.layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container-lg pt-3 mb-3">
|
||||
@include('front.partials.breadcrumbs')
|
||||
|
||||
<div class="mb-3">
|
||||
@include('front.partials.search')
|
||||
</div>
|
||||
|
||||
<h1 class="h2 text-body-emphasis font-family-zilla-slab">
|
||||
<i class="bi bi-search"></i> <span class="fw-bold">{{ $query }}</span> AI tools
|
||||
</h1>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="container-lg pb-5">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-8 col-xl-9">
|
||||
@foreach ($results as $result)
|
||||
<div class="card mb-4 hover-grow shadow">
|
||||
<div class="card-body p-3 p-lg-3">
|
||||
<div class="row g-2 overflow-hidden flex-md-row h-md-250 position-relative">
|
||||
<div class="col-3 col-lg-3 d-none d-lg-flex" style="height:100%;">
|
||||
<div class="align-self-center p-1">
|
||||
<img class="img-fluid rounded-3 shadow-sm"
|
||||
src="{{ $result->ai_tool->screenshot_img }}" alt="{{ $result->tool_name }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-9 d-flex flex-column position-static">
|
||||
<a class="fw-bold" href="#">
|
||||
<h3 class="h5 fw-bold line-clamp-1">{{ $result->ai_tool->tool_name }}</h3>
|
||||
</a>
|
||||
<p class="line-clamp-2 mb-2">
|
||||
@foreach (str_extract_sentences($result->ai_tool->summary, 2) as $sentence)
|
||||
{!! $sentence !!}
|
||||
@endforeach
|
||||
</p>
|
||||
|
||||
<div class="mb-3 d-flex gap-1">
|
||||
<span class="badge rounded-pill text-bg-highlighter-yellow">
|
||||
<i class="bi bi-currency-dollar"></i> {{ $result->ai_tool->pricing_type }}
|
||||
</span>
|
||||
<span class="badge rounded-pill text-bg-highlighter-orange">
|
||||
<i class="bi bi-globe"></i>
|
||||
@if ($result->ai_tool->is_app_web_both == 'both')
|
||||
App & Web
|
||||
@else
|
||||
{{ ucwords($result->ai_tool->is_app_web_both) }}
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
@foreach ($result->ai_tool->keywords as $keyword)
|
||||
@if ($loop->iteration <= 3)
|
||||
<a href="{{ get_route_search_result($keyword->value_lowercased) }}"
|
||||
class="btn btn-outline-dark btn-sm border-2 px-2 py-1 rounded-pill text-decoration-none text-nowrap">{{ $keyword->value }}</a>
|
||||
@else
|
||||
<a href="{{ route('front.discover.home') }}"
|
||||
class="btn btn-outline-dark btn-sm border-2 px-2 py-1 rounded-pill text-decoration-none text-nowrap">
|
||||
+ {{ $result->ai_tool->keywords->count() - 3 }} more
|
||||
</a>
|
||||
@break
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
<div class="mb-2">
|
||||
@if ($results instanceof \Illuminate\Pagination\LengthAwarePaginator)
|
||||
@if ($results->hasPages())
|
||||
<div class="d-flex justify-content-center">
|
||||
{{ $results->onEachSide(1)->links('pagination::bootstrap-5-pagination-limit-10') }}
|
||||
</div>
|
||||
@endif
|
||||
@elseif ($results instanceof \Illuminate\Pagination\CursorPaginator)
|
||||
@if ($results->hasPages())
|
||||
<div class="d-flex justify-content-center">
|
||||
{{ $results->links('pagination::simple-bootstrap-5') }}
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
<div class="d-flex justify-content-center text-center text-secondary mb-3">
|
||||
<small>Use <b>Search</b> to discover AI tools by brand, task or features.</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-4 col-xl-3">
|
||||
@include('front.partials.sidebar')
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
51
resources/views/vendor/pagination/bootstrap-4.blade.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span class="page-link" aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev"
|
||||
aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="page-item disabled" aria-disabled="true"><span
|
||||
class="page-link">{{ $element }}</span></li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="page-item active" aria-current="page"><span
|
||||
class="page-link">{{ $page }}</span></li>
|
||||
@else
|
||||
<li class="page-item"><a class="page-link"
|
||||
href="{{ $url }}">{{ $page }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next"
|
||||
aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span class="page-link" aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
73
resources/views/vendor/pagination/bootstrap-5-pagination-limit-10.blade.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav class="d-flex justify-items-center justify-content-between">
|
||||
<!-- Mobile View Pagination -->
|
||||
<div class="d-flex justify-content-between flex-fill d-sm-none">
|
||||
<ul class="pagination mb-0 pb-0">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.previous')</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}"
|
||||
rel="prev">@lang('pagination.previous')</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages() && $paginator->currentPage() < 10)
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.next')</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Desktop View Pagination -->
|
||||
<div class="d-none flex-sm-fill d-sm-flex align-items-sm-center justify-content-sm-between">
|
||||
<div class="mx-1">
|
||||
<ul class="pagination pb-0 mb-0">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span class="page-link" aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev"
|
||||
aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach (range(1, min(10, $paginator->lastPage())) as $i)
|
||||
@if ($i == $paginator->currentPage())
|
||||
<li class="page-item active" aria-current="page"><span
|
||||
class="page-link">{{ $i }}</span></li>
|
||||
@else
|
||||
<li class="page-item"><a class="page-link"
|
||||
href="{{ $paginator->url($i) }}">{{ $i }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages() && $paginator->currentPage() < 10)
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next"
|
||||
aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span class="page-link" aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@endif
|
||||
83
resources/views/vendor/pagination/bootstrap-5-pagination.blade.php
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav class="d-flex justify-items-center justify-content-between">
|
||||
<div class="d-flex justify-content-between flex-fill d-sm-none">
|
||||
<ul class="pagination mb-0 pb-0">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.previous')</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}"
|
||||
rel="prev">@lang('pagination.previous')</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.next')</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="d-none flex-sm-fill d-sm-flex align-items-sm-center justify-content-sm-between">
|
||||
|
||||
<div class="mx-1">
|
||||
<ul class="pagination pb-0 mb-0">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span class="page-link" aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev"
|
||||
aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="page-item disabled" aria-disabled="true"><span
|
||||
class="page-link">{{ $element }}</span></li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="page-item active" aria-current="page"><span
|
||||
class="page-link">{{ $page }}</span></li>
|
||||
@else
|
||||
<li class="page-item"><a class="page-link"
|
||||
href="{{ $url }}">{{ $page }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next"
|
||||
aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span class="page-link" aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@endif
|
||||
11
resources/views/vendor/pagination/bootstrap-5-showing.blade.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
@if ($paginator->hasPages())
|
||||
<p class="small text-muted mb-0 pb-0">
|
||||
{!! __('Showing') !!}
|
||||
<span class="fw-semibold">{{ $paginator->firstItem() }}</span>
|
||||
{!! __('to') !!}
|
||||
<span class="fw-semibold">{{ $paginator->lastItem() }}</span>
|
||||
{{-- {!! __('of') !!}
|
||||
<span class="fw-semibold">{{ $paginator->total() }}</span> --}}
|
||||
{!! __('results') !!}
|
||||
</p>
|
||||
@endif
|
||||
94
resources/views/vendor/pagination/bootstrap-5.blade.php
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav class="d-flex justify-items-center justify-content-between">
|
||||
<div class="d-flex justify-content-between flex-fill d-sm-none">
|
||||
<ul class="pagination mb-0 pb-0">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.previous')</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}"
|
||||
rel="prev">@lang('pagination.previous')</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.next')</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="d-none flex-sm-fill d-sm-flex align-items-sm-center justify-content-sm-between">
|
||||
<div class="mx-1">
|
||||
<p class="small text-muted mb-0 pb-0">
|
||||
{!! __('Showing') !!}
|
||||
<span class="fw-semibold">{{ $paginator->firstItem() }}</span>
|
||||
{!! __('to') !!}
|
||||
<span class="fw-semibold">{{ $paginator->lastItem() }}</span>
|
||||
{!! __('of') !!}
|
||||
<span class="fw-semibold">{{ $paginator->total() }}</span>
|
||||
{!! __('results') !!}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mx-1">
|
||||
<ul class="pagination pb-0 mb-0">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span class="page-link" aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev"
|
||||
aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="page-item disabled" aria-disabled="true"><span
|
||||
class="page-link">{{ $element }}</span></li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="page-item active" aria-current="page"><span
|
||||
class="page-link">{{ $page }}</span></li>
|
||||
@else
|
||||
<li class="page-item"><a class="page-link"
|
||||
href="{{ $url }}">{{ $page }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next"
|
||||
aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span class="page-link" aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@endif
|
||||
47
resources/views/vendor/pagination/default.blade.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li>
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev"
|
||||
aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="disabled" aria-disabled="true"><span>{{ $element }}</span></li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="active" aria-current="page"><span>{{ $page }}</span></li>
|
||||
@else
|
||||
<li><a href="{{ $url }}">{{ $page }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li>
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
40
resources/views/vendor/pagination/semantic-ui.blade.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
@if ($paginator->hasPages())
|
||||
<div class="ui pagination menu" role="navigation">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<a class="icon item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')"> <i
|
||||
class="left chevron icon"></i> </a>
|
||||
@else
|
||||
<a class="icon item" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">
|
||||
<i class="left chevron icon"></i> </a>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<a class="icon item disabled" aria-disabled="true">{{ $element }}</a>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<a class="item active" href="{{ $url }}" aria-current="page">{{ $page }}</a>
|
||||
@else
|
||||
<a class="item" href="{{ $url }}">{{ $page }}</a>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<a class="icon item" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">
|
||||
<i class="right chevron icon"></i> </a>
|
||||
@else
|
||||
<a class="icon item disabled" aria-disabled="true" aria-label="@lang('pagination.next')"> <i
|
||||
class="right chevron icon"></i> </a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
27
resources/views/vendor/pagination/simple-bootstrap-4.blade.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.previous')</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.next')</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
30
resources/views/vendor/pagination/simple-bootstrap-5.blade.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="Pagination Navigation">
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">{!! __('pagination.previous') !!}</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">
|
||||
{!! __('pagination.previous') !!}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}"
|
||||
rel="next">{!! __('pagination.next') !!}</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">{!! __('pagination.next') !!}</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
19
resources/views/vendor/pagination/simple-default.blade.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="disabled" aria-disabled="true"><span>@lang('pagination.previous')</span></li>
|
||||
@else
|
||||
<li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a></li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li><a href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a></li>
|
||||
@else
|
||||
<li class="disabled" aria-disabled="true"><span>@lang('pagination.next')</span></li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
29
resources/views/vendor/pagination/simple-tailwind.blade.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="Pagination Navigation" class="flex justify-between">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<span
|
||||
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">
|
||||
{!! __('pagination.previous') !!}
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev"
|
||||
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
|
||||
{!! __('pagination.previous') !!}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next"
|
||||
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
|
||||
{!! __('pagination.next') !!}
|
||||
</a>
|
||||
@else
|
||||
<span
|
||||
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">
|
||||
{!! __('pagination.next') !!}
|
||||
</span>
|
||||
@endif
|
||||
</nav>
|
||||
@endif
|
||||
130
resources/views/vendor/pagination/tailwind.blade.php
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="{{ __('Pagination Navigation') }}" class="flex items-center justify-between">
|
||||
<div class="flex justify-between flex-1 sm:hidden">
|
||||
@if ($paginator->onFirstPage())
|
||||
<span
|
||||
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">
|
||||
{!! __('pagination.previous') !!}
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $paginator->previousPageUrl() }}"
|
||||
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
|
||||
{!! __('pagination.previous') !!}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if ($paginator->hasMorePages())
|
||||
<a href="{{ $paginator->nextPageUrl() }}"
|
||||
class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
|
||||
{!! __('pagination.next') !!}
|
||||
</a>
|
||||
@else
|
||||
<span
|
||||
class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">
|
||||
{!! __('pagination.next') !!}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-gray-700 leading-5">
|
||||
{!! __('Showing') !!}
|
||||
@if ($paginator->firstItem())
|
||||
<span class="font-medium">{{ $paginator->firstItem() }}</span>
|
||||
{!! __('to') !!}
|
||||
<span class="font-medium">{{ $paginator->lastItem() }}</span>
|
||||
@else
|
||||
{{ $paginator->count() }}
|
||||
@endif
|
||||
{!! __('of') !!}
|
||||
<span class="font-medium">{{ $paginator->total() }}</span>
|
||||
{!! __('results') !!}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="relative z-0 inline-flex shadow-sm rounded-md">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<span aria-disabled="true" aria-label="{{ __('pagination.previous') }}">
|
||||
<span
|
||||
class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-l-md leading-5"
|
||||
aria-hidden="true">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev"
|
||||
class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-l-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150"
|
||||
aria-label="{{ __('pagination.previous') }}">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<span aria-disabled="true">
|
||||
<span
|
||||
class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 cursor-default leading-5">{{ $element }}</span>
|
||||
</span>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<span aria-current="page">
|
||||
<span
|
||||
class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5">{{ $page }}</span>
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $url }}"
|
||||
class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-500 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150"
|
||||
aria-label="{{ __('Go to page :page', ['page' => $page]) }}">
|
||||
{{ $page }}
|
||||
</a>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next"
|
||||
class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-r-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150"
|
||||
aria-label="{{ __('pagination.next') }}">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
@else
|
||||
<span aria-disabled="true" aria-label="{{ __('pagination.next') }}">
|
||||
<span
|
||||
class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-r-md leading-5"
|
||||
aria-hidden="true">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@endif
|
||||
@@ -21,12 +21,17 @@
|
||||
|
||||
$url_to_crawl = UrlToCrawl::find(1);
|
||||
|
||||
if (is_null($url_to_crawl))
|
||||
{
|
||||
return ;
|
||||
if (is_null($url_to_crawl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GetUrlBodyJob::dispatch($url_to_crawl->id)->onQueue('default')->onConnection('default');
|
||||
|
||||
return 'ok';
|
||||
});
|
||||
});
|
||||
|
||||
Route::get('/epoch', function () {
|
||||
|
||||
dd(epoch_now_timestamp(1));
|
||||
|
||||
});
|
||||
|
||||
@@ -51,6 +51,20 @@
|
||||
|
||||
});
|
||||
|
||||
Route::prefix('ai-search')->group(function () {
|
||||
|
||||
Route::post('/', [\App\Http\Controllers\Front\FrontSearchController::class, 'search'])->name('front.search.post');
|
||||
|
||||
Route::get('/{query}', [\App\Http\Controllers\Front\FrontSearchController::class, 'searchResult'])->name('front.search.results');
|
||||
|
||||
});
|
||||
|
||||
Route::prefix('ai-tool')->group(function () {
|
||||
|
||||
Route::get('/{ai_tool_slug}', [\App\Http\Controllers\Front\FrontToolController::class, 'show'])->name('front.aitool.show');
|
||||
|
||||
});
|
||||
|
||||
Route::get('/terms', [App\Http\Controllers\Front\FrontHomeController::class, 'terms'])->name('front.terms')->middleware('cacheResponse:2630000');
|
||||
|
||||
Route::get('/privacy', [App\Http\Controllers\Front\FrontHomeController::class, 'privacy'])->name('front.privacy')->middleware('cacheResponse:2630000');
|
||||
|
||||