mirror of
https://repo.getmonero.org/AnonDev/xmrmemes.git
synced 2024-12-21 13:45:00 -05:00
Almost complete site
Add dark / light theme Add social sharing on meme pages Add approving / pending admin section Improve design Add pagination on profiles Make front end date time user friendly Finish rough draft of site And Much more... Still need to fix a few minor things before it goes live. Almost complete.
This commit is contained in:
parent
52a9007882
commit
dbfda5cf9e
23
README.md
23
README.md
@ -1,16 +1,17 @@
|
||||
## Work In Progress
|
||||
|
||||
Not Ready Yet...
|
||||
Almost Done...
|
||||
|
||||
## About XmrMemes
|
||||
|
||||
Dependencies
|
||||
Meme site for Monero. You can submit memes and get paid.
|
||||
|
||||
## Dependencies
|
||||
|
||||
```
|
||||
sudo apt install php-bcmath
|
||||
sudo apt install php-bcmath supervisor
|
||||
```
|
||||
|
||||
|
||||
## Running Monero Daemon
|
||||
|
||||
```
|
||||
@ -21,16 +22,26 @@ sudo apt install php-bcmath
|
||||
./monero-wallet-rpc --testnet --rpc-bind-port 28083 --disable-rpc-login --wallet-dir .
|
||||
```
|
||||
|
||||
## Seeding
|
||||
## Seeding the Database
|
||||
|
||||
You must seed addresses first and be connected to the daemon.
|
||||
|
||||
```
|
||||
php artisan migrate
|
||||
```
|
||||
|
||||
```
|
||||
php artisan db:seed --class=AddressSeeder
|
||||
```
|
||||
|
||||
## Cron Job to process payments
|
||||
|
||||
You must set up supervisor https://laravel.com/docs/8.x/queues#supervisor-configuration to process queues (jobs)
|
||||
|
||||
Then set up 1 cron job to call
|
||||
|
||||
```
|
||||
php artisan db:seed
|
||||
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
|
||||
```
|
||||
|
||||
## This Project Uses Laravel
|
||||
|
@ -5,6 +5,8 @@ namespace App\Console;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
use App\Jobs\ProcessPayments;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
@ -24,7 +26,7 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
// $schedule->command('inspire')->hourly();
|
||||
$schedule->job(new ProcessPayments)->withoutOverlapping()->everyMinute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
25
app/Http/Controllers/ApiController.php
Normal file
25
app/Http/Controllers/ApiController.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Meme;
|
||||
|
||||
class ApiController extends Controller
|
||||
{
|
||||
public function documentation()
|
||||
{
|
||||
$data = [
|
||||
'memes_example' => json_encode(Meme::get(), JSON_PRETTY_PRINT),
|
||||
'memes_endpoint' => url('api/memes'),
|
||||
];
|
||||
return view('api', ['data' => $data]);
|
||||
}
|
||||
|
||||
public function memes()
|
||||
{
|
||||
$memes = Meme::get();
|
||||
return $memes;
|
||||
}
|
||||
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Meme;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
@ -23,6 +24,12 @@ class DashboardController extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('dashboard');
|
||||
if (\Auth::user()->is_admin === 1) {
|
||||
$memes_pending = Meme::withoutGlobalScope('approved')->where('is_approved', 0)->get();
|
||||
}
|
||||
$data = [
|
||||
'memes_pending' => $memes_pending ?? null,
|
||||
];
|
||||
return view('dashboard', ['data' => $data]);
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,11 @@ class MemeController extends Controller
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'title' => ['required', 'string', 'max:255'],
|
||||
'caption' => ['string', 'max:255', 'nullable'],
|
||||
'image' => ['required', 'image'],
|
||||
]);
|
||||
$user = \Auth::user();
|
||||
$used_ids = Meme::pluck('address_id')->toArray();
|
||||
$address = Address::whereNotIn('id', $used_ids)->first('id');
|
||||
@ -78,7 +83,7 @@ class MemeController extends Controller
|
||||
'user_id' => $user->id,
|
||||
'address_id' => $address->id,
|
||||
'title' => $request->input('title'),
|
||||
// 'caption' => $request->input('caption'),
|
||||
'caption' => $request->input('caption'),
|
||||
'image' => $request->file('image'),
|
||||
]);
|
||||
}
|
||||
@ -133,14 +138,27 @@ class MemeController extends Controller
|
||||
//
|
||||
}
|
||||
|
||||
public function approve($id)
|
||||
{
|
||||
if (\Auth::user()->is_admin === 1) {
|
||||
$meme = Meme::withoutGlobalScope('approved')->find($id);
|
||||
$meme->is_approved = 1;
|
||||
$meme->save();
|
||||
return redirect()->away(url()->previous());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Meme $meme
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Meme $meme)
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
if (\Auth::user()->is_admin === 1) {
|
||||
Meme::withoutGlobalScope('approved')->where('id', $id)->delete();
|
||||
return redirect()->away(url()->previous());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
app/Http/Controllers/ThemeSwitcherController.php
Normal file
14
app/Http/Controllers/ThemeSwitcherController.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ThemeSwitcherController extends Controller
|
||||
{
|
||||
public function theme(Request $request, $style)
|
||||
{
|
||||
$request->session()->put('theme', $style);
|
||||
return redirect()->away(url()->previous());
|
||||
}
|
||||
}
|
@ -2,64 +2,10 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Tip;
|
||||
use App\Models\Address;
|
||||
use App\Models\Meme;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use MoneroIntegrations\MoneroPhp\walletRPC;
|
||||
|
||||
class TipController extends Controller
|
||||
{
|
||||
|
||||
public function check()
|
||||
{
|
||||
try {
|
||||
$walletRPC = new walletRPC('127.0.0.1', config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
||||
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
||||
$get_transfers = $walletRPC->get_transfers('all', true);
|
||||
// dd($get_transfers);
|
||||
// dd($walletRPC->get_balance());
|
||||
foreach ($get_transfers['in'] as $transfer) {
|
||||
$address = Address::where('address', $transfer['address'])->first();
|
||||
$tip_exists = Tip::where('txid', $transfer['txid'])->first();
|
||||
if ($address && !$tip_exists) {
|
||||
$tip = new Tip();
|
||||
$tip->address_id = $address->id;
|
||||
$tip->amount = $transfer['amount'];
|
||||
$tip->txid = $transfer['txid'];
|
||||
$tip->height = $transfer['height'];
|
||||
$tip->save();
|
||||
}
|
||||
}
|
||||
$walletRPC->close_wallet();
|
||||
} catch (\Exception $e) {
|
||||
echo 'Caught exception: ', $e->getMessage(), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
public function payout()
|
||||
{
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
try {
|
||||
$walletRPC = new walletRPC('127.0.0.1', config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
||||
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
||||
$tip = Tip::where('is_sent', 0)->firstOrFail();
|
||||
$meme = Meme::where('address_id', $tip->address_id)->first();
|
||||
if ($meme->user->address) {
|
||||
$send_funds = $walletRPC->sweep_all($meme->user->address, $tip->address->address_index);
|
||||
$tip->is_sent = 1;
|
||||
$tip->save();
|
||||
}
|
||||
$walletRPC->close_wallet();
|
||||
} catch (\Exception $e) {
|
||||
echo 'Caught exception: ', $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
|
@ -4,13 +4,16 @@ namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
use App\Models\Meme;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
public function show($id)
|
||||
{
|
||||
$user = User::where('id', $id)->firstOrFail();
|
||||
$data = [
|
||||
'user' => User::with('memes')->where('id', $id)->firstOrFail(),
|
||||
'user' => $user,
|
||||
'memes' => Meme::where('user_id', $user->id)->orderByDesc('created_at')->paginate(20),
|
||||
];
|
||||
return view('profile', ['data' => $data]);
|
||||
}
|
||||
|
100
app/Jobs/ProcessPayments.php
Normal file
100
app/Jobs/ProcessPayments.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
use App\Models\Tip;
|
||||
use App\Models\Address;
|
||||
use App\Models\Meme;
|
||||
use MoneroIntegrations\MoneroPhp\walletRPC;
|
||||
|
||||
// Can put code below inside functions to debug the Monero library
|
||||
// ini_set('display_errors', 1);
|
||||
// ini_set('display_startup_errors', 1);
|
||||
// error_reporting(E_ALL);
|
||||
|
||||
class ProcessPayments implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->get_transactions();
|
||||
$this->payout();
|
||||
}
|
||||
|
||||
public function get_transactions()
|
||||
{
|
||||
try {
|
||||
$walletRPC = new walletRPC('127.0.0.1', config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
||||
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
||||
$get_transfers = $walletRPC->get_transfers('all', true);
|
||||
if (isset($get_transfers['in'])) {
|
||||
foreach ($get_transfers['in'] as $transfer) {
|
||||
$address = Address::where('address', $transfer['address'])->first();
|
||||
$tip_exists = Tip::where('txid', $transfer['txid'])->first();
|
||||
if ($address && !$tip_exists) {
|
||||
$tip = new Tip();
|
||||
$tip->address_id = $address->id;
|
||||
$tip->amount = $transfer['amount'];
|
||||
$tip->txid = $transfer['txid'];
|
||||
$tip->is_deposit = 1;
|
||||
$tip->save();
|
||||
$meme = Meme::where('address_id', $address->id)->firstOrFail();
|
||||
$meme->payment_pending = 1;
|
||||
$meme->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
$walletRPC->close_wallet();
|
||||
} catch (\Exception $e) {
|
||||
echo 'Caught exception: ', $e->getMessage(), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
public function payout()
|
||||
{
|
||||
try {
|
||||
$walletRPC = new walletRPC('127.0.0.1', config('app.xmr_network_port')); // Change to match your wallet (monero-wallet-rpc) IP address and port; 18083 is the customary port for mainnet, 28083 for testnet, 38083 for stagenet
|
||||
$open_wallet = $walletRPC->open_wallet(config('app.xmr_wallet_name'), '');
|
||||
$meme = Meme::where('payment_pending', 1)->firstOrFail();
|
||||
if ($meme->user->address) {
|
||||
$send_funds = $walletRPC->sweep_all($meme->user->address, $meme->address->address_index);
|
||||
if ($send_funds['amount_list']) {
|
||||
$tip = new Tip;
|
||||
$tip->address_id = $meme->address_id;
|
||||
$tip->amount = $send_funds['amount_list'][0];
|
||||
$tip->txid = $send_funds['tx_hash_list'][0];
|
||||
$tip->is_deposit = 0;
|
||||
$tip->save();
|
||||
$meme->payment_pending = 0;
|
||||
$meme->save();
|
||||
}
|
||||
}
|
||||
$walletRPC->close_wallet();
|
||||
} catch (\Exception $e) {
|
||||
echo 'Caught exception: ', $e->getMessage(), "\n";
|
||||
}
|
||||
}
|
||||
}
|
@ -4,16 +4,25 @@ namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Meme extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
protected $appends = ['meme_tips_total'];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::addGlobalScope('approved', function (Builder $builder) {
|
||||
$builder->where('is_approved', 1);
|
||||
});
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
@ -26,12 +35,12 @@ class Meme extends Model
|
||||
|
||||
public function tips()
|
||||
{
|
||||
return $this->hasManyThrough(Tip::class, Address::class, 'id', 'address_id', 'address_id', 'id');
|
||||
return $this->hasManyThrough(Tip::class, Address::class, 'id', 'address_id', 'address_id', 'id')->orderBy('created_at', 'DESC');
|
||||
}
|
||||
|
||||
public function getMemeTipsTotalAttribute()
|
||||
{
|
||||
return $this->tips->sum('amount_formatted');
|
||||
return $this->tips->where('is_deposit', 1)->sum('amount_formatted');
|
||||
}
|
||||
|
||||
public function setImageAttribute($value)
|
||||
|
@ -51,6 +51,7 @@ class User extends Authenticatable
|
||||
|
||||
public function tips()
|
||||
{
|
||||
return $this->hasManyThrough(Tip::class, Meme::class, 'address_id', 'id', 'id', 'address_id');
|
||||
return $this->hasManyThrough(Tip::class, Meme::class, 'id', 'address_id');
|
||||
}
|
||||
|
||||
@ -61,7 +62,7 @@ class User extends Authenticatable
|
||||
|
||||
public function getTipsTotalAttribute()
|
||||
{
|
||||
return $this->tips->sum('amount_formatted');
|
||||
return $this->tips->where('is_deposit', 1)->sum('amount_formatted');
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
protected function configureRateLimiting()
|
||||
{
|
||||
RateLimiter::for('api', function (Request $request) {
|
||||
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
|
||||
return Limit::perHour(60)->by(optional($request->user())->id ?: $request->ip());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ class CreateUsersTable extends Migration
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password');
|
||||
$table->string('address', 95);
|
||||
$table->boolean('is_admin')->default(0);
|
||||
$table->rememberToken();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
@ -20,6 +20,9 @@ class CreateMemesTable extends Migration
|
||||
$table->string('title');
|
||||
$table->string('caption')->nullable();
|
||||
$table->string('image')->nullable();
|
||||
$table->boolean('is_approved')->default(0);
|
||||
$table->boolean('payment_pending')->default(0);
|
||||
$table->softDeletes();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
@ -18,8 +18,7 @@ class CreateTipsTable extends Migration
|
||||
$table->foreignId('address_id')->constrained();
|
||||
$table->bigInteger('amount');
|
||||
$table->string('txid')->unique();
|
||||
$table->bigInteger('height');
|
||||
$table->boolean('is_sent')->default(0);
|
||||
$table->boolean('is_deposit');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
36
database/migrations/2021_07_31_055445_create_jobs_table.php
Normal file
36
database/migrations/2021_07_31_055445_create_jobs_table.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateJobsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('jobs', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('queue')->index();
|
||||
$table->longText('payload');
|
||||
$table->unsignedTinyInteger('attempts');
|
||||
$table->unsignedInteger('reserved_at')->nullable();
|
||||
$table->unsignedInteger('available_at');
|
||||
$table->unsignedInteger('created_at');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('jobs');
|
||||
}
|
||||
}
|
16166
public/css/app_dark.css
vendored
Normal file
16166
public/css/app_dark.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,12 +7,12 @@
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
:root {
|
||||
--blue: #ff6600;
|
||||
--blue: #0d6efd;
|
||||
--indigo: #6574cd;
|
||||
--purple: #9561e2;
|
||||
--pink: #f66d9b;
|
||||
--red: #e3342f;
|
||||
--orange: #f6993f;
|
||||
--orange: #ff6600;
|
||||
--yellow: #ffed4a;
|
||||
--green: #38c172;
|
||||
--teal: #4dc0b5;
|
||||
@ -16155,3 +16155,7 @@ readers do not read off random characters that represent icons */
|
||||
#social-links ul {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.table {
|
||||
table-layout: fixed;
|
||||
}
|
586
public/js/app.js
vendored
586
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
173
public/js/manifest.js
vendored
Normal file
173
public/js/manifest.js
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
/******/ (() => { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({});
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = __webpack_modules__;
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/chunk loaded */
|
||||
/******/ (() => {
|
||||
/******/ var deferred = [];
|
||||
/******/ __webpack_require__.O = (result, chunkIds, fn, priority) => {
|
||||
/******/ if(chunkIds) {
|
||||
/******/ priority = priority || 0;
|
||||
/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
|
||||
/******/ deferred[i] = [chunkIds, fn, priority];
|
||||
/******/ return;
|
||||
/******/ }
|
||||
/******/ var notFulfilled = Infinity;
|
||||
/******/ for (var i = 0; i < deferred.length; i++) {
|
||||
/******/ var [chunkIds, fn, priority] = deferred[i];
|
||||
/******/ var fulfilled = true;
|
||||
/******/ for (var j = 0; j < chunkIds.length; j++) {
|
||||
/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
|
||||
/******/ chunkIds.splice(j--, 1);
|
||||
/******/ } else {
|
||||
/******/ fulfilled = false;
|
||||
/******/ if(priority < notFulfilled) notFulfilled = priority;
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ if(fulfilled) {
|
||||
/******/ deferred.splice(i--, 1)
|
||||
/******/ result = fn();
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ return result;
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/define property getters */
|
||||
/******/ (() => {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/ __webpack_require__.d = (exports, definition) => {
|
||||
/******/ for(var key in definition) {
|
||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/global */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.g = (function() {
|
||||
/******/ if (typeof globalThis === 'object') return globalThis;
|
||||
/******/ try {
|
||||
/******/ return this || new Function('return this')();
|
||||
/******/ } catch (e) {
|
||||
/******/ if (typeof window === 'object') return window;
|
||||
/******/ }
|
||||
/******/ })();
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/make namespace object */
|
||||
/******/ (() => {
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = (exports) => {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/node module decorator */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.nmd = (module) => {
|
||||
/******/ module.paths = [];
|
||||
/******/ if (!module.children) module.children = [];
|
||||
/******/ return module;
|
||||
/******/ };
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/jsonp chunk loading */
|
||||
/******/ (() => {
|
||||
/******/ // no baseURI
|
||||
/******/
|
||||
/******/ // object to store loaded and loading chunks
|
||||
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
|
||||
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
|
||||
/******/ var installedChunks = {
|
||||
/******/ "/js/manifest": 0,
|
||||
/******/ "css/app_dark": 0,
|
||||
/******/ "css/app_light": 0
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // no chunk on demand loading
|
||||
/******/
|
||||
/******/ // no prefetching
|
||||
/******/
|
||||
/******/ // no preloaded
|
||||
/******/
|
||||
/******/ // no HMR
|
||||
/******/
|
||||
/******/ // no HMR manifest
|
||||
/******/
|
||||
/******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
|
||||
/******/
|
||||
/******/ // install a JSONP callback for chunk loading
|
||||
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
|
||||
/******/ var [chunkIds, moreModules, runtime] = data;
|
||||
/******/ // add "moreModules" to the modules object,
|
||||
/******/ // then flag all "chunkIds" as loaded and fire callback
|
||||
/******/ var moduleId, chunkId, i = 0;
|
||||
/******/ for(moduleId in moreModules) {
|
||||
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
|
||||
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ if(runtime) var result = runtime(__webpack_require__);
|
||||
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
|
||||
/******/ for(;i < chunkIds.length; i++) {
|
||||
/******/ chunkId = chunkIds[i];
|
||||
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
|
||||
/******/ installedChunks[chunkId][0]();
|
||||
/******/ }
|
||||
/******/ installedChunks[chunkIds[i]] = 0;
|
||||
/******/ }
|
||||
/******/ return __webpack_require__.O(result);
|
||||
/******/ }
|
||||
/******/
|
||||
/******/ var chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || [];
|
||||
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
|
||||
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
|
||||
/******/ })();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/
|
||||
/******/
|
||||
/******/ })()
|
||||
;
|
37206
public/js/vendor.js
vendored
Normal file
37206
public/js/vendor.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,7 @@
|
||||
{
|
||||
"/js/app.js": "/js/app.js",
|
||||
"/css/app.css": "/css/app.css"
|
||||
"/js/app.js": "/js/app.js?id=a4f7ea48d857a5e8d88e",
|
||||
"/js/manifest.js": "/js/manifest.js?id=d7335e682eb6c876d5bc",
|
||||
"/css/app_dark.css": "/css/app_dark.css?id=77995f3b0798a182ca9f",
|
||||
"/css/app_light.css": "/css/app_light.css?id=8971b6e0fc76badb2856",
|
||||
"/js/vendor.js": "/js/vendor.js?id=964b623e0af1bb38e06e"
|
||||
}
|
||||
|
@ -36,3 +36,8 @@
|
||||
#social-links ul {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
// Fixes text truncate not working in tables
|
||||
.table {
|
||||
table-layout: fixed;
|
||||
}
|
15
resources/sass/_variables.scss
vendored
15
resources/sass/_variables.scss
vendored
@ -1,19 +1,4 @@
|
||||
// Body
|
||||
$body-bg: #f8fafc;
|
||||
|
||||
// Typography
|
||||
$font-family-sans-serif: 'Nunito', sans-serif;
|
||||
$font-size-base: 0.9rem;
|
||||
$line-height-base: 1.6;
|
||||
|
||||
// Colors
|
||||
$blue: #ff6600;
|
||||
$indigo: #6574cd;
|
||||
$purple: #9561e2;
|
||||
$pink: #f66d9b;
|
||||
$red: #e3342f;
|
||||
$orange: #f6993f;
|
||||
$yellow: #ffed4a;
|
||||
$green: #38c172;
|
||||
$teal: #4dc0b5;
|
||||
$cyan: #6cb2eb;
|
||||
|
166
resources/sass/_variables_dark.scss
vendored
Normal file
166
resources/sass/_variables_dark.scss
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
// Body
|
||||
$body-bg: #000000;
|
||||
|
||||
// Colors
|
||||
$blue: #0d6efd;
|
||||
$indigo: #6574cd;
|
||||
$purple: #9561e2;
|
||||
$pink: #f66d9b;
|
||||
$red: #e3342f;
|
||||
$orange: #ff6600;
|
||||
$yellow: #ffed4a;
|
||||
$green: #38c172;
|
||||
$teal: #4dc0b5;
|
||||
$cyan: #6cb2eb;
|
||||
|
||||
|
||||
$white: #fff !default;
|
||||
$gray-100: #f8f9fa !default;
|
||||
$gray-200: #ebebeb !default;
|
||||
$gray-300: #dee2e6 !default;
|
||||
$gray-400: #ced4da !default;
|
||||
$gray-500: #adb5bd !default;
|
||||
$gray-600: #999 !default;
|
||||
$gray-700: #444 !default;
|
||||
$gray-800: #121212 !default;
|
||||
$gray-900: #222 !default;
|
||||
$black: #000 !default;
|
||||
|
||||
|
||||
|
||||
$primary: $orange !default;
|
||||
$secondary: $gray-700 !default;
|
||||
$success: $cyan !default;
|
||||
$info: $cyan !default;
|
||||
$warning: $yellow !default;
|
||||
$danger: $red !default;
|
||||
$light: $gray-800 !default;
|
||||
$dark: $gray-500 !default;
|
||||
|
||||
$yiq-contrasted-threshold: 175 !default;
|
||||
|
||||
// Body
|
||||
|
||||
$body-bg: #121212 !default;
|
||||
$body-color: $white !default;
|
||||
|
||||
// Links
|
||||
|
||||
$link-color: $primary !default;
|
||||
|
||||
// Tables
|
||||
|
||||
$table-accent-bg: $gray-900 !default;
|
||||
|
||||
$table-border-color: $gray-700 !default;
|
||||
|
||||
$table-dark-bg: $gray-500 !default;
|
||||
$table-dark-border-color: darken($gray-500, 7.5%) !default;
|
||||
$table-dark-color: $body-bg !default;
|
||||
|
||||
// Forms
|
||||
|
||||
$input-border-color: transparent !default;
|
||||
|
||||
$input-group-addon-color: $gray-500 !default;
|
||||
$input-group-addon-bg: $gray-700 !default;
|
||||
|
||||
$custom-file-color: $gray-500 !default;
|
||||
$custom-file-border-color: $gray-700 !default;
|
||||
|
||||
// Dropdowns
|
||||
|
||||
$dropdown-bg: $gray-900 !default;
|
||||
$dropdown-border-color: $gray-700 !default;
|
||||
$dropdown-divider-bg: $gray-700 !default;
|
||||
|
||||
$dropdown-link-color: $white !default;
|
||||
$dropdown-link-hover-color: $white !default;
|
||||
$dropdown-link-hover-bg: $primary !default;
|
||||
|
||||
// Navs
|
||||
|
||||
$nav-link-padding-x: 2rem !default;
|
||||
$nav-link-disabled-color: $gray-500 !default;
|
||||
|
||||
$nav-tabs-border-color: $gray-700 !default;
|
||||
$nav-tabs-link-hover-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent !default;
|
||||
$nav-tabs-link-active-color: $white !default;
|
||||
$nav-tabs-link-active-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent !default;
|
||||
|
||||
// Navbar
|
||||
|
||||
$navbar-dark-color: $white !default;
|
||||
$navbar-dark-hover-color: $primary !default;
|
||||
|
||||
$navbar-light-color: rgba($white,.5) !default;
|
||||
$navbar-light-hover-color: $white !default;
|
||||
$navbar-light-active-color: $white !default;
|
||||
$navbar-light-disabled-color: rgba($white,.3) !default;
|
||||
$navbar-light-toggler-border-color: rgba($white,.1) !default;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination-color: $white !default;
|
||||
$pagination-bg: $primary !default;
|
||||
$pagination-border-width: 0 !default;
|
||||
$pagination-border-color: transparent !default;
|
||||
|
||||
$pagination-hover-color: $white !default;
|
||||
$pagination-hover-bg: lighten($primary, 10%) !default;
|
||||
$pagination-hover-border-color: transparent !default;
|
||||
|
||||
$pagination-active-bg: $pagination-hover-bg !default;
|
||||
$pagination-active-border-color: transparent !default;
|
||||
|
||||
$pagination-disabled-color: $white !default;
|
||||
$pagination-disabled-bg: darken($primary, 15%) !default;
|
||||
$pagination-disabled-border-color: transparent !default;
|
||||
|
||||
// Jumbotron
|
||||
|
||||
$jumbotron-bg: $gray-900 !default;
|
||||
|
||||
// Cards
|
||||
|
||||
$card-cap-bg: $gray-700 !default;
|
||||
$card-bg: $gray-900 !default;
|
||||
|
||||
// Popovers
|
||||
|
||||
$popover-bg: $gray-900 !default;
|
||||
|
||||
$popover-header-bg: $gray-700 !default;
|
||||
|
||||
// Modals
|
||||
|
||||
$modal-content-bg: $gray-900 !default;
|
||||
$modal-content-border-color: $gray-700 !default;
|
||||
|
||||
$modal-header-border-color: $gray-700 !default;
|
||||
|
||||
// Progress bars
|
||||
|
||||
$progress-height: 0.625rem !default;
|
||||
$progress-font-size: 0.625rem !default;
|
||||
$progress-bg: $gray-700 !default;
|
||||
|
||||
// List group
|
||||
|
||||
$list-group-bg: $gray-900 !default;
|
||||
$list-group-border-color: $gray-700 !default;
|
||||
|
||||
$list-group-hover-bg: $gray-700 !default;
|
||||
|
||||
// Breadcrumbs
|
||||
|
||||
$breadcrumb-bg: $gray-700 !default;
|
||||
|
||||
// Close
|
||||
|
||||
$close-color: $white !default;
|
||||
$close-text-shadow: none !default;
|
||||
|
||||
// Code
|
||||
|
||||
$pre-color: inherit !default;
|
16
resources/sass/_variables_light.scss
vendored
Normal file
16
resources/sass/_variables_light.scss
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// Body
|
||||
$body-bg: #f8fafc;
|
||||
|
||||
// Colors
|
||||
$blue: #0d6efd;
|
||||
$indigo: #6574cd;
|
||||
$purple: #9561e2;
|
||||
$pink: #f66d9b;
|
||||
$red: #e3342f;
|
||||
$orange: #ff6600;
|
||||
$yellow: #ffed4a;
|
||||
$green: #38c172;
|
||||
$teal: #4dc0b5;
|
||||
$cyan: #6cb2eb;
|
||||
|
||||
$primary: $orange !default;
|
7
resources/sass/app_dark.scss
vendored
Normal file
7
resources/sass/app_dark.scss
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
@import 'variables_dark';
|
||||
@import 'common';
|
||||
|
||||
.img-qr {
|
||||
background: white;
|
||||
margin: 1rem 0;
|
||||
}
|
2
resources/sass/app_light.scss
vendored
Normal file
2
resources/sass/app_light.scss
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
@import 'variables_light';
|
||||
@import 'common';
|
@ -7,7 +7,7 @@
|
||||
<h1>About</h1>
|
||||
<p class="lead">Post Monero memes and get tipped Monero.</p>
|
||||
<p class="lead mb-0">Monero (XMR) Donations Happily Accepted.</p>
|
||||
<img src="{{ $data['qr'] }}" alt="QR code">
|
||||
<img class="img-qr" src="{{ $data['qr'] }}" alt="QR code">
|
||||
<p class="lead">{{ $data['address'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
23
resources/views/api.blade.php
Normal file
23
resources/views/api.blade.php
Normal file
@ -0,0 +1,23 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-12">
|
||||
<h1 class="text-center">API Documentation</h1>
|
||||
<p class="lead mt-3 text-center">
|
||||
Memes Endpoint: <code>{{ $data['memes_endpoint'] }}</code>
|
||||
</p>
|
||||
<p class="text-center">
|
||||
API is experimental. Breaking changes may occur in the future.
|
||||
</p>
|
||||
<p class="mb-5 text-center">
|
||||
Rate Limit: 60 Request Per Hour
|
||||
</p>
|
||||
<code>
|
||||
<pre class="bg-white p-1">{{ $data['memes_example'] }}</pre>
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
@ -6,18 +6,38 @@
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Dashboard') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
@if (session('status'))
|
||||
<div class="alert alert-success" role="alert">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{ __('You are logged in!') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if ($data['memes_pending'])
|
||||
<div class="row row-cols-1 row-cols-md-4 grid-memes mt-3">
|
||||
@foreach ($data['memes_pending'] as $meme)
|
||||
<div class="col mb-4">
|
||||
<div class="card">
|
||||
@if ($meme->image)
|
||||
<img src="{{ url($meme->image) }}" class="card-img-top mx-auto d-block" alt="{{ $meme->title }} Meme">
|
||||
@else
|
||||
<img src="https://picsum.photos/200" class="card-img-top" alt="{{ $meme->title }} Meme">
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{ $meme->title }}</h5>
|
||||
<p class="card-text">{{ $meme->caption }}</p>
|
||||
<p class="card-text"><a href="{{ url('meme/approve/' . $meme->id) }}">Approve</a> | <a href="{{ url('meme/destroy/' . $meme->id) }}">Delete</a></p>
|
||||
<p class="card-text">By: <a href="{{ url('/user/' . $meme->user->id) }}">{{ $meme->user->name }}</a></p>
|
||||
<p class="card-text">{{ $meme->created_at->diffForHumans() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
|
@ -23,7 +23,7 @@
|
||||
</a>
|
||||
<p class="card-text">By: <a href="{{ url('/user/' . $meme->user->id) }}">{{ $meme->user->name }}</a></p>
|
||||
<p class="card-text">{{ $meme->meme_tips_total }} XMR Recieved</p>
|
||||
<p class="card-text">{{ $meme->created_at }}</p>
|
||||
<p class="card-text">{{ $meme->created_at->diffForHumans() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -13,17 +13,18 @@
|
||||
<!-- Scripts -->
|
||||
<script src="{{ asset('js/app.js') }}" defer></script>
|
||||
|
||||
<!-- Fonts -->
|
||||
{{-- <link rel="dns-prefetch" href="//fonts.gstatic.com"> --}}
|
||||
{{-- <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet"> --}}
|
||||
|
||||
<!-- Styles -->
|
||||
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
|
||||
@if (Session::get('theme'))
|
||||
<link href="{{ url('') . mix('css/app_' . Session::get('theme') . '.css') }}" rel="stylesheet">
|
||||
@else
|
||||
<link href="{{ url('') . mix('css/app_light.css') }}" rel="stylesheet">
|
||||
@endif
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-light shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{{ url('/') }}">
|
||||
<img class="img-logo" src="{{ url('logo.png') }}" alt="">
|
||||
@ -51,6 +52,14 @@
|
||||
|
||||
<!-- Right Side Of Navbar -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<span class="nav-item mx-2 my-auto" data-toggle="tooltip" data-placement="bottom" title="{{ Session::get('theme') === 'light' ? 'Dark' : 'Light' }} Theme">
|
||||
@if (Session::get('theme') === 'dark')
|
||||
<a class="btn btn-light" href="{{ url('/theme/light') }}" role="button"><i class="fas fa-sun text-primary"></i></a>
|
||||
@else
|
||||
<a class="btn btn-light" href="{{ url('/theme/dark') }}" role="button"><i class="far fa-moon text-dark"></i></a>
|
||||
@endif
|
||||
</span>
|
||||
|
||||
<!-- Authentication Links -->
|
||||
@guest
|
||||
@if (Route::has('login'))
|
||||
@ -96,12 +105,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="py-4">
|
||||
@yield('content')
|
||||
</main>
|
||||
|
||||
<footer class="container-fluid py-5 bg-white shadow-lg text-center">
|
||||
<footer class="container-fluid py-5 bg-light shadow-lg text-center">
|
||||
<div class="row">
|
||||
<div class="col-6 col-md">
|
||||
<ul class="list-unstyled">
|
||||
@ -115,7 +123,7 @@
|
||||
</div>
|
||||
<div class="col-6 col-md">
|
||||
<ul class="list-unstyled">
|
||||
<li><a href="#">API</a></li>
|
||||
<li><a href="{{ url('api') }}">API</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-6 col-md">
|
||||
|
@ -6,6 +6,15 @@
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Submit Meme') }}</div>
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger mt-3 mb-0">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('meme-create') }}" enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
@ -16,6 +16,9 @@
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title">{{ $data['meme']->title }}</h5>
|
||||
@if ($data['meme']->caption)
|
||||
<p class="card-text mb-1">{{ $data['meme']->caption }}</p>
|
||||
@endif
|
||||
<p class="card-text">By: <a href="{{ url('/user/' . $data['meme']->user->id) }}">{{ $data['meme']->user->name }}</a></p>
|
||||
</div>
|
||||
@if ($data['meme']->image)
|
||||
@ -30,7 +33,7 @@
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<h5 class="card-title">{{ $data['meme']->meme_tips_total }} XMR Recieved</h5>
|
||||
<p class="card-text">Published {{ $data['meme']->created_at }}</p>
|
||||
<p class="card-text">Published {{ $data['meme']->created_at->diffForHumans() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -38,31 +41,62 @@
|
||||
<div class="row text-center justify-content-center">
|
||||
<div class="col-md-12">
|
||||
<h3 class="mt-4 mb-0">Tip The Creator</h3>
|
||||
<img src="{{ $data['qr'] }}" alt="QR code">
|
||||
<p class="">{{ $data['meme']->address->address }}</p>
|
||||
<img class="img-qr" src="{{ $data['qr'] }}" alt="QR code">
|
||||
<p class="text-break">{{ $data['meme']->address->address }}</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h3 class="mt-4">Monero Tips Recieved</h3>
|
||||
<div class="col-12 col-lg-6">
|
||||
<h4 class="mt-4">Monero Tips Recieved</h4>
|
||||
<div class="table-responsive-md text-left mt-4">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Amount</th>
|
||||
<th scope="col">Date Recieved</th>
|
||||
<th scope="col">Transaction ID</th>
|
||||
<th scope="col">Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($data['meme']['tips'] as $tip)
|
||||
@if ($tip->is_deposit === 1)
|
||||
<tr>
|
||||
<td>{{ $tip->amount_formatted }}</td>
|
||||
<td>{{ $tip->created_at->diffForHumans() }}</td>
|
||||
<td class="text-truncate">
|
||||
<a href="https://testnet.xmrchain.net/tx/{{ $tip->txid }}" target="_blank">
|
||||
{{ $tip->txid }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6">
|
||||
<h4 class="mt-4">Monero Tips Sent</h4>
|
||||
<div class="table-responsive-md text-left mt-4">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>{{ $tip->amount_formatted }}</td>
|
||||
<td class="d-inline-block text-truncate" style="max-width: 150px;">
|
||||
<a href="https://testnet.xmrchain.net/tx/{{ $tip->txid }}" target="_blank">
|
||||
{{ $tip->txid }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ $tip->created_at }}</td>
|
||||
<th scope="col">Amount</th>
|
||||
<th scope="col">Date Sent</th>
|
||||
<th scope="col">Transaction ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($data['meme']['tips'] as $tip)
|
||||
@if ($tip->is_deposit === 0)
|
||||
<tr>
|
||||
<td>{{ $tip->amount_formatted }}</td>
|
||||
<td>{{ $tip->created_at->diffForHumans() }}</td>
|
||||
<td class="text-truncate">
|
||||
<a href="https://testnet.xmrchain.net/tx/{{ $tip->txid }}" target="_blank">
|
||||
{{ $tip->txid }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<p class="text-center">Total Earnings: {{ $data['user']->tips_total }}</h3>
|
||||
<p class="text-center">Total Memes: {{ $data['user']->memes_total }}</h3>
|
||||
<div class="row row-cols-1 row-cols-md-4 grid-memes">
|
||||
@foreach ($data['user']->memes as $meme)
|
||||
@foreach ($data['memes'] as $meme)
|
||||
<div class="col mb-4">
|
||||
<div class="card">
|
||||
<a href="{{ url('/meme/' . $meme->id) }}">
|
||||
@ -23,7 +23,7 @@
|
||||
<h5 class="card-title">{{ $meme->title }}</h5>
|
||||
</a>
|
||||
<p class="card-text">{{ $meme->meme_tips_total }} XMR Recieved</p>
|
||||
<p class="card-text">{{ $meme->created_at }}</p>
|
||||
<p class="card-text">{{ $meme->created_at->diffForHumans() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -31,5 +31,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center w-100">
|
||||
{{ $data['memes']->links() }}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
@ -17,3 +17,5 @@ use Illuminate\Support\Facades\Route;
|
||||
Route::middleware('auth:api')->get('/user', function (Request $request) {
|
||||
return $request->user();
|
||||
});
|
||||
|
||||
Route::middleware('api')->get('memes', [App\Http\Controllers\ApiController::class, 'memes']);
|
||||
|
@ -15,16 +15,15 @@ use Illuminate\Support\Facades\Route;
|
||||
|
||||
|
||||
Auth::routes();
|
||||
|
||||
Route::get('/', [App\Http\Controllers\MemeController::class, 'index'])->name('homepage');
|
||||
Route::get('meme/{id}', [App\Http\Controllers\MemeController::class, 'show'])->name('meme');
|
||||
Route::get('user/{id}', [App\Http\Controllers\UserController::class, 'show'])->name('user');
|
||||
Route::get('/leaderboard', [App\Http\Controllers\MemeController::class, 'leaderboard'])->name('leaderboard');
|
||||
Route::get('/about', [App\Http\Controllers\AboutController::class, 'index'])->name('about');
|
||||
Route::get('/dashboard', [App\Http\Controllers\DashboardController::class, 'index'])->name('dashboard');
|
||||
Route::get('meme/{id}', [App\Http\Controllers\MemeController::class, 'show'])->name('meme');
|
||||
Route::get('meme/approve/{id}', [App\Http\Controllers\MemeController::class, 'approve']);
|
||||
Route::get('meme/destroy/{id}', [App\Http\Controllers\MemeController::class, 'destroy']);
|
||||
Route::get('/submit/meme', [App\Http\Controllers\MemeController::class, 'create'])->name('meme')->middleware('auth');
|
||||
Route::post('/meme-create', [App\Http\Controllers\MemeController::class, 'store'])->name('meme-create');
|
||||
|
||||
// API
|
||||
Route::get('tips/check', [App\Http\Controllers\TipController::class, 'check']);
|
||||
Route::get('tips/payout', [App\Http\Controllers\TipController::class, 'payout']);
|
||||
Route::post('/meme-create', [App\Http\Controllers\MemeController::class, 'store'])->name('meme-create')->middleware('auth');
|
||||
Route::get('user/{id}', [App\Http\Controllers\UserController::class, 'show'])->name('user');
|
||||
Route::get('/dashboard', [App\Http\Controllers\DashboardController::class, 'index'])->name('dashboard');
|
||||
Route::get('/leaderboard', [App\Http\Controllers\MemeController::class, 'leaderboard'])->name('leaderboard');
|
||||
Route::get('/api', [App\Http\Controllers\ApiController::class, 'documentation'])->name('api');
|
||||
Route::get('/theme/{style}', [App\Http\Controllers\ThemeSwitcherController::class, 'theme']);
|
||||
|
4
webpack.mix.js
vendored
4
webpack.mix.js
vendored
@ -12,5 +12,5 @@ const mix = require('laravel-mix');
|
||||
*/
|
||||
|
||||
mix.js('resources/js/app.js', 'public/js')
|
||||
.sass('resources/sass/app.scss', 'public/css')
|
||||
.sourceMaps();
|
||||
.sass('resources/sass/app_light.scss', 'public/css').extract().version()
|
||||
.sass('resources/sass/app_dark.scss', 'public/css').extract().version();
|
||||
|
Loading…
Reference in New Issue
Block a user