Skip to content

Commit

Permalink
Add optional notes to transactions #feature (#7)
Browse files Browse the repository at this point in the history
* ✨ Add note column to transactinos with tests

* ✨ Add note to transactions
  • Loading branch information
saleem-hadad authored Apr 4, 2022
1 parent dc4d1ae commit 2d9d53c
Show file tree
Hide file tree
Showing 15 changed files with 109 additions and 21 deletions.
1 change: 1 addition & 0 deletions database/factories/TransactionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function definition()
return [
'amount' => $this->faker->numberBetween(),
'brand_id' => Brand::factory(),
'note' => $this->faker->text()
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

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

class AddNoteToTransactionsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('transactions', function (Blueprint $table) {
$table->text('note')->nullable();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('transactions', function (Blueprint $table) {
$table->dropColumn('note');
});
}
}
5 changes: 3 additions & 2 deletions graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Transaction {
amount: Float!
brand: Brand! @belongsTo
created_at: Date!
note: String
}

type Sms {
Expand Down Expand Up @@ -58,8 +59,8 @@ type Query {
}

type Mutation {
createTransaction(amount: Float! brand_id: Int! created_at: String!): Transaction @create
updateTransaction(id: ID! amount: Float! brand_id: Int! created_at: String!): Transaction @update
createTransaction(amount: Float! brand_id: Int! created_at: String! note: String): Transaction @create
updateTransaction(id: ID! amount: Float! brand_id: Int! created_at: String! note: String): Transaction @update
deleteTransaction(id: ID!): Transaction @delete

createBrand(name: String! category_id: Int!): Brand @create
Expand Down
2 changes: 1 addition & 1 deletion public/css/app.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/js/app.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions public/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"/js/app.js": "/js/app.js?id=e1e1cedaae086936dc8b",
"/css/app.css": "/css/app.css?id=f7bc88db7b9dceab7c0d"
"/js/app.js": "/js/app.js?id=d80c6aa68ccfd74342c8",
"/css/app.css": "/css/app.css?id=9980ba94755724b3d676"
}
11 changes: 7 additions & 4 deletions resources/js/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default class Api {
id
amount
created_at
note
brand {
id
name
Expand All @@ -22,12 +23,13 @@ export default class Api {
}`});
}

createTransaction({amount, brandId, createdAt}) {
createTransaction({amount, brandId, createdAt, note}) {
return axios.post('/graphql', {query: `mutation {
createTransaction(amount: ${amount} brand_id: ${brandId} created_at: """${createdAt}""") {
createTransaction(amount: ${amount} brand_id: ${brandId} created_at: """${createdAt}""" note: """${note}""") {
id
amount
created_at
note
brand {
id
name
Expand All @@ -40,12 +42,13 @@ export default class Api {
}`});
}

updateTransaction({id, amount, brand, createdAt}) {
updateTransaction({id, amount, brand, createdAt, note}) {
return axios.post('/graphql', {query: `mutation {
updateTransaction(id: ${id} amount: ${amount} brand_id: ${brand} created_at: """${createdAt}""") {
updateTransaction(id: ${id} amount: ${amount} brand_id: ${brand} created_at: """${createdAt}""" note: """${note}""") {
id
amount
created_at
note
brand {
id
name
Expand Down
14 changes: 14 additions & 0 deletions resources/js/Pages/Transaction/Create.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default function Create({brands, showCreate, onClose, onCreate}) {
const [amount, setAmount] = useState(0);
const [brandId, setBrandId] = useState(0);
const [createdAt, setCreatedAt] = useState('');
const [note, setNote] = useState('');
const [isReady, setIsReady] = useState(false);
const [loading, setLoading] = useState(false);

Expand All @@ -22,6 +23,7 @@ export default function Create({brands, showCreate, onClose, onCreate}) {
amount,
brandId,
createdAt,
note
})
.then(({data}) => {
onCreate(data.data.createTransaction)
Expand Down Expand Up @@ -80,6 +82,18 @@ export default function Create({brands, showCreate, onClose, onCreate}) {
</select>
</div>

<div className="mt-4">
<Label forInput="note" value="Note (optional)" />

<Input
type="text"
name="note"
value={note}
className="mt-1 block w-full"
handleChange={(e) => setNote(e.target.value)}
/>
</div>

<div className="flex items-center justify-end mt-4">
<button onClick={create} className={`inline-flex items-center px-4 py-2 bg-blue-500 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest active:bg-blue-500 transition ease-in-out duration-150 ${isReady ? '' : 'disabled opacity-25'}`}>
{loading && <svg xmlns="http://www.w3.org/2000/svg" className="mr-2 animate-spin h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
Expand Down
17 changes: 16 additions & 1 deletion resources/js/Pages/Transaction/Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@ export default function Edit({brands, transaction, onClose, onUpdate}) {
const [amount, setAmount] = useState(0)
const [createdAt, setCreatedAt] = useState('')
const [brand, setBrand] = useState(0)
const [note, setNote] = useState('')

useEffect(() => {
if(! transaction) return;

setAmount(transaction.amount)
setBrand(transaction.brand.id)
setCreatedAt(transaction.created_at)
setNote(transaction.note)
}, [transaction])

const update = () => {
Api.updateTransaction({
id: transaction.id,
amount,
brand,
createdAt
createdAt,
note
})
.then(({data}) => {
onUpdate(data.data.updateTransaction)
Expand Down Expand Up @@ -78,6 +81,18 @@ export default function Edit({brands, transaction, onClose, onUpdate}) {
</select>
</div>

<div className="mt-4">
<Label forInput="note" value="Note (optional)" />

<Input
type="text"
name="note"
value={note}
className="mt-1 block w-full"
handleChange={(e) => setNote(e.target.value)}
/>
</div>

<div className="flex items-center justify-end mt-4">
<button onClick={update} className="inline-flex items-center px-4 py-2 bg-blue-500 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest active:bg-blue-500 transition ease-in-out duration-150">
Update
Expand Down
18 changes: 15 additions & 3 deletions resources/js/Pages/Transaction/Index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { PencilAltIcon, TrashIcon } from '@heroicons/react/outline';
import { PencilAltIcon, TrashIcon, InformationCircleIcon } from '@heroicons/react/outline';
import { Head } from '@inertiajs/inertia-react';
import Authenticated from '@/Layouts/Authenticated';
import Edit from '@/Pages/Transaction/Edit';
Expand Down Expand Up @@ -133,13 +133,25 @@ export default function Index({auth}) {
{transactions.map((item) => (
<tr key={item.id} className='loaded' id={'item-' + item.id}>
<td className="px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800">{item.id}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800">{AppCurrency} {Engine.formatNumber(item.amount, null)}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800">{AppCurrency} {Engine.formatNumber(item.amount, null)} </td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800">{item.brand.category ? item.brand.category.name : '-'}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800">{item.brand.name}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800">{item.brand.category ? item.brand.category.type : '-'}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-bold text-gray-800">{item.created_at}</td>
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button onClick={() => setEditItem(item)} type="button">
{item.note &&
<button>
<div class="relative flex flex-col items-center group">
<InformationCircleIcon className="h-5 w-5 text-gray-500" aria-hidden="true" />
<div class="absolute bottom-0 flex flex-col items-center hidden mb-6 group-hover:flex">
<span class="relative z-10 p-2 text-xs leading-none text-white whitespace-no-wrap bg-gray-800 rounded shadow-lg">{item.note}</span>
<div class="w-3 h-3 -mt-2 rotate-45 bg-gray-700"></div>
</div>
</div>
</button>
}

<button onClick={() => setEditItem(item)} type="button" className="ml-2">
<span className="sr-only">Edit</span>
<PencilAltIcon className="h-5 w-5 text-gray-500" aria-hidden="true" />
</button>
Expand Down
4 changes: 3 additions & 1 deletion tests/Feature/CreateTransactionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ public function it_create_a_model()

$this->graphQL(/** @lang GraphQL */ '
mutation {
createTransaction(amount: 100 brand_id: 1 created_at: """2022-05-01""") {
createTransaction(amount: 100 brand_id: 1 created_at: """2022-05-01""" note: """someNote""") {
id
amount
created_at
note
brand {
id
name
Expand All @@ -38,6 +39,7 @@ public function it_create_a_model()
"id" => 1,
"amount" => 100,
"created_at" => "2022-05-01",
"note" => "someNote",
"brand" => [
"id" => $brand->id,
"name" => $brand->name,
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/BrandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class BrandTest extends TestCase
/** @test */
public function it_has_name()
{
$sut = Brand::factory()->make(['name' => 'test']);
$sut = Brand::factory()->create(['name' => 'test']);

$this->assertEquals("test", $sut->name);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/CategoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ public function class_has_income_constant()
/** @test */
public function it_has_name()
{
$sut = Category::factory()->make(['name' => 'categoryTest']);
$sut = Category::factory()->create(['name' => 'categoryTest']);

$this->assertEquals("categoryTest", $sut->name);
}

/** @test */
public function it_has_type()
{
$sut = Category::factory()->make(['type' => Category::EXPENSES]);
$sut = Category::factory()->create(['type' => Category::EXPENSES]);

$this->assertEquals(Category::EXPENSES, $sut->type);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/SmsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ class SmsTest extends TestCase
/** @test */
public function it_has_body()
{
$sut = Sms::factory()->make(['name' => 'someName']);
$sut = Sms::factory()->create(['body' => 'someName']);

$this->assertEquals("someName", $sut->name);
$this->assertEquals("someName", $sut->body);
}

/** @test */
Expand Down
10 changes: 9 additions & 1 deletion tests/Unit/TransactionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,19 @@ class TransactionTest extends TestCase
/** @test */
public function it_has_amount()
{
$sut = Transaction::factory()->make(['amount' => 10]);
$sut = Transaction::factory()->create(['amount' => 10]);

$this->assertEquals(10, $sut->amount);
}

/** @test */
public function it_can_have_note()
{
$sut = Transaction::factory()->create(['note' => 'some note']);

$this->assertEquals('some note', $sut->note);
}

/** @test */
public function it_belongs_to_brand()
{
Expand Down

0 comments on commit 2d9d53c

Please sign in to comment.