<file_sep>using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using TreasureFinder.Models;
using System;



namespace TreasureFinder.Controllers
{

  [ApiController]
  [Route("api/[controller]/{itemId}")]
  public class ImagesController : ControllerBase
  {
    private readonly TreasureFinderContext _db;

    public ImagesController(TreasureFinderContext db)
    {
      _db = db;
    }
    [HttpPost]
    public IActionResult Post(Image image)
    {
      Console.WriteLine($"image {image}");
      _db.Images.Add(image);
      _db.SaveChanges();

      return Ok();
    }
  }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.IO;
using Microsoft.AspNetCore.Http;
using TreasureFinder.Models;


namespace TreasureFinder.Controllers
{

  [ApiController]
  [Route("api/[controller]")]
  public class ItemsController : ControllerBase
  {
    private readonly TreasureFinderContext _db;

    public ItemsController(TreasureFinderContext db)
    {
      _db = db;
    }

    private bool ItemExists(int id) => _db.Items.Any(item => item.ItemId == id);

    [HttpGet]
    public async Task<ActionResult<IEnumerable<Item>>> Get(string title, string description, string address, string startdate, string enddate, string condition, bool images)
    {
      // url?startdate=2021/12/05&enddate=2021/06/06
      var query = _db.Items.AsQueryable();
      if (title != null) query = query.Where(i => i.Title.Contains(title.Trim()));
      if (description != null) query = query.Where(i => i.Description.Contains(description.Trim()));
      if (address != null) query = query.Where(i => i.Address.Contains(address.Trim()));

      if (startdate != null && enddate != null)
      {
        var startDate = DateTime.Parse(startdate);
        var endDate = DateTime.Parse(enddate);
        query = query.Where(i => i.CreatedAt >= startDate && i.CreatedAt <= endDate);
      }
      else if (startdate != null && enddate == null)
      {
        var startDate = DateTime.Parse(startdate);
        query = query.Where(i => i.CreatedAt >= startDate);
      }
      else if (startdate == null && enddate != null)
      {
        var endDate = DateTime.Parse(enddate);
        query = query.Where(i => i.CreatedAt <= endDate);
      }
      else
      {
        Console.WriteLine("both start date and end date are null");
      }

      if (condition != null) query = query.Where(i => i.Condition.Trim() == condition.Trim());

      if (images == true) query = query.Where(i => i.Images.Count > 0);
      query.Include(entity => entity.Images);
      return await query.ToListAsync();
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<Item>> GetItem(int id)
    {
      var item = await _db.Items.Include(i => i.Images)
      .FirstOrDefaultAsync(i => i.ItemId == id);
      if (item == null)
      {
        return NotFound();
      }
      return item;
    }

    [HttpPost]
    public async Task<ActionResult<Item>> Post(Item item)
    {
      item.CreatedAt = DateTime.Now;
      _db.Items.Add(item);
      await _db.SaveChangesAsync();
      return CreatedAtAction(nameof(GetItem), new { id = item.ItemId }, item);
    }

    [HttpPut("{id}")]
    public async Task<ActionResult<Item>> Put(int id, Item item)
    {
      if (id != item.ItemId) return BadRequest();

      _db.Entry(item).State = EntityState.Modified;

      try
      {
        await _db.SaveChangesAsync();
      }
      catch (DbUpdateConcurrencyException)
      {
        if (!ItemExists(id)) return NotFound();
        else throw;
      }
      return item;
    }

    [HttpDelete("{id}")]
    public async Task<ActionResult> DeleteItem(int id)
    {
      Item item = await _db.Items.FindAsync(id);
      if (item == null) return NotFound();

      _db.Items.Remove(item);
      await _db.SaveChangesAsync();

      return NoContent();
    }
  }
}
<file_sep>using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System;

namespace TreasureFinder.Models
{
  public class TreasureFinderContext : DbContext
  {
    public TreasureFinderContext(DbContextOptions<TreasureFinderContext> options) : base(options)
    {
    }
    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        
    }
    protected override void OnModelCreating(ModelBuilder builder)
    {
      builder.Entity<Item>()
      .HasMany(i => i.Images);

      builder.Entity<Item>(i =>
      {
        i.HasData(
          new
          {
            ItemId = 1,
            Title = "Free Couch",
            Description = "Free floral sectional",
            Condition = "Like New",
            Address = "123 Main Street",
            CreatedAt = DateTime.Now,
            Url = "http://www.google.com",
            Dimensions = "40X115X80",
            Weight = "50",
            UserId = 1
          });
      });

    }
    public DbSet<Image> Images { get; set; }
    public DbSet<Item> Items { get; set; }
  
  }
}<file_sep><br>
<p align="center">
  <big>||  &nbsp;&nbsp;&nbsp;<u><b>Treasure Finder API</b></u>&nbsp;&nbsp;&nbsp;  ||</big>
</p>
<p align="center">Changing the world one line of code at a time.<br></p>
<p align="center">
  <small>June 17th, 2021.</small><br>
    <p align="center">
        <a href="https://github.com/Magofna68/MessageBoard.Solution/stargazers">
            <img src="https://img.shields.io/github/license/Magofna68/PierresTreats.Solution?style=plastic">
        </a>
        ¨
        <a href="https://github.com/Magofna68/MessageBoard.Solution/issues">
            <img src="https://img.shields.io/github/last-commit/Magofna68/MessageBoard.Solution?style=plastic">
        </a>
        ¨
        <a href="https://linkedin.com/in/Magofna68">
            <img src="https://img.shields.io/badge/-LinkedIn-black.svg?style=plastic&logo=linkedin&colorB=2867B2">
        </a>
    </p>
<p align="center">Contributors:<br><small><NAME>, <NAME>, <NAME>, & <NAME></small></p>
<p align="center">
    <!-- Project Avatar/Logo -->
    <p align="center">
    </p>
    <p align="center">
      __________________________________________________
    </p>
    <br>
    <p align="center"><a href="https://github.com/Magofna68">
        <img src="https://avatars.githubusercontent.com/u/80496559?v=4">
    </a></p>
    <br>
    <!-- GitHub Link -->
    <!-- Project Shields -->
</p>

------------------------------

# 🌐 About the Project
## This is one of two componenets we created for our wk 14 Team Week project at Epicodus (wk 14). This is the API side; hosting the client data for consumption.
<br>
This project will provide the client the ability to create posts to get rid of free items or "freecycle".
With full CRUD functionality to post, this API as a stretch goal will be able to host user uploaded photos of the items posted. 
<br>
<br>

### 🛠 Built With
* [Visual Studio Code](https://code.visualstudio.com/)
* [C#](https://docs.microsoft.com/en-us/dotnet/csharp/)
* [ASP.NET Core MVC](https://docs.microsoft.com/en-us/aspnet/core/mvc/overview?view=aspnetcore-3.1)
* [Swagger: SquashBuckle v5.6.3](https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-nswag?view=aspnetcore-3.1&tabs=visual-studio)
* [Postman](postman.com)

------------------------------

## Installation Requirements:

### 1) Install .NET Core
* On macOS:
  * [Click here](https://dotnet.microsoft.com/download/thank-you/dotnet-sdk-2.2.106-macos-x64-installer)
* On Windows 10:
  * [Click here](https://dotnet.microsoft.com/download/thank-you/dotnet-sdk-2.2.203-windows-x64-installer)

### 2) Install dotnet script
 * Enter the command ``dotnet tool install -g dotnet-script`` in Terminal.

### 4) Install Postman
* [Download and install Postman](https://www.postman.com/downloads/).

### 5) VS Code

  * i) Code Editor:
     * [Download Here](https://www.npmjs.com/)
  * ii) Download and install into applications folder

______________________________________________________________________________________
<br>

## Setup:

  #### i) Cloning

  1) Navigate to project directory
  2) Click the green 'Clone or download' button to copy URL.
  3) Navigate to local repository to host the file.
  4) Use the following command to clone the repository to your local device: 
  * $ git clone '___*Copied URL*___'
  5) Run the following command to enter project: 
  - $ cd '___*Copied URL*___'

  #### ii) AppSettings

  1) Create a new file in the project directory named `appsettings.json`
  2) Add in the following code snippet to the new appsettings.json file and update fields in brackets:
  
  ```
    "AllowedHosts": "*",
    "ConnectionStrings": {
        "DefaultConnection": "Server=localhost;Port=[Misc_Number];database=[project_api];uid=root;pwd=[<PASSWORD>];"
    }
  ```

  #### Launch the API
  1) Navigate to project directory
  2) Run the command `dotnet run` to have access to the API in Postman or browser.

------------------------------

## 🛰️ API Documentation
Explore the API endpoints in Postman or a browser. You will not be able to utilize authentication in a browser.

### Using Swagger Documentation 
#### i) To launch the project API with Swashbuckle, run the following command in the Terminal:
`dotnet run`
 #### ii) Click on / hard code the following URL into your browser: `http://localhost:5000/swagger`
________________________________________________
________________________________________________

### Endpoints
Base URL: `https://localhost:5000`

#### HTTP Request Structure
```
GET /api/{project}
POST /api/{project}
GET /api/{project}/{id}
PUT /api/{project}/{id}
DELETE /api/{project}/{id}
```

#### Example Query w/ swagger:
```
https://localhost:5000/swagger/index.html
```

#### Sample JSON Response
```
{
    "Id": 14,
    "Name": "<NAME>",
    "Street Address": "1111 Epicodus ln NE",
    "City": "Portland",
    "State": "Oregon"
    "Age: "34",
}
```

..........................................................................................

<file_sep>﻿using System;
using Microsoft.EntityFrameworkCore.Migrations;

namespace Treasure.Solution.Migrations
{
    public partial class RemoveItemFromImage : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.UpdateData(
                table: "Items",
                keyColumn: "ItemId",
                keyValue: 1,
                column: "CreatedAt",
                value: new DateTime(2021, 6, 15, 12, 42, 37, 41, DateTimeKind.Local).AddTicks(3290));
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.UpdateData(
                table: "Items",
                keyColumn: "ItemId",
                keyValue: 1,
                column: "CreatedAt",
                value: new DateTime(2021, 6, 15, 10, 8, 2, 442, DateTimeKind.Local).AddTicks(9960));
        }
    }
}
<file_sep>﻿using System;
using Microsoft.EntityFrameworkCore.Migrations;

namespace Treasure.Solution.Migrations
{
    public partial class seeddata : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.InsertData(
                table: "Items",
                columns: new[] { "ItemId", "Adress", "Condition", "CreatedAt", "Description", "Dimensions", "Title", "Url", "UserId", "Weight" },
                values: new object[] { 1, null, "Like New", new DateTime(2021, 6, 14, 14, 29, 10, 871, DateTimeKind.Local).AddTicks(1740), "Free floral sectional", "40X115X80", "Free Couch", "http://www.google.com", 1, "50" });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DeleteData(
                table: "Items",
                keyColumn: "ItemId",
                keyValue: 1);
        }
    }
}
<file_sep>﻿using System;
using Microsoft.EntityFrameworkCore.Migrations;

namespace Treasure.Solution.Migrations
{
    public partial class AddressFieldFix : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.RenameColumn(
                name: "Adress",
                table: "Items",
                newName: "Address");

            migrationBuilder.UpdateData(
                table: "Items",
                keyColumn: "ItemId",
                keyValue: 1,
                columns: new[] { "Address", "CreatedAt" },
                values: new object[] { "123 Main Street", new DateTime(2021, 6, 15, 10, 8, 2, 442, DateTimeKind.Local).AddTicks(9960) });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.RenameColumn(
                name: "Address",
                table: "Items",
                newName: "Adress");

            migrationBuilder.UpdateData(
                table: "Items",
                keyColumn: "ItemId",
                keyValue: 1,
                columns: new[] { "Adress", "CreatedAt" },
                values: new object[] { null, new DateTime(2021, 6, 14, 14, 29, 10, 871, DateTimeKind.Local).AddTicks(1740) });
        }
    }
}
<file_sep>using System.ComponentModel.DataAnnotations.Schema;
namespace TreasureFinder.Models
{
  public class Image
  {
    public int ImageId { get; set; }
    public string ImageString { get; set; }
    [ForeignKey("Item")]
    public int ItemId { get; set; }
    //public virtual  Item Item { get; set; }
  }
}<file_sep>using System;
using System.Collections.Generic;

namespace TreasureFinder.Models
{
  public class Item
  {

    public Item()
    {
      Images = new HashSet<Image>();
    }

    public int ItemId { get; set; }

    public string Title { get; set; }

    public string Description { get; set; }

    public string Address { get; set; }

    public string Condition { get; set; }

    public DateTime CreatedAt { get; set; }

    public string Url { get; set; }

    public string Dimensions { get; set; }

    public string Weight { get; set; }

    public ICollection<Image> Images { get; set; }

    public int UserId { get; set; }
  }
}<file_sep>﻿using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;

namespace Treasure.Solution.Migrations
{
    public partial class initial : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Items",
                columns: table => new
                {
                    ItemId = table.Column<int>(type: "int", nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    Title = table.Column<string>(type: "longtext CHARACTER SET utf8mb4", nullable: true),
                    Description = table.Column<string>(type: "longtext CHARACTER SET utf8mb4", nullable: true),
                    Adress = table.Column<string>(type: "longtext CHARACTER SET utf8mb4", nullable: true),
                    Condition = table.Column<string>(type: "longtext CHARACTER SET utf8mb4", nullable: true),
                    CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
                    Url = table.Column<string>(type: "longtext CHARACTER SET utf8mb4", nullable: true),
                    Dimensions = table.Column<string>(type: "longtext CHARACTER SET utf8mb4", nullable: true),
                    Weight = table.Column<string>(type: "longtext CHARACTER SET utf8mb4", nullable: true),
                    UserId = table.Column<int>(type: "int", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Items", x => x.ItemId);
                });

            migrationBuilder.CreateTable(
                name: "Images",
                columns: table => new
                {
                    ImageId = table.Column<int>(type: "int", nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    ImageString = table.Column<string>(type: "longtext CHARACTER SET utf8mb4", nullable: true),
                    ItemId = table.Column<int>(type: "int", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Images", x => x.ImageId);
                    table.ForeignKey(
                        name: "FK_Images_Items_ItemId",
                        column: x => x.ItemId,
                        principalTable: "Items",
                        principalColumn: "ItemId",
                        onDelete: ReferentialAction.Cascade);
                });

            migrationBuilder.CreateIndex(
                name: "IX_Images_ItemId",
                table: "Images",
                column: "ItemId");
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Images");

            migrationBuilder.DropTable(
                name: "Items");
        }
    }
}
