Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Nathan-Roberts123 committed Apr 26, 2024
0 parents commit e040fa0
Show file tree
Hide file tree
Showing 34 changed files with 8,170 additions and 0 deletions.
21 changes: 21 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": ["eslint:recommended", "plugin:react/recommended"],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": ["react"],
"rules": { "react/react-in-jsx-scope": "off" }
}
44 changes: 44 additions & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Deploy Via SST

on:
push:
branches: [master]
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
env:
MONGODB_URI: ${{secrets.MONGODB_URI}}
USERNAME: Paul
WEBURL: https://d2pwr7td6bbxrr.cloudfront.net
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 18

- name: Cache Next.js Build
uses: actions/cache@v3
with:
path: |
.next/cache/
.open-next/
.sst/
key: cache-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]xs') }}
restore-keys: |
cache-${{ hashFiles('**/yarn.lock.') }}-
- run: npm install -g yarn
- run: yarn install --frozen-lockfile
- run: yarn build

- name: Install AWS Creds
run: |
mkdir -p ~/.aws
echo "[default]" > ~/.aws/credentials
echo "aws_access_key_id=${{ secrets.AWS_ACCESS_KEY_ID }}" >> ~/.aws/credentials
echo "aws_secret_access_key=${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> ~/.aws/credentials
- name: Deploy to AWS with SST
run: npx sst deploy --stage production
37 changes: 37 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
.env

# sst
.sst

# open-next
.open-next
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.next
coverage
18 changes: 18 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"arrowParens": "avoid",
"bracketSpacing": true,
"htmlWhitespaceSensitivity": "css",
"insertPragma": false,
"bracketSameLine": false,
"jsxSingleQuote": false,
"printWidth": 80,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"requirePragma": false,
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false,
"vueIndentScriptAndStyle": false
}
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Test a Next.js App with Cypress

## Video Lesson Outline:

[# 1 - Application Overview](https://youtu.be/xIl-0ZTtOHY)

[# 2 - Install Cypress and eslint-plugin-cypress](https://youtu.be/dkekN7rKF1Y)

[# 3 - Configure Cypress.json File](https://youtu.be/smd5UQUq5Uc)

[# 4 - Write Our First Test](https://youtu.be/TLjFmOpGjUU)

[# 5 - Write Better Tests with Cypress Testing Library](https://youtu.be/a1SvfURYxTQ)

[# 6 - Run Cypress in Multiple Browsers](https://youtu.be/z7s-acDceCs)

[# 7 - Test The Client Flow ](https://youtu.be/RupBr0w-bAk)

## Installing/Running the app

### Create a .env file

```
USERNAME="name you want displayed in project here"
MONGODB_URI="database creds here"
```

```bash
yarn
yarn dev
```

## Running Tests

```bash
yarn cy:open
```

### Formatting with Prettier

```bash
yarn format
```

## Technologies Used

[NextJS](https://nextjs.org/)

[Cypress-testing-library](https://testing-library.com/docs/cypress-testing-library/intro)

[Tailwindcss](https://tailwindcss.com/)

[React-notifications-component](https://teodosii.github.io/react-notifications-component/)

[React-icons](https://github.com/react-icons/react-icons#readme)

[Mongoose](https://mongoosejs.com/)

[MongoDB Atlas](https://www.mongodb.com/cloud/atlas/)

[Prettier](https://prettier.io/docs/en/install.html)
20 changes: 20 additions & 0 deletions components/CancelBtn.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Link from 'next/link'
import { MdCancel } from 'react-icons/md'

const CancelBtn = () => (
<button
type="button"
className="bg-gray-400 hover:bg-gray-600 text-black font-bold py-2 px-4 rounded"
>
<Link href="/">
<a>
Cancel
<span className="inline-block" style={{ height: '0.85em' }}>
<MdCancel />
</span>
</a>
</Link>
</button>
)

export default CancelBtn
44 changes: 44 additions & 0 deletions components/Client.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import PropTypes from 'prop-types'
import Link from 'next/link'
import { FaRegEdit } from 'react-icons/fa'

const Client = ({ id, name, email, phone, address, company, notes }) => {
return (
<>
<tr>
<td className="border px-4 py-2">{name}</td>
<td className="border px-4 py-2">{email}</td>
<td className="border px-4 py-2">{phone}</td>
<td className="border px-4 py-2">{address}</td>
<td className="border px-4 py-2">{company}</td>
<td className="border px-4 py-2">
{notes ? `${notes.slice(0, 15)}...` : ''}
</td>
<td className="border px-4 py-2">
<button
name={`edit ${name}`}
className="bg-orange-500 hover:bg-orange-700 text-white font-bold py-2 px-4 rounded"
>
<Link href="/edit/[id]" as={`/edit/${id}`}>
<a>
<FaRegEdit />
</a>
</Link>
</button>
</td>
</tr>
</>
)
}

Client.propTypes = {
id: PropTypes.string,
name: PropTypes.string,
email: PropTypes.string,
phone: PropTypes.number,
address: PropTypes.string,
company: PropTypes.string,
notes: PropTypes.string
}.isRequired

export default Client
25 changes: 25 additions & 0 deletions components/ClientList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import PropTypes from 'prop-types'
import Client from './Client'

const ClientList = ({ clients }) => {
if (clients) {
const list = clients.map(client => <Client key={client.id} {...client} />)
return <>{list}</>
}
}

ClientList.propTypes = {
clients: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string,
name: PropTypes.string,
email: PropTypes.string,
phone: PropTypes.number,
address: PropTypes.string,
company: PropTypes.string,
notes: PropTypes.string
})
)
}

export default ClientList
7 changes: 7 additions & 0 deletions components/Footer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const Footer = () => (
<footer className="bg-black text-white text-2xl p-3 text-center font-bold fixed left-0 bottom-0 w-full">
Client Address Book &#9400;{new Date().getFullYear()}
</footer>
)

export default Footer
37 changes: 37 additions & 0 deletions components/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Link from 'next/link'
import { useRouter } from 'next/router'
import { FaAddressCard } from 'react-icons/fa'

const Header = () => (
<header>
<ul className="bg-black text-white p-3 flex flex-row justify-between font-bold">
<li className="text-4xl">
<span
style={{ height: '1.9rem', marginRight: '0.5em' }}
className="inline-block"
>
<FaAddressCard />
</span>
{process.env.username}&apos;s Clients{' '}
</li>
<nav className="flex justify-between">
{useRouter().pathname !== '/' && (
<li className="self-center text-2xl hover:text-gray-500">
<Link href="/">
<a>Clients</a>
</Link>
</li>
)}
{useRouter().pathname !== '/add-client' && (
<li className="self-center text-2xl hover:text-gray-500 ml-5">
<Link href="/add-client">
<a>Add Client</a>
</Link>
</li>
)}
</nav>
</ul>
</header>
)

export default Header
17 changes: 17 additions & 0 deletions components/Layout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import PropTypes from 'prop-types'
import Header from './Header'
import Footer from './Footer'

const Layout = props => (
<>
<Header />
<div className="py-10">{props.children}</div>
<Footer />
</>
)

Layout.propTypes = {
children: PropTypes.node
}

export default Layout
3 changes: 3 additions & 0 deletions css/tailwind.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
16 changes: 16 additions & 0 deletions db/models/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Schema } from 'mongoose'
import uniqueValidator from 'mongoose-unique-validator'

const userSchema = new Schema({
name: { type: String, required: true, unique: true },
email: { type: String, required: true },
address: { type: String, required: false },
phone: { type: Number, required: false },
company: { type: String, required: false },
notes: { type: String, required: false }
})

// Ensures names are unique
userSchema.plugin(uniqueValidator, { message: '{PATH} is already in use' })

export default userSchema
17 changes: 17 additions & 0 deletions db/mongoose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import mongoose from 'mongoose'
import clientSchema from './models/client'

const dbConnect = async () => {
const connection = await mongoose.createConnection(process.env.mongodb, {
useNewUrlParser: true,
useUnifiedTopology: true
})

const Client = connection.model('Client', clientSchema)

return {
models: { Client }
}
}

export default dbConnect
8 changes: 8 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require('dotenv').config()

module.exports = {
env: {
username: process.env.USERNAME,
mongodb: process.env.MONGODB_URI
}
}
Loading

0 comments on commit e040fa0

Please sign in to comment.