Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add view completed exercises list #385

Merged
merged 13 commits into from Jul 7, 2020
10 changes: 9 additions & 1 deletion app/Http/Controllers/MyController.php
Expand Up @@ -4,7 +4,9 @@

use App\Chapter;
use App\User;
use App\Exercise;
use Auth;
use Illuminate\Pagination\LengthAwarePaginator;

class MyController extends Controller
{
Expand All @@ -19,12 +21,18 @@ public function __invoke()
$chapters = Chapter::with('children', 'exercises')->get();
$mainChapters = $chapters->where('parent_id', null);
$completedExercises = $user->completedExercises->keyBy('exercise_id');
$savedSolutionsExercises = $user->solutions()
->with('exercise')
->distinct('exercise_id')
->orderBy('exercise_id')
->paginate(10);

return view('my.index', compact(
'user',
'chapters',
'mainChapters',
'completedExercises'
'completedExercises',
'savedSolutionsExercises'
));
}
}
24 changes: 21 additions & 3 deletions app/Http/Controllers/SolutionController.php
Expand Up @@ -18,14 +18,15 @@ public function __construct()
public function store(Request $request, User $user)
{
$validatedData = $request->validate([
'exercise_id' => 'required|integer|min:1',
'content' => 'required|string|min:1'
]);

$solution = new Solution($validatedData);
$solution->user()->associate($user);
$exercise = Exercise::findOrFail($request->get('exercise_id'));

$solution = new Solution($validatedData);
$solution->user()->associate($user)->exercise()->associate($exercise);


if ($solution->save()) {
activity()
->performedOn($solution)
Expand All @@ -42,6 +43,23 @@ public function store(Request $request, User $user)
return back();
}

public function show(User $user, Solution $solution)
{

$currentExercise = $solution->exercise;

$solutionsListForCurrentExercise = $solution->exercise
->solutions()
->where('user_id', $user->id)
->get();

return view('solution.show', compact(
'currentExercise',
'solutionsListForCurrentExercise',
'user'
));
}

public function destroy(User $user, Solution $solution)
{
if ($solution->delete()) {
Expand Down
7 changes: 6 additions & 1 deletion app/Policies/SolutionPolicy.php
Expand Up @@ -10,12 +10,17 @@
class SolutionPolicy
{
use HandlesAuthorization;

public function create(User $user)
{
return Auth::check();
}

public function view(User $user, Solution $solution)
{
return $user->id == $solution->user_id;
}

public function delete(User $user, Solution $solution)
{
return $user->id == $solution->user_id;
Expand Down
1 change: 0 additions & 1 deletion app/Solution.php
Expand Up @@ -7,7 +7,6 @@
class Solution extends Model
{
protected $fillable = [
'exercise_id',
'content'
];

Expand Down
15 changes: 15 additions & 0 deletions resources/js/app.js
Expand Up @@ -14,3 +14,18 @@ hljs.registerLanguage('scheme', scheme);
$('#flash-overlay-modal').modal();
hljs.initHighlightingOnLoad();

// LINK TO TABS
$(document).ready(() => {
AlexeyShobanov marked this conversation as resolved.
Show resolved Hide resolved
var url = window.location.href;
if (url.indexOf("#") > 0) {
var activeTab = url.substring(url.indexOf("#") + 1);
$('.nav[role="tablist"] a[href="#' + activeTab + '"]').tab('show');
}

$('a[role="tab"]').on("click", function () {
var newUrl;
const hash = $(this).attr("href");
newUrl = url.split("#")[0] + hash;
history.replaceState(null, null, newUrl);
});
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Может этот код завернуть в функцию, Которую вызывать + убрать var и заменить на const? Просто и правда выглядит, что какой-то чувак по-быстрому накидал решение не разбираясь в тонкостях js

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, подумаю как это сделать

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Смотри, если с js не хочешь морочиться, то можно и не делать, потом поправим наверное.
Просто из-за var будет глобальная переменная. Ну и вообще тут код не очень написан, как мне кажется.

10 changes: 10 additions & 0 deletions resources/lang/en/progresses.php
@@ -0,0 +1,10 @@
<?php

return [
'сhapters' => 'Chapters',
'my_solutions' => 'My Solutions',
'exercise' => 'Exercise',
'see_details' => 'See details',
'solutions' => 'Solutions',
'exercises' => 'Exercises'
];
5 changes: 4 additions & 1 deletion resources/lang/en/solution.php
Expand Up @@ -6,5 +6,8 @@
'title_add_solution' => 'Solution',
'title_output_solution' => 'My solution',
'add_solution' => 'Add solution',
'show_solution' => 'My solutions'
'show_solution' => 'My solutions',
'exercise' => 'Exercise',
'code_review' => 'Code Review',
'sub_title' => 'Compare your versions'
];
10 changes: 10 additions & 0 deletions resources/lang/ru/progresses.php
@@ -0,0 +1,10 @@
<?php

return [
'сhapters' => 'Главы',
'my_solutions' => 'Мои Решения',
'exercise' => 'Упражнение',
'see_details' => 'Подробнее',
'solutions' => 'Решения',
'exercises' => 'Упражнения'
];
5 changes: 4 additions & 1 deletion resources/lang/ru/solution.php
Expand Up @@ -6,5 +6,8 @@
'title_add_solution' => 'Решение',
'title_output_solution' => 'Мое решение',
'add_solution' => 'Добавить решение',
'show_solution' => 'Мои решения'
'show_solution' => 'Мои решения',
'exercise' => 'Упражнение',
'code_review' => 'Код Ревью',
'sub_title' => 'Сравни свои решения'
];
2 changes: 2 additions & 0 deletions resources/sass/_variables.scss
@@ -1,5 +1,7 @@
// Body
$body-bg: #f8fafc;
//
$nav-tabs-link-active-bg: #fff;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а зачем цвет менять?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь пришлось прописывать цвет таба, так как был изменен цвет основного фона для этого проекта, а он тянет за собой изменение цвета таба (по умолчанию он был белым, как и нужно). Обсуждал это с Андреем, он подсказал, что это решается так

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Как это выглядит можно посмотреть здесь:
https://hexlet-sicp-test.herokuapp.com/


// Typography
$font-family-sans-serif: 'Nunito', sans-serif;
Expand Down
8 changes: 4 additions & 4 deletions resources/views/layouts/app.blade.php
Expand Up @@ -25,20 +25,20 @@
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>

<body class="d-flex flex-column">
<body class="d-flex flex-column min-vh-100">
@if (config('app.env') == 'production')
@include('layouts.deps._gtm_body')
@endif
<div class="d-flex flex-column min-vh-100">
<div class="flex-grow-1">
@include('layouts._nav')
<main class="my-5">
<main class="my-4">
<div class="container mb-3">
@include('flash::message')
@yield('content')
</div>
</main>
@include('layouts._footer')
</div>
@include('layouts._footer')

</body>

Expand Down
55 changes: 13 additions & 42 deletions resources/views/my/index.blade.php
@@ -1,49 +1,20 @@
@extends('layouts.app')

@section('content')
<div class="row">
<div class="col">
<h3>{{ __('layout.nav.my_progress') }}</h3>
</div>
<div class="col text-right">
<h5><a href="{{ route('users.show', $user) }}">{{ $user->name }}</a></h5>
<div class="d-flex flex-wrap justify-content-between">
<div class="h3">{{ __('layout.nav.my_progress') }}</h3></div>
<div class="h5 align-self-center">
<a href="{{ route('users.show', $user) }}">{{ $user->name }}</a>
</div>
</div>
<div class="row mt-2">
<div class="col-12 col-md-4 mb-2">
<div class="nav nav-pills flex-column sticky-top x-z-index-0" role="tablist">
@foreach($mainChapters as $mainChapter)
<a class="nav-item nav-link {{ $mainChapter->path === '1' ? 'active' : '' }}"
id="subChapters{{ $mainChapter->id }}-tab"
href="#subChapters{{ $mainChapter->id }}"
data-toggle="tab"
role="tab"
aria-controls="subChapters{{ $mainChapter->id }}"
aria-selected="{{ $mainChapter->path === '1' ? 'true' : 'false' }}">
{{ $mainChapter->path }} {{ getChapterName($mainChapter->path) }}
</a>
@endforeach
</div>
</div>
<div class="col-12 col-md-8">
<div class="card pl-2 pr-3">
{!! Form::open()->route('users.chapters.store', [$user]) !!}
<div class="tab-content">
@foreach($mainChapters as $mainChapter)
<div
class="tab-pane card-body {{ $mainChapter->path === '1' ? 'active' : '' }}"
id="subChapters{{ $mainChapter->id }}"
role="tabpanel"
aria-labelledby="subChapters{{ $mainChapter->id }}-tab">
@include('partials.chapter_form_element', ['chapter' => $mainChapter])
</div>
@endforeach
<div class="form-group text-right">
{!! Form::submit(__('layout.common.save')) !!}
</div>
</div>
{!! Form::close() !!}
</div>
</div>
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
AlexeyShobanov marked this conversation as resolved.
Show resolved Hide resolved
<a class="nav-item nav-link active" id="nav-chapters-tab" data-toggle="tab" href="#nav-chapters" role="tab" aria-controls="nav-home" aria-selected="true">{{ __('progresses.сhapters') }}</a>
<a class="nav-item nav-link" id="nav-solutions-tab" data-toggle="tab" href="#nav-solutions" role="tab" aria-controls="nav-profile" aria-selected="false">{{ __('progresses.my_solutions') }}</a>
</div>
</nav>
<div class="tab-content bg-white" id="nav-tabContent">
<div class="tab-pane fade show active" id="nav-chapters" role="tabpanel" aria-labelledby="nav-chapters-tab">@include('my.progresses._my_chapters')</div>
<div class="tab-pane fade show" id="nav-solutions" role="tabpanel" aria-labelledby="nav-solutions-tab">@include('my.progresses._my_solutions')</div>
AlexeyShobanov marked this conversation as resolved.
Show resolved Hide resolved
</div>
@endsection
35 changes: 35 additions & 0 deletions resources/views/my/progresses/_my_chapters.blade.php
@@ -0,0 +1,35 @@
<div class="row row-cols-1 row-cols-md-2 no-gutters border border-top-0">
<div class="col col-md-4 border-right x-z-index-0">
AlexeyShobanov marked this conversation as resolved.
Show resolved Hide resolved
<div class="nav nav-pills flex-column sticky-top m-2 pt-2" role="tablist">
@foreach($mainChapters as $mainChapter)
<a class="nav-item nav-link {{ $mainChapter->path === '1' ? 'active' : '' }}"
id="subChapters{{ $mainChapter->id }}-tab"
href="#subChapters{{ $mainChapter->id }}"
data-toggle="tab"
role="tab"
aria-controls="subChapters{{ $mainChapter->id }}"
aria-selected="{{ $mainChapter->path === '1' ? 'true' : 'false' }}">
{{ $mainChapter->path }} {{ getChapterName($mainChapter->path) }}
</a>
@endforeach
</div>
</div>
<div class="col col-md-8">
{!! Form::open()->route('users.chapters.store', [$user]) !!}
<div class="tab-content m-2 m-lg-4">
@foreach($mainChapters as $mainChapter)
<div
class="tab-pane {{ $mainChapter->path === '1' ? 'active' : '' }}"
id="subChapters{{ $mainChapter->id }}"
role="tabpanel"
aria-labelledby="subChapters{{ $mainChapter->id }}-tab">
@include('partials.chapter_form_element', ['chapter' => $mainChapter])
</div>
@endforeach
<div class="text-right mt-2 mt-lg-4">
{!! Form::submit(__('layout.common.save')) !!}
</div>
</div>
{!! Form::close() !!}
</div>
</div>
23 changes: 23 additions & 0 deletions resources/views/my/progresses/_my_solutions.blade.php
@@ -0,0 +1,23 @@

<div class="table-responsive border border-top-0 p-4">
AlexeyShobanov marked this conversation as resolved.
Show resolved Hide resolved
<table class="table">
<thead>
<tr>
<th class="border-top h5">{{ __('progresses.exercises') }}</th>
<th class="border-top h5">{{ __('progresses.solutions') }}</th>
</tr>
@foreach ($savedSolutionsExercises as $solution)
<tr>
<td>
{{ __('progresses.exercise') }} {{ $solution->exercise->path }} {{ getExerciseTitle($solution->exercise) }} (Chapter {{ $solution->exercise->chapter->path }})
</td>
<td>
<a href="{{ route('users.solutions.show', [$user, $solution]) }}">
{{ __('progresses.see_details') }}
</td>
</tr>
@endforeach
</thead>
</table>
</div>
{{ $savedSolutionsExercises->fragment('nav-solutions')->links() }}
80 changes: 80 additions & 0 deletions resources/views/solution/show.blade.php
@@ -0,0 +1,80 @@
@extends('layouts.app')

@section('content')

<div class="d-flex flex-wrap justify-content-between mb-2 mb-lg-4">
<div class="h5">
<a href="{{ route('exercises.show', $currentExercise) }}">
{{ __('solution.exercise') }} {{ $currentExercise->path }}: {{ getExerciseTitle($currentExercise) }}
</div>
<div class="h5">
<a href="{{ route('users.show', $user) }}">{{ $user->name }}</a>
</div>
</div>

<h2 class="text-center">{{ __('solution.code_review') }}</h2>
<div class="text-center h5">{{ __('solution.sub_title') }}</div>
<hr>
<div class="row no-gutters">
<div class="col-12 col-md p-2 p-lg-4">
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
@foreach ($solutionsListForCurrentExercise as $currentSolution)
@if ($loop->first)
<li class="nav-item" role="presentation">
<a class="nav-link active" id="pills-{{ $currentSolution->id }}-tab" data-toggle="pill" href="#pills-{{ $currentSolution->id }}" role="tab" aria-controls="pills-{{ $currentSolution->id }}" aria-selected="true">v.{{ $loop->iteration }}</a>
</li>
@else
<li class="nav-item" role="presentation">
<a class="nav-link" id="pills-{{ $currentSolution->id }}-tab" data-toggle="pill" href="#pills-{{ $currentSolution->id }}" role="tab" aria-controls="pills-{{ $currentSolution->id }}" aria-selected="true">v.{{ $loop->iteration }}</a>
</li>
@endif
@endforeach
</ul>
<div class="tab-content" id="pills-tabContent">
@foreach ($solutionsListForCurrentExercise as $currentSolution)
@if ($loop->first)
<div class="tab-pane fade show active" id="pills-{{ $currentSolution->id }}" role="tabpanel" aria-labelledby="pills-{{ $currentSolution->id }}-tab">
<pre><code>{{ $currentSolution->content }}</code></pre>
</div>
@else
<div class="tab-pane fade show" id="pills-{{ $currentSolution->id }}" role="tabpanel" aria-labelledby="pills-{{ $currentSolution->id }}-tab">
<pre><code>{{ $currentSolution->content }}</code></pre>
</div>
@endif
@endforeach
</div>
</div>

@if (count($solutionsListForCurrentExercise) > 1)
<div class="d-none d-md-block border-left"></div>
AlexeyShobanov marked this conversation as resolved.
Show resolved Hide resolved
<div class="col p-2 p-lg-4">
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
@foreach ($solutionsListForCurrentExercise as $currentSolution)
@if ($loop->first)
<li class="nav-item" role="presentation">
<a class="nav-link active" id="pills-{{ $currentSolution->id }}double-tab" data-toggle="pill" href="#pills-{{ $currentSolution->id }}double" role="tab" aria-controls="pills-{{ $currentSolution->id }}double" aria-selected="true">v.{{ $loop->iteration }}</a>
</li>
@else
<li class="nav-item" role="presentation">
<a class="nav-link" id="pills-{{ $currentSolution->id }}double-tab" data-toggle="pill" href="#pills-{{ $currentSolution->id }}double" role="tab" aria-controls="pills-{{ $currentSolution->id }}double" aria-selected="true">v.{{ $loop->iteration }}</a>
</li>
@endif
@endforeach
</ul>
<div class="tab-content" id="pills-tabContent">
@foreach ($solutionsListForCurrentExercise as $currentSolution)
@if ($loop->first)
<div class="tab-pane fade show active" id="pills-{{ $currentSolution->id }}double" role="tabpanel" aria-labelledby="pills-{{ $currentSolution->id }}double-tab">
<pre><code>{{ $currentSolution->content }}</code></pre>
</div>
@else
<div class="tab-pane fade show" id="pills-{{ $currentSolution->id }}double" role="tabpanel" aria-labelledby="pills-{{ $currentSolution->id }}double-tab">
<pre><code>{{ $currentSolution->content }}</code></pre>
</div>
@endif
@endforeach
</div>
</div>
@endif
</div>
@endsection