# Kudos



# Week 1 + 2

## Goals

- [ ] Learn about Kudos!
- [ ] Gain an understanding of some essential developer tools
- [ ] Install git, Node, and VSCode
-  [ ] Create and clone your own repository

---

## How will this work?

Weekly session where we will:
- Go over the session's goals
- Code together
- Get support if needed
- Recap

By the end, we will have a finshed project!

## Why Kudos?

At Blueprint, recognizing the contributions of our developer members is crucial for fostering a positive and productive project team environment. This tool is specifically designed to highlight the efforts of these members and gather valuable feedback. By acknowledging their hard work, especially amidst their academic and other commitments, we aim to improve their overall project team experience and prevent potential feelings of being overworked or burnt out.

## Setup

For any project, it is essential to have certain 'tools' installed...

These tools go by many names:
 - libraries
 - environments
 - packages
 - dependencies
 - etc.

But they all serve one broad purpose: help developers build.

So, before we begin building our project, lets first install all of the necessary tools we'll need along the way.

### Git and GitHub

A key foundation of software development is collaboration.

Across industry, developers collaborate using two essential tools: Git and GitHub

Later on, we will explore these two tools, but for now lets just install them.

#### Windows install

1. Go to the official Git website at https://git-scm.com/downloads
2. The download for Windows should begin automatically.
3. Once the installer finishes downloading, run the `.exe` file.
4. Follow the prompts in the installation wizard. 
5. After installation, open a new terminal and type `git --version` to verify the installation.

#### macOS install 

1. The easiest way to get Git on macOS is in the terminal.
2. Open your Terminal application.
3. Type `git --version` and press enter.
4. If Git is not installed, a pop-up will appear asking you to install the command line developer tools. Click "Install" and follow the on-screen instructions.

Now, lets create and authenticate a GitHub account. 

#### Creating Your GitHub Account

Creating a GitHub account is a simple process.

1.  Go to the GitHub Website: Open your web browser and navigate to [github.com](https://github.com).
2.  Sign Up: On the homepage, you'll see a sign-up form. Enter your **email address**, create a **password**, and choose a **username**.
3.  Verification: You'll likely need to solve a quick puzzle to verify you're human. After that, GitHub will send a verification code to the email address you provided. Go to your inbox, find the email, and enter the code on the GitHub site.

That's it! You now have a GitHub account.

#### Authenticating Your Account

Authentication proves your identity when you want to push (upload) or pull (download) code from your computer. Using your password for this is no longer supported for security reasons. Instead, you should use a **Personal Access Token (PAT)**.

A PAT is like a long, secure password that you use only for accessing GitHub from the command line or apps.

1.  Go to Your Settings:

      * Click on your profile picture in the top-right corner and select **Settings**.
      * In the left sidebar, scroll down and click on **Developer settings**.
      * Click on **Personal access tokens**, then select **Tokens (classic)**.

2.  Generate a New Token:

      * Click the **Generate new token** button.
      * Set an **Expiration** date. For better security, don't set it to "No expiration". 90 days is fine.
      * Under **Select scopes**, select the **`repo`** scope.

3.  Copy and Save Your Token:

      * Click the **Generate token** button at the bottom.
      * **This is the only time you will see the token\!!!** Copy it immediately and save it in a secure place, like a password manager. If you lose it, you'll have to generate a new one.

4.  **Using Your PAT**:

      * Now, when you perform a Git operation in your terminal (like `git push`) that requires authentication over HTTPS, you'll be prompted for your username and password.
      * Enter your GitHub **username**.
      * When asked for your password, **paste your Personal Access Token**.

You're all set! Your GitHub account is now created and authenticated for use on your computer. 

### Node

Like git, Node is a tool in the software development world that is a must-have.

Among many other things, it allows us to see the changes in our code live in our browser!

So as we add components of our app, we can ensure they look and function as we want them to.
#### Windows 

1. Go to the official Node.js website: https://nodejs.org/en/download
2. Download correct verion.
3. Run the installer and follow the on-screen instructions. 
4. Once the installation is complete, you can open the terminal and verify the installation by typing:
   
```
node -v
npm -v
```

These commands should return the version numbers for Node.js and npm, confirming a successful installation.

#### macOS

1. The easiest way is to download the official `.pkg` installer from the Node.js website: https://nodejs.org/en/download
2. Choose the LTS version and run the installer after it downloads.
3. Follow the installation steps. The installer will guide you through the process.
4. After installation, open a new Terminal window and run the same commands as above to verify: `node -v` and `npm -v`.

### Visual Studio Code

We will be writing all of our code using Visual Studio.

Visual Studio has a simple install. Simply use this link and follow the steps: https://code.visualstudio.com/download

### Troubleshooting

Before we move on, lets address some common issues that you may run into during setup. 

#### Checking Node Versions (Windows Users)

If you recieve an error when running the `node - v` and `npm -v` commands:
1. Search 'Terminal' in your taskbar start menu.
2. Hover over the Terminal Icon, then right-click. 
3. A menu should appear. Click on the option to 'Run as Administrator'. This should open a new terminal that indicates you are an Administrator in the title bar. 
4. Run this command: `Set-ExecutionPolicy RemoteSigned`.
5. Now, try running `node - v` and `npm -v` once again, and you should be able to see their versions, confirming your Node has installed correctly.

## Creating a Repository

You now know the basics of git and GitHub! 

The next step is to create your own repository where you'll store all of your code for the project.

On the main page of GitHub's site, you will see a green box in the top left corner that says 'New'.

[![Screenshot 2025-09-10 at 9.20.12 AM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-10-at-9-20-12-am.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-10-at-9-20-12-am.png)

Click it, and you will be redirected to a new page that looks like this:

[![Screenshot 2025-09-10 at 9.21.29 AM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-10-at-9-21-29-am.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-10-at-9-21-29-am.png)

On this page, you will enter the details of your repository. In our case, this includes a specific set of options that oyu should copy from the screenshot above. Your repository name should be `my-kudos`, visibility should be public, and add README option shoud be toggled on.

Click create, and you will again be redirected.

[![Screenshot 2025-09-10 at 9.21.47 AM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-10-at-9-21-47-am.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-10-at-9-21-47-am.png)

This is your repo! Now, all you have to do is follow some of the steps from the prior section.

The first is cloning your repo with `git clone`.

[![Screenshot 2025-09-10 at 9.24.04 AM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-10-at-9-24-04-am.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-10-at-9-24-04-am.png)

Like before, to check that the clone was successful, `cd` into your new directory.

[![Screenshot 2025-09-10 at 9.24.51 AM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-10-at-9-24-51-am.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-10-at-9-24-51-am.png)

Note: In this example, I also used the `ls` command, which lists the contents for your directory. Since we just created our repo and initialized it with a `README.md` file, the only thing in our project folder should be that file - and it is.

### Making a Change

As a way to test what we've done so far, lets try actually making changes to file and seeing them reflected in our repository. 

Our goal will be to edit a file in our project - then upload the changes to our GitHub repo using the commands we just learned.

#### Editing a file

In VSCode, open your `README.md` file. 

It should look something like this:

[![Screenshot 2025-09-16 at 9.17.38 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-16-at-9-17-38-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-16-at-9-17-38-pm.png)

Lets make a simple change: add a short sentence about yourself!

It should look like something like this:

[![Screenshot 2025-09-16 at 9.22.27 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-16-at-9-22-27-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-16-at-9-22-27-pm.png)

Note: Those green bars next to each of the lines we just wrote indicate that these are new (uncommitted) lines. This is good! It means that we now have code to upload (commit) to our repo!

#### Making a Commit

Once the change is made, use the `git add` command in order to include or 'stage' our changes for the next commit. Commits can be thought of as checkpoints; more on that later.  

In this case, we made changes to the `README.MD` , so our file path is `/README.MD` and we type in: 

```bash
git add /README.MD
```

Note: You can use `git add` to add as many files as you need, and another common option is to use `git add .` to add all files with changes. Also, The file path is case sensitive.

#### Checking Changes to be Committed

You can use the `git status` command to check what files have been added or "staged" for a commit to ensure you added the right things. In this case, it's only the one contributors file that we added.

[![Screenshot 2025-09-16 at 9.27.16 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-16-at-9-27-16-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-16-at-9-27-16-pm.png)

You can see here that our file is under changes to be committed and is in **green** text. Changes not staged for commit will be in **red** (if there are any).

#### Committing Changes

With our changes made and staged, we can create a **commit** which can be thought of as a  checkpoint for our code. We can revert to this point if we make mistakes or need to look at the version of the code at this point in time.

It is also good practice to include a commit message by using the `-m` flag to describe what changes were made. For us, we will just say that we are adding a new contributor, like so: 

```bash 
git commit -m "Added info about me!"
```

Commit Messages: When writing a commit, it is usually good practice to follow a convention. At Blueprint, we use the Conventional Commits specification: [www.conventionalcommits.org](https://www.conventionalcommits.org), but don't worry about that right now!

We can commit as often as we want, or when we feel it is necessary before making big changes.

[![Screenshot 2025-09-16 at 9.29.03 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-16-at-9-29-03-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-16-at-9-29-03-pm.png)

#### Pushing a Commit

In order for our changes to appear on the remote repository (the one on Github, which is online), we need to push our changes using the `git push` command. If we run it as is, however, we will encounter an error:
  
It is no big deal - the reason it happens is because when we create the branch contributors/johnDoe, we only created it locally and it does not exist on the Github repository. 

Therefore, we must run the command shown: 

```bash
git push --set-upstream origin contributors/<your name>
```

Once the branch is set up remotely, or if the branch already existed remotely and was not created locally, we can simply use `git push`.

#### Seeing our Changes

Finally, we can confirm that all of these steps were done correctly by going over to our repo on GitHub and refreshing the page. 

Upon doing so, we should see any changes we made reflected on the web, like this:

[![Screenshot 2025-09-16 at 9.31.04 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/scaled-1680-/screenshot-2025-09-16-at-9-31-04-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-09/screenshot-2025-09-16-at-9-31-04-pm.png)

Note: Another way to check is by opening VSCode again, and seeing if those green bars from earlier are still there. If not, then that means there are no new lines to stage, and your commit was successful!

## Project Outcomes

At the end of our time together, I hope that you all improve on a two key areas of software development:

### Technical Skills

- Development Patterns: Hooks, Context, functional components
- State Management: Complex state updates and data relationships
- User Experience Design: Responsive, accessible, intuitive interfaces
- Problem Solving: Handling edge cases and data integrity

### Project Management Skills

- Incremental Development: Built feature by feature
- Requirements Analysis: Translated real needs into technical specifications
- Testing Strategy: Systematic verification of functionality
- Documentation: Clear code organization and commenting

# Week 3

## Goals

- [ ] Ensure everyone has a React project installed and GitHub repo initialized
- [ ] Leran about React project structure
- [ ] Setup project scaffolding
- [ ] Define and structure data
- [ ] Implement some basic components


## Project Structure

### Key Files

`node_modules`

Where the third party libraries like react are installed; never needs to be touched.

`public`

Where the public assets exist (images, audio, etc).

`src`

Where all of our code is stored.

We start out only having `App.tsx`.

`index.html`

The container for our app.

Also has the entry point ot our app in `<script..`.

`package.json`

Some metadata on the project and its dependencies.

Also has some develpment dependencies.

### Components


Components are the building blocks a React app - which is what we will be building! They help us write clean, moular, and efficient code.

ex:

Grid of cards -> Card is a component -> Button in card is component

We build all components individually, then combine them to form a page.

Essentially, a react app is a tree of components iwth the app as the root bringing everything together.

## Setup

Let's navigate into our project directory and install the initial dependencies.

```
npx create-react-app blueprint_kudos --template typescript
cd blueprint_kudos
npm install
```

Create a `tsconfig.json` file
```json
{
  "compilerOptions": {
    "esModuleInterop": true,
    "skipLibCheck": true,
    "target": "es2022",
    "allowJs": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true,
    "verbatimModuleSyntax": true
  }
}

```

Now that we're in our project, lets focus on styling.

We're going to use **Tailwind CSS**. It's a framework that lets us style our components by adding class names directly in our HTML, instead of writing separate CSS files. It's super productive.

Let's install Tailwind and a few helper packages:

```
npm install tailwindcss postcss autoprefixer class-variance-authority clsx tailwind-merge
npx tailwindcss init -p
```

After you run that last command, you'll notice a couple of new files in your project, including `tailwind.config.js`. This is where we tell Tailwind where to look for our files. Let's configure it. 

Note: you don't need to know what these exact commnads mean, but do remember from our first session back in Week 1 what a dependency is - it will help you understand why this step is necessary.

Open up `tailwind.config.js` and replace its contents with this:

```js
/** @type {import('tailwindcss').Config} */
export default {
  content: ['./index.html', './src/**/*.{ts,tsx}'],
  theme: { extend: {} },
  plugins: [],
}
```

This just tells Tailwind to scan all our `.ts` and `.tsx` files inside the `src` folder for class names.

Finally, we need to actually include Tailwind's styles in our app. Open `src/index.css` and replace everything in there with these three lines:

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

/* This part is optional but nice for dark mode */
:root {
  color-scheme: light dark;
}
```

And that's it for setup! Let's run the dev server to make sure everything is working.

```
npm run dev
```

### Defining Data

Before we start building components, it's a really good idea to think about the _shape_ of our data. 

What does a "Developer" look like? What information does a "Kudos" contain? 

Using **TypeScript** to define these shapes, or "types," helps us avoid a ton of bugs later.

Let's create a new folder `src/lib` to hold some of our shared logic. Inside it, create a file named `types.ts`.

`src/lib/types.ts`:

```tsx
export type Role = 'techLead' | 'developer';

export type Developer = {
  id: string;
  name: string;
  avatarUrl?: string;
  teamId: string;
};

export type Team = {
  id: string;
  name: string;
};

export type Kudos = {
  id: string;
  fromId: string; // developer or TL giving kudos
  toId: string;   // recipient developer
  message: string;
  createdAt: string;
  sprint?: string;
  tag?: 'collaboration' | 'quality' | 'initiative';
};
```

See how clear that is? Now, whenever we work with a `Developer` object, TypeScript will make sure it has an `id`, a `name`, etc.

Next, let's create a little file for small, reusable functions. We'll call this file `utils.ts`.

`src/lib/utils.ts`:

```tsx
// a simple function to generate a unique-ish ID
export const uid = () => Math.random().toString(36).slice(2, 9);

// a helper to get the current timestamp in a standard format
export const nowIso = () => new Date().toISOString();


// note: we'll see how this works when we build our components.
export function cn(...classes: Array<string | false | null | undefined>) {
  return classes.filter(Boolean).join(' ');
}
```


### Managing States

This part of the session may be a little more abstract, but it asks an important question: how do all our different components (the sidebar, the dashboard, the modal, etc) share information and stay in sync? 

We need a single, central "source of truth." This is often called **state management**.

For this we leverage a concept called context - and need a respective file for it.

Let's create our context file.

`src/lib/app-context.tsx`:

```tsx
import React, { createContext, useContext, useMemo, useReducer } from 'react';
import type { Developer, Team, Kudos, Role } from './types';
import { uid, nowIso } from './utils';

// first, we define the shape of our entire application's state
type State = {
  role: Role;
  teams: Team[];
  developers: Developer[];
  kudos: Kudos[];
  activeDeveloperId?: string;
  giveKudosOpen: boolean;
  giveKudosRecipientId?: string;
};

// next, we define all the possible actions that can change our state
type Action =
  | { type: 'switchRole'; role: Role }
  | { type: 'setActiveDeveloper'; developerId?: string }
  | { type: 'openGiveKudos'; toId?: string }
  | { type: 'closeGiveKudos' }
  | { type: 'createKudos'; toId: string; fromId: string; message: string; tag?: Kudos['tag'] };

// our initial data so the app isn't empty when it loads
const initialState: State = {
  role: 'techLead',
  teams: [
    { id: 't1', name: 'Alpha' },
    { id: 't2', name: 'Beta' },
  ],
  developers: [
    { id: 'd1', name: 'Alex Johnson', teamId: 't1' },
    { id: 'd2', name: 'Sam Lee', teamId: 't1' },
    { id: 'd3', name: 'Priya Patel', teamId: 't2' },
  ],
  kudos: [],
  giveKudosOpen: false,
};

// the reducer function
function reducer(state: State, action: Action): State {
  switch (action.type) {
    // for each action, we return a *new* copy of the state with the changes
    case 'switchRole':
      return { ...state, role: action.role };
    case 'setActiveDeveloper':
      return { ...state, activeDeveloperId: action.developerId };
    case 'openGiveKudos':
      return { ...state, giveKudosOpen: true, giveKudosRecipientId: action.toId };
    case 'closeGiveKudos':
      return { ...state, giveKudosOpen: false, giveKudosRecipientId: undefined };
    case 'createKudos': {
      const newKudos: Kudos = {
        id: uid(),
        toId: action.toId,
        fromId: action.fromId, // we'll hardcode this for now
        message: action.message,
        createdAt: nowIso(),
        tag: action.tag,
      };
      // add the new kudos to the *beginning* of the array
      return { ...state, kudos: [newKudos, ...state.kudos], giveKudosOpen: false };
    }
    default:
      return state;
  }
}

// creating the actual context and a provider component
const AppContext = createContext<{ state: State; dispatch: React.Dispatch<Action> } | null>(null);

export function AppProvider({ children }: { children: React.ReactNode }) {
  const [state, dispatch] = useReducer(reducer, initialState);
  const value = useMemo(() => ({ state, dispatch }), [state]);
  return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
}

// custom hook to make it easy for components to access the state
export function useApp() {
  const ctx = useContext(AppContext);
  if (!ctx) throw new Error('useApp must be used within AppProvider');
  return ctx;
}

// "Selectors" are helpers to get specific, computed data from the state
export const selectors = {
  developerById: (id?: string) => (s: State) => s.developers.find((d) => d.id === id),
  developersByTeam: (teamId: string) => (s: State) => s.developers.filter((d) => d.teamId === teamId),
  kudosForDeveloper: (devId: string) => (s: State) => s.kudos.filter((k) => k.toId === devId),
};
```

...that was a lot of code.

I know it seems like a lot, but this is the 'brain' of our app, so it is important we do it right.


## Building Components

Instead of pulling in a UI library from an external source, let's create a few of our own simple, reusable components. 

Think of these as the bricks of a house. We'll build them once and reuse them everywhere.

Let's create a `src/components/ui` folder. Inside it, we'll create our `Button`, `Card`, `Input`, and `Textarea`.

For our buttons...

`src/components/ui/button.tsx`:

```tsx
import React from 'react';
import { cn } from '../../lib/utils'; // Remember our helper?

type Props = React.ButtonHTMLAttributes<HTMLButtonElement> & { variant?: 'primary' | 'ghost' };
export function Button({ className, variant = 'primary', ...props }: Props) {
  const base = 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none h-9 px-4';
  const styles =
    variant === 'primary'
      ? 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-400'
      : 'bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800';
  // Here's where `cn` is useful, merging base styles, variant styles, and any custom classes
  return <button className={cn(base, styles, className)} {...props} />;
}
```


For our cards...

`src/components/ui/card.tsx`:

```tsx
import React from 'react';
import { cn } from '../../lib/utils';

export function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn('rounded-lg border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900', className)} {...props} />;
}
export function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn('p-4 border-b border-gray-200 dark:border-gray-800', className)} {...props} />;
}
export function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return <div className={cn('p-4 space-y-2', className)} {...props} />;
}
```

For our inputs...

`src/components/ui/input.tsx`:

```tsx
import React from 'react';
import { cn } from '../../lib/utils';

export const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(
  ({ className, ...props }, ref) => (
    <input
      ref={ref}
      className={cn('w-full rounded-md border border-gray-300 dark:border-gray-700 bg-transparent px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-blue-400', className)}
      {...props}
    />
  )
);
Input.displayName = 'Input';
```


And finally, for our text areas...

`src/components/ui/textarea.tsx`:

```tsx
import React from 'react';
import { cn } from '../../lib/utils';

export const Textarea = React.forwardRef<HTMLTextAreaElement, React.TextareaHTMLAttributes<HTMLTextAreaElement>>(
  ({ className, ...props }, ref) => (
    <textarea
      ref={ref}
      className={cn('w-full rounded-md border border-gray-300 dark:border-gray-700 bg-transparent px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-blue-400', className)}
      {...props}
    />
  )
);
Textarea.displayName = 'Textarea';
```

We now have a consistent set of UI components to build our features with!

# Week 3

## Goals

- [ ] Intro to CSS
- [ ] Building a demo page
- [ ] Implementing the `KudosCard` component
## A Note About Project Versions and Installations...

I knwo we had some mix-ups and discrepencies last session when trying to create a project.

So, we need to do some cleaning to ensure there is no confusion in the future with project names, versions, etc.

Let's take a few minutes to delete all prior projects relating to Kudos (`blueprint_kudos`, `kudos-me`, etc.)

For the last time (fingers crossed) let's create a React project configured to use TypeScript.

In your **root** directory, run:

```
npx create-react-app blueprint_kudos --template typescript
```

After running, you may be asked a few questions. Simply respond yes to all of them.

Then, to open your project in VSCode and start your live development server, run:

```
cd blueprint_kudos
npm install
npm start
```

## Part 1: CSS Basics

Last week you saw some live changes made to the browser, and hopefully gained some understanding of why we really need tools like Node and git.

This week, we will be getting hands-on with one of the main languages of our app: CSS.

### What is CSS?

CSS, which stands for Cascading Style Sheets, is a style sheet language used for describing the presentation of a document written in a markup language like HTML.

Basically, it makes websites look nice.

### HTML

You may have heard of HTML, but what does it actually do?

HTML is the **structure** of a webpage. It's like the skeleton or framework that holds everything together.

Here is some brief info about HTML before we begin diving into CSS. Feel free to check out some tutorials/videos on HTML ifn you want to learn more tha what is in these docs.

#### How HTML Works

HTML uses **tags** (words in angle brackets) to define different parts of a webpage:

```html
<h1>This is a heading</h1>
<p>This is a paragraph</p>
<button>Click me</button>
```

#### Cheatsheet

Use this as a cheatsheet for whenever you forgot/don't know which tags to use.

- **`<h1>`, `<h2>`, `<h3>`** - Headings (big to small)
- **`<p>`** - Paragraphs
- **`<div>`** - Container/box
- **`<button>`** - Clickable buttons
- **`<img>`** - Images
- **`<a>`** - Links

And remember: **HTML is the foundation - everything else builds on top of it!**

#### A Useful Analogy

A classic analogy that I will probably continue using throughout the next few sessions is this:

Our app is like a house...

HTML is the walls.

TypeScript is the door.

**CSS is the paint.**

We need all three to build a house, and in our case, this app.

But, specifically, CSS controls:
- **Colors** - text, backgrounds, borders
- **Layout** - where elements appear on the page
- **Typography** - fonts, sizes, spacing
- **Visual effects** - shadows, animations, hover effects

Let's see how this works in practice.

### Classes

You may have heard of classes before... but CSS classes are slightly different.

CSS classes are reusable **style** definitions that you can **apply to HTML elements.** They're like templates for styling that you can use over and over again.

We can think of CSS classes like labels or tags that you apply to HTML elements to style them.

Imagine you have a box of different colored stickers:
- Yellow stickers for "important" items
- Red stickers for "urgent" items
- Green stickers for "completed" items

You stick these labels on different objects, and everyone knows what each color means.

CSS classes work the same way. You "stick" a class name on an HTML (wall) element, and the browser knows how to style it with CSS (paint).

### Selectors

Before we can style anything, we need to tell CSS what we want to style. This is where selectors come in.

The purpose of selectors is to **tell CSS which HTML elements we want to style**

Let's create a simple demo TypeScript file to see this in action.

First though, let's create a directory (folder) to store our components:

CREATE: `src/components`

Then, 

CREATE:` src/components/CSSBasicsDemo.tsx`

```ts
// Creating the demo component
export function CSSBasicsDemo() {
  return (
    <div className="demo-container"> {/* 1. demo-container class*/}
      <h2>CSS Basics Demo</h2>
      <div className="box-model-demo">
        <h3>Box Model</h3>
        <div className="box-example"> {/* 2. box-example class */}
          <div className="content">Content</div>
        </div>
      </div>
    </div>
  );
}
export default CSSBasicsDemo;
```

Now, let me add the CSS file. Notice how I'm targeting these elements using class names:

CREATE: `src/components/CSSBasicsDemo.css`

```css
/* I'm targeting the demo-container class */
.demo-container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

/* I'm targeting the box-example class */
.box-example {
  width: 200px;
  height: 100px;
  padding: 20px;
  margin: 20px;
  border: 3px solid #3b82f6;
  background-color: #f8fafc;
}
```

See how this works? I'm using class names - those are the words after 'className=' in the HTML - to target specific elements. This is the most common way to style things in React.

Recall: `src/App.tsx` is the main file in any React project, because it is where the main application structure is defined, and where each component is referenced.

So, let's update ours with our new components:

```ts
import React from 'react';
import { CSSBasicsDemo } from './components/CSSBasicsDemo'; // refernces .tsx demo file
import './components/CSSBasicsDemo.css'; // refernces .css demo file

function App() {
	return <CSSBasicsDemo />;
}

export default App;
```
[![Screenshot 2025-10-01 at 12.45.51 AM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2025-10-01-at-12-45-51-am.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/screenshot-2025-10-01-at-12-45-51-am.png)

If you're seeing a page that looks like this, then you've done everything correctly so far!

### The Box Model

Note: This is a VERY important section, so be sure to ask any questions if you need to. The Box Model is absolutely crucial to understand. 

The Box Model describes that **every single element on a webpage is a box.**

To show you what I mean, let's use some developer tools (DevTools) made availible to us through `Inspect Element`.

To access your DevTools, right-click the object you want to examine (in our case, the blue box), and select`Inspect Element` from the dropdown.

[![Screenshot 2025-10-01 at 12.35.35 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2025-10-01-at-12-35-35-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/screenshot-2025-10-01-at-12-35-35-pm.png)

You should now see a new window appear. It should look something like this:

[![Screenshot 2025-10-01 at 12.35.56 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2025-10-01-at-12-35-56-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/screenshot-2025-10-01-at-12-35-56-pm.png)

Let me break down what's happening here:

Each class is made up of properties which describe it in many ways. 

In this example:
- The **content** is the actual text or image inside.
- **Padding** is the space inside the element, between the content and the border. That's the white space around the blue text.
- The **border** is the line around the element. That's the blue line you see.
- **Margin** is the space outside the element, between this element and other elements.

Let's see what heppns when we make a change to one of these properties...

First, hover over some of the `<div>`s so you can see exactly how your code is visualized on our webpage. Like this:

[![Screenshot 2025-10-01 at 12.36.08 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2025-10-01-at-12-36-08-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/screenshot-2025-10-01-at-12-36-08-pm.png)

See how when my mouse is hovered over `"box-example"` it is highlighted on our webpage? This makes knwoing what our code does visually super clear.

We can see the properties of any element we want in the right panel that looks like this:

[![Screenshot 2025-10-01 at 12.47.26 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2025-10-01-at-12-47-26-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/screenshot-2025-10-01-at-12-47-26-pm.png)

Hmm... some of those properties in the panel seem very familiar...

Remember how we gave our classes certain properties earlier in `src/components/CSSBasicsDemo.css`?  We can now play around with their values to see their effect visually on our webpage.

Let's do some experimentation.

UPDATE: `src/components/CSSBasicsDemo.css`

```css
.box-example {
  padding: 40px; /* Changed from 20px */
}
```

See how the content moved further from the border? That's padding.

Now let us change the margin...

```css
.box-example {
  margin: 40px; /* Changed from 20px */
}
```

See how the entire box moved away from other elements? That's margin.

This is so important because when you're building layouts, you need to understand how these four things work together. 

**Most layout problems you'll face when first starting off come from not understanding the box model.**

To close off this section, experimentsome more with the box-example properties and see the changes visually in your live server.

```css
.demo-container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

/* Play around here and see the visual changes */
.box-example {
  width: 200px;
  height: 200px; /* 100 -> 200 */
  padding: 80px; /* 20 -> 40 -> 80 */
  margin: 60px; /* 20 -> 60 */
  border: 3px solid #3b82f6;
  background-color: #f8fafc;
}

```


## Part 2: Building Our Kudos Card Component 

### Step 1: Planning Our Component

In software development, the first step is always to plan.

Since we already have an idea of what our end product looks like, and we now understand how our app is structured, **we can actually do this step without any pre-existing visualization!**

But, because we have an end product already, let's look back to it and create a quick list of components we will need to build.

[look at final Kudos example from Week 1]

One clear one that we should consider is the card layout - especially since it is the heart of our app. 

Let's think about what this component needs:
- A recipient's name
- The kudos message
- Who gave the kudos
- When it was given
- What type it is (kudos or feedback)

This is a great example of a real-world component. It's not too simple, but not too complex either.

Let me create the basic structure first...

### Step 2: Structuring the Component

Let's create a new file for our kudos card component. 

Note: In React, it's common to have one component per file.

CREATE: `src/components/KudosCard.tsx`
```ts
import React from 'react';

interface KudosCardProps {
  recipient: string;
  message: string;
  giver: string;
  type: 'kudos' | 'feedback';
  date: string;
}

export function KudosCard({ recipient, message, giver, type, date }: KudosCardProps) {
  return (
    <div className="kudos-card">
      <div className="kudos-header">
        <h3 className="recipient-name">{recipient}</h3>
        <span className="kudos-type">{type}</span>
      </div>
      
      <p className="kudos-message">{message}</p>
      
      <div className="kudos-footer">
        <span className="giver-name">From: {giver}</span>
        <span className="kudos-date">{date}</span>
      </div>
    </div>
  );
}
```

Let me walk through what I'm doing here:

First, I'm defining the TypeScript interface. This tells us exactly what props this component expects. This is really helpful because if someone tries to use this component incorrectly, TypeScript will catch the error.

The component structure is semantic - I'm using meaningful HTML elements. The header contains the recipient name and type, the message is in a paragraph, and the footer has the giver and date.

Notice how I'm using className for all the styling. **This is how we connect our HTML to our CSS.**

Now let me add the CSS...

### Step 3: Applying CSS Styles

I'm creating a separate CSS file for this component. This keeps things organized and makes the component reusable.

CREATE: `src/components/KudosCard.css`


```css
/* src/components/KudosCard.css */

.kudos-card {

	/* Box Model */
	width: 100%; /* Full width of container */
	max-width: 400px; /* Maximum width */
	padding: 24px; /* Space inside the card */
	margin: 16px 0; /* Space above and below */
	border: 1px solid #e2e8f0; /* Light gray border */
	border-radius: 12px; /* Rounded corners */
	
	/* Layout */
	display: flex; /* Make it a flex container */
	flex-direction: column; /* Stack children vertically */
	gap: 16px; /* Space between children */
	
	/* Colors */
	background-color: #ffffff; /* White background */
	color: #1e293b; /* Dark gray text */
	
	/* Typography */
	font-family: 'Inter', -apple-system, sans-serif; /* Font family */
	font-size: 14px; /* Base font size */
	line-height: 1.5; /* Line spacing */
	
	/* Visual Effects */
	box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); /* Subtle shadow */	
	transition: all 0.2s ease; /* Smooth transitions */
}
```

Let me break this down:

I'm using the box model we learned about:  padding for internal space, margin for external space, border for the outline.

`max-width: 400px` means the card won't get wider than 400 pixels, but it can be smaller on mobile devices.

`display: flex` with `flex-direction: column` stacks the elements vertically.

`gap: 16px` puts consistent space between all the child elements.

I know we can really strecth our skills though, so let's keep adding props...

For the hover effect from before:

```css
	/* ...prior code... */

.kudos-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
  border-color: #cbd5e1;
}
```

This creates a nice interactive effect. When you hover over the card, it should  move up slightly and get a stronger shadow.

Now let me style the header...

```css
	/* ...prior code... */

.kudos-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.recipient-name {
  font-size: 18px;
  font-weight: 600;
  color: #0f172a;
  margin: 0;
}

.kudos-type {
  padding: 4px 12px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
```

The header uses flexbox to put the name on the left and the type badge on the right.

The type badge has rounded corners (`border-radius: 20px`) and is styled like a pill.

Let me add different colors for different types...

```css
	/* ...prior code... */

.kudos-type.kudos {
  background-color: #dbeafe;
  color: #1e40af;
}

.kudos-type.feedback {
  background-color: #f3f4f6;
  color: #374151;
}
```

This uses CSS class combination. When an element has both `kudos-type` and `kudos` classes, it gets the blue styling. When it has `kudos-type` and `feedback`, it gets the gray styling.

Now let me style the message and footer...

```css
	/* ...prior code... */

.kudos-message {
  font-size: 15px;
  line-height: 1.6;
  color: #475569;
  margin: 0;
  flex-grow: 1;
}

.kudos-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 12px;
  border-top: 1px solid #f1f5f9;
  font-size: 12px;
  color: #64748b;
}
```

The message uses `flex-grow: 1` which means it will take up all available space, pushing the footer to the bottom.

The footer has a subtle border on top to separate it from the message.

All together now...

```css
/* src/components/KudosCard.css */

.kudos-card {

	/* Box Model */
	width: 100%; /* Full width of container */
	max-width: 400px; /* Maximum width */
	padding: 24px; /* Space inside the card */
	margin: 16px 0; /* Space above and below */
	border: 1px solid #e2e8f0; /* Light gray border */
	border-radius: 12px; /* Rounded corners */
	
	/* Layout */
	display: flex; /* Make it a flex container */
	flex-direction: column; /* Stack children vertically */
	gap: 16px; /* Space between children */
	
	/* Colors */
	background-color: #ffffff; /* White background */
	color: #1e293b; /* Dark gray text */
	
	/* Typography */
	font-family: 'Inter', -apple-system, sans-serif; /* Font family */
	font-size: 14px; /* Base font size */
	line-height: 1.5; /* Line spacing */
	
	/* Visual Effects */
	box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); /* Subtle shadow */	
	transition: all 0.2s ease; /* Smooth transitions */

}

.kudos-card:hover {

	transform: translateY(-2px); /* Move up slightly on hover */	
	box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); /* Stronger shadow on hover */
	border-color: #cbd5e1; /* Lighter border on hover */
}

  
.kudos-header {
	display: flex; /* Make it a flex container */
	justify-content: space-between; /* Space items apart */
	align-items: center; /* Center items vertically */
	margin-bottom: 8px; /* Space below header */
}

.recipient-name {
	font-size: 18px; /* Larger font size */
	font-weight: 600; /* Bold text */
	color: #0f172a; /* Very dark gray */
	margin: 0; /* Remove default margin */
}

.kudos-type {
	padding: 4px 12px; /* Space inside badge */
	border-radius: 20px; /* Pill-shaped */
	font-size: 12px; /* Small font size */
	font-weight: 500; /* Medium bold */
	text-transform: uppercase; /* All caps */
	letter-spacing: 0.5px; /* Space between letters */
}

  
.kudos-type.kudos {
	background-color: #dbeafe; /* Light blue background */
	color: #1e40af; /* Dark blue text */
}

  
.kudos-type.feedback {
	background-color: #f3f4f6; /* Light gray background */
	color: #374151; /* Dark gray text */
}


.kudos-message {
	font-size: 15px; /* Slightly larger font */
	line-height: 1.6; /* Good line spacing */
	color: #475569; /* Medium gray text */
	margin: 0; /* Remove default margin */
	flex-grow: 1; /* Take up available space */
}


.kudos-footer {
	display: flex; /* Make it a flex container */
	justify-content: space-between; /* Space items apart */
	align-items: center; /* Center items vertically */
	padding-top: 12px; /* Space above footer */
	border-top: 1px solid #f1f5f9; /* Light border on top */
	font-size: 12px; /* Small font size */
	color: #64748b; /* Light gray text */
}

.giver-name {
	font-weight: 500; /* Medium bold */
}


.kudos-date {
	color: #94a3b8; /* Very light gray */
}
```


Finally, let's create a demo page to show this in action...

### Step 4: Creating the Demo Page

We need to update the App component to show our kudos cards...

```ts
// src/App.tsx
import React from 'react';
import { KudosCard } from './components/KudosCard';
import './components/KudosCard.css';

function App() {
  const sampleKudos = [
    {
      recipient: "Jane Smith",
      message: "Amazing work on the authentication refactor! Your clean code and thorough testing saved us so much time.",
      giver: "John Doe",
      type: "kudos" as const,
      date: "Mar 22, 2024"
    },
    {
      recipient: "Mike Johnson", 
      message: "Thanks for staying late to help debug the payment integration. Your persistence really paid off!",
      giver: "Sarah Wilson",
      type: "kudos" as const,
      date: "Mar 21, 2024"
    },
    {
      recipient: "Alex Chen",
      message: "Great job presenting the technical architecture to stakeholders. You explained everything so clearly!",
      giver: "Emily Davis", 
      type: "feedback" as const,
      date: "Mar 20, 2024"
    }
  ];

  return (
    <div className="app-container">
      <div className="app-content">
        <h1 className="app-title">
          - Kudos Cards Demo -
        </h1>
        
        <div className="cards-grid">
          {sampleKudos.map((kudos, index) => (
            <KudosCard
              key={index}
              recipient={kudos.recipient}
              message={kudos.message}
              giver={kudos.giver}
              type={kudos.type}
              date={kudos.date}
            />
          ))}
        </div>
      </div>
    </div>
  );
}

export default App;
```

Let me add some CSS for the app layout...

```css
/* Add to App.css or create App.css */
.app-container {
  min-height: 100vh;
  background-color: #f8fafc;
  padding: 32px 0;
}

.app-content {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 16px;
}

.app-title {
  font-size: 48px;
  font-weight: 700;
  text-align: center;
  color: #0f172a;
  margin-bottom: 32px;
}

.cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
  gap: 24px;
}

@media (max-width: 768px) {
  .cards-grid {
    grid-template-columns: 1fr;
  }
}
```

Look at that! We have working kudos cards!!!

Notice how they respond to hover, how the different types have different colors, how the layout is clean and structured!

# Week 4

## Welcome!

### Goals

- [ ] Discuss TypeScript essentials and how we should structure a component
- [ ] Build the Kudos form with `KudosForm.tsx`

### Quick Recap

Last week we learned:
- CSS fundamentals
- How to build the KudosCard component
- How to display multiple cards using sample data

### A Quick Note...

The nest few sessions (weeks) will be dedicated to implementing `KudosForm` and the respective cards that are created after a submission is made.

This will take some time, so I decided to split it up into a few parts (3, to be exact). Part 1 covers the TypeScript aspect (this doc), part 2 dives into CSS by having you complete a challenge (week 5), and part 3 is about implementing state, also through a challenge (week 6). Before moving ahead and reading this doc, make sure you've read week 3 as you'll need it for the challenges that lie ahead... 🤫

Good luck!


## Building the Kudos Form Component

### Step 1: Setting Up the KudosForm File

First, let's create a new file for our form component.

We will start with just the imports and the component shell:

**CREATE**: `src/components/KudosForm.tsx`

```ts
import { useState } from 'react';
import './KudosForm.css';

export function KudosForm() {
  return (
    <div>
      <h2>Form goes here</h2>
    </div>
  );
}
```

**What's happening:**
- We import `useState` from React - this is the **hook** we'll use for state
- We import our CSS file (which we'll create next)
- We export a function component called `KudosForm`
- For now, it just returns a simple div with text

### Step 2: Defining the Props Interface

In this step, we are going to learn about a few key React topics so be sure to ask questions if you are confused.

Currently, we know that our form needs some way to communicate with its parent component (App.tsx). 

So, how can we do this? How can we connect the live state of our component - in this case, our kudos form - with its parent component?

To facilitate this communication, we use **props**.

#### Props

Props are **read-only properties** that are passed from a **parent component** to a **child component**. 

They are a fundamental concept for passing data and configuration down the component tree and ensuring that components can talk to each other in real-time.

#### Interfaces

This may seem like a lot to manage - and it is - but thankfully, React makes it really easy for us to organize and manage this data. To show this, let's talk a bit about interfaces.

Interfaces are primarily used to **define the structure and types** that the props of a component's object must adhere to. 

It is a little tricky to understand at first, but it is important to note that interfaces do not actually recieve or store this data, but rather, they enforce 'rules' that an object must follow.

An interface is basically a blueprint (hahahaha😅😐) that describes the data we want to receive from objects.

#### Destructuring

To make processing this data easier, we can employ a technique called destructuring.

Destructuring allows us to unpack an object's props into easy-to-use variables that we can call right in the function.

Without destructuring, our code looks like this:

```ts
//Regular Function component
function Welcome(props) {
  return <h1>Hello, {props.name} from {props.city}!</h1>;
}
```

See how we have to use dot-notation to retrieve information from an object? We are making it harder for ourselves than it has to be.

By destructuring objects, we can simply take their distinct variables as parameters rather than calling them from an object.

It looks like this:

```ts
// Destructuring { name, city } from the props object
function Welcome({ name, city }) {
  return <h1>Hello, {name} from {city}!</h1>;
}
```


### Putting these ideas together...

Let's define what data it expects and what it will send eventually send back.

**UPDATE**: Add this interface at the top of `src/components/KudosForm.tsx`:

```ts
import { useState } from 'react';
import './KudosForm.css';

// Define what props this component accepts
interface KudosFormProps {
  onSubmit: (kudos: {
    recipient: string; // recipient name as a string
    message: string; // kudos message as a string
    giver: string; // kudos giver as a string
    type: 'kudos' | 'feedback'; // type (kudos or feedback)
    date: string; // date as a string
  }) => void;
}

export function KudosForm({ onSubmit }: KudosFormProps) {
  return (
    <div>
      <h2>Form goes here</h2>
    </div>
  );
}
```

**What's happening:**
- `KudosFormProps` is a TypeScript **interface** that defines what props our component expects
- `onSubmit` - when the user submits the form, we'll create a kudos object and pass it to the parent component using this function. The parent decides what to do with it (like adding it to a list).
- The function accepts a kudos object with all the fields we need to track
- `type: 'kudos' | 'feedback'` means type can ONLY be one of these two strings
- `void` means the function doesn't return anything
- `{ onSubmit }: KudosFormProps` - we **destructure** the props to get the onSubmit function


---

### Step 3: Creating the Form Structure - Header

Let's build the actual form, starting with the header and structure.

**UPDATE**: Replace the return statement in `src/components/KudosForm.tsx`:

```ts
export function KudosForm({ onSubmit }: KudosFormProps) {
  return (
    <form className="kudos-form">
      <h2 className="form-title">✨ Give Kudos</h2>
    </form>
  );
}
```

**What's happening:**
- We use `<form>` instead of `<div>` - this is the HTML element for forms
- `className="kudos-form"` - this is how we attach CSS classes in React (remember: not `class`, but `className`)
- The emoji ✨ gives it some swag
- `form-title` is a CSS class we'll style later

---

### Step 4: Adding the Recipient Input Field

Finally, let's add our first input field!

This will be for the main input we are handling in this program... a Kudos message!

And again, feel free to ask questions as we walk through this - it is super important.

**UPDATE**: Add the first form group inside the `<form>` in `src/components/KudosForm.tsx`:

```ts
export function KudosForm({ onSubmit }: KudosFormProps) {
  return (
    <form className="kudos-form">
      <h2 className="form-title">✨ Give Kudos</h2>
      
      <div className="form-group">
        <label htmlFor="recipient">To:</label>
        <input
          id="recipient"
          type="text"
          placeholder="Enter recipient name"
          required
        />
      </div>
    </form>
  );
}
```

**What's happening:**
- `<div className="form-group">` - A container for the label and input
- `<label htmlFor="recipient">` - The label describes what the input is for
  - `htmlFor="recipient"` connects this label to the input with `id="recipient"`
  - When you click the label, it focuses the input!
- `<input>` - The actual text field
  - `id="recipient"` - Unique identifier, connects to the label
  - `type="text"` - Makes it a text input
  - `placeholder` - The gray text that shows when empty
  - `required` - HTML validation - form won't submit if empty

---

### Step 5: Adding the Message Text area

Next, let's add a textarea for the kudos message.

**UPDATE**: Add the message field in `src/components/KudosForm.tsx`:

```ts
export function KudosForm({ onSubmit }: KudosFormProps) {
  return (
    <form className="kudos-form">
      <h2 className="form-title">✨ Give Kudos</h2>
      
      <div className="form-group">
        <label htmlFor="recipient">To:</label>
        <input
          id="recipient"
          type="text"
          placeholder="Enter recipient name"
          required
        />
      </div>

      <div className="form-group">
        <label htmlFor="message">Message:</label>
        <textarea
          id="message"
          placeholder="Write your kudos or feedback..."
          rows={4}
          required
        />
      </div>
    </form>
  );
}
```

**What's happening:**
- `<textarea>` - Like an input, but for multi-line text
- `rows={4}` - Start with 4 visible rows (users can type more)
- Notice we use `{4}` with curly braces because it's a number, not a string
- Same pattern: label with `htmlFor`, textarea with matching `id`

---

### Step 6: Adding the Giver Input Field

Now let's add a field for who's giving the kudos.

**UPDATE**: Add the giver field in `src/components/KudosForm.tsx`:

```ts
export function KudosForm({ onSubmit }: KudosFormProps) {
  return (
    <form className="kudos-form">
      <h2 className="form-title">✨ Give Kudos</h2>
      
      <div className="form-group">
        <label htmlFor="recipient">To:</label>
        <input
          id="recipient"
          type="text"
          placeholder="Enter recipient name"
          required
        />
      </div>

      <div className="form-group">
        <label htmlFor="message">Message:</label>
        <textarea
          id="message"
          placeholder="Write your kudos or feedback..."
          rows={4}
          required
        />
      </div>

      <div className="form-group">
        <label htmlFor="giver">From:</label>
        <input
          id="giver"
          type="text"
          placeholder="Your name"
          required
        />
      </div>
    </form>
  );
}
```

**What's happening:**
- Same pattern as the recipient field
- This captures who is giving the kudos
- Notice the consistent structure: div wrapper, label, input

---

### Step 7: Adding the Type Selector (Dropdown)

Let's add a dropdown to choose between "kudos" and "feedback".

**UPDATE**: Add the type selector in `src/components/KudosForm.tsx`:

```ts
export function KudosForm({ onSubmit }: KudosFormProps) {
  return (
    <form className="kudos-form">
      <h2 className="form-title">✨ Give Kudos</h2>
      
      <div className="form-group">
        <label htmlFor="recipient">To:</label>
        <input
          id="recipient"
          type="text"
          placeholder="Enter recipient name"
          required
        />
      </div>

      <div className="form-group">
        <label htmlFor="message">Message:</label>
        <textarea
          id="message"
          placeholder="Write your kudos or feedback..."
          rows={4}
          required
        />
      </div>

      <div className="form-group">
        <label htmlFor="giver">From:</label>
        <input
          id="giver"
          type="text"
          placeholder="Your name"
          required
        />
      </div>

      <div className="form-group">
        <label htmlFor="type">Type:</label>
        <select id="type">
          <option value="kudos">Kudos</option>
          <option value="feedback">Feedback</option>
        </select>
      </div>
    </form>
  );
}
```

**What's happening:**
- `<select>` - Creates a dropdown menu
- `<option value="kudos">` - Each option has a value (what gets stored) and text (what user sees)
- The first option (Kudos) is selected by default
- This will let users choose whether they're giving kudos or feedback through the simple logic we impleemnted a few steps ago

---

### Step 8: Adding the Submit Button

Finally, let's add the submit button to complete our form structure.

**UPDATE**: Add the button at the end of the form in `src/components/KudosForm.tsx`:

```ts
export function KudosForm({ onSubmit }: KudosFormProps) {
  return (
    <form className="kudos-form">
      <h2 className="form-title">✨ Give Kudos</h2>
      
      <div className="form-group">
        <label htmlFor="recipient">To:</label>
        <input
          id="recipient"
          type="text"
          placeholder="Enter recipient name"
          required
        />
      </div>

      <div className="form-group">
        <label htmlFor="message">Message:</label>
        <textarea
          id="message"
          placeholder="Write your kudos or feedback..."
          rows={4}
          required
        />
      </div>

      <div className="form-group">
        <label htmlFor="giver">From:</label>
        <input
          id="giver"
          type="text"
          placeholder="Your name"
          required
        />
      </div>

      <div className="form-group">
        <label htmlFor="type">Type:</label>
        <select id="type">
          <option value="kudos">Kudos</option>
          <option value="feedback">Feedback</option>
        </select>
      </div>

      <button type="submit" className="submit-button">
        Send Kudos 🎉
      </button>
    </form>
  );
}
```

**What's happening:**
- `<button type="submit">` - When clicked, this will submit the form
- `type="submit"` is crucial - it tells the browser this button submits the form
- `className="submit-button"` for styling
- We're doing great work!


#### Step 8a: Import the Form Component

Now let's see our form structure! Even though it's not styled yet, we can display it to make sure everything is working.

**UPDATE**: Add imports at the top of `src/App.tsx`:

```ts:src/App.ts
import { useState } from 'react';
import { KudosCard } from './components/KudosCard';
import { KudosForm } from './components/KudosForm';  // ← Add this
import './components/KudosCard.css';
import './App.css';
```

**What's happening:**
- We import the `KudosForm` component we just created
- Now we can use `<KudosForm />` in our JSX
- Note: We're NOT importing the CSS yet - we'll add that after we create it

---

#### Step 8b: Create a Temporary Handler Function

Our form expects an `onSubmit` prop (remember the interface we created?). Let's create a temporary function to pass to it.

**UPDATE**: Add this inside the `App` function in `src/App.tsx`, right before the `return` statement:

```ts:src/App.ts
function App() {
  const sampleKudos = [
    {
      recipient: "Jane Smith",
      message: "Amazing work on the authentication refactor! Your attention to detail made the whole team more productive.",
      giver: "John Doe",
      type: "kudos" as const,
      date: "Mar 22, 2024"
    },
    {
      recipient: "Bob Wilson",
      message: "Could improve code documentation in the API module.",
      giver: "Alice Chen",
      type: "feedback" as const,
      date: "Mar 20, 2024"
    }
  ];

  // Temporary function - we'll make this work properly later!
  const handleAddKudos = (kudos: any) => {
    console.log('New kudos submitted:', kudos);
  };

  return (
    // ... rest of code ...
  );
}
```

**What's happening:**
- We create a function called `handleAddKudos` that takes a kudos object
- For now, it just logs to the console - we'll make it actually add kudos later
- `kudos: any` - TypeScript type `any` means "any type" (we'll make this properly typed later)
- This function will be called when the form is submitted

---

#### Step 8c: Add the Form to the JSX

**UPDATE**: Add the form component in `src/App.tsx`:

```ts
return (
  <div className="app-container">
    <div className="app-content">
      <h1 className="app-title">🎉 Kudos Board</h1>
      
      {/* Add the form here! */}
      <KudosForm onSubmit={handleAddKudos} />
      
      <div className="cards-grid">
        {sampleKudos.map((kudos, index) => (
          <KudosCard
            key={index}
            recipient={kudos.recipient}
            message={kudos.message}
            giver={kudos.giver}
            type={kudos.type}
            date={kudos.date}
          />
        ))}
      </div>
    </div>
  </div>
);
```

**What's happening:**
- `<KudosForm onSubmit={handleAddKudos} />` - We render the form component
- `onSubmit={handleAddKudos}` - We pass our temporary function as a prop
- The form appears ABOVE the kudos cards
- The form will receive the `handleAddKudos` function through its props

---

#### Step 8d: Check Your Browser!

**Look at your browser now!**

You should see your unstyled form appear above the kudos cards. It won't look pretty yet (that's coming in Part 3!), but you should see:

- The "Give Kudos" header
- The "To:" label and input field
- The "Message:" label and textarea
- The "From:" label and input field
- The "Type:" label and dropdown
- The "Send Kudos" button
- All the existing kudos cards below

**Try clicking around:**
- You can type in the fields
- You can select from the dropdown
- If you click the button, the form will submit (though nothing will happen yet - we haven't added the submit logic)

**Don't worry that it looks plain!** In the next section (Part 3), we'll make it beautiful with CSS!

# Week 5

## Goals

- [ ] Wrap up the `KudosForm.tsx` from last week's session
- [ ] Complete this week's challenge


## Your Objective

Your goal is to style the `KudosForm.tsx` component by adding CSS rules to the `KudosForm.css` file. We've already set up all the `className` attributes you'll need in the component. 

Your job is to target those classes and bring the app to life!

Try to create a design that is:
- **Clean and readable:** Users should easily understand what to do.
- **Modern:** Think soft shadows, rounded corners, and good spacing.
- **Interactive:** The form should give visual feedback when a user interacts with it (like clicking an input or hovering over the button).

## Task Outline

Here's a breakdown of the elements to style:

1. **The Main Container (`.kudos-form`)**
    - Make the form stand out from the background. It should look like a distinct "card." How can you give it some depth and defined edges?

2. **The Title (`.form-title`)**
    - The title "Give Kudos" should be a clear and prominent header for the form. How can you make it the focal point?

3. **Field Groups (`.form-group`)**
    - Currently, all the labels and inputs are squished together. Add some vertical spacing between each field group to let the form breathe.

4. **Field Labels (`.form-group label`)**
    - Style the labels (`To:`, `Message:`, etc.) so they are clear and distinct from the input fields they describe. They should sit neatly above their respective inputs.

5. **Inputs, Textareas, & Selects**
    - Target `.form-group input`, `.form-group textarea`, and `.form-group select` all at once.
    - Give them a consistent look. They should have clean borders, nice internal padding, and stretch to the full width of the form.

6. **The Focus State (`:focus`)**
    - This is a key part of user experience! When a user clicks into an input field, it should be visually obvious which one is active. How can you change the border or add a glow effect?

7. **The Submit Button (`.submit-button`)**
    - Make it look like the primary action on the form. Think about its color, font size, and shape.

## Some Hints...

Here are a few CSS properties that might help you out:

- **For the card effect:** Look into `box-shadow` and `border-radius`.
- **For spacing:** Your best friends are `margin` and `padding`. Remember, margin is for space _outside_ an element, and padding is for space _inside_.
- **To make the button feel "clickable":** Use `cursor: pointer;` to change the mouse icon, and for the "press down" effect, check out `transform: translateY(1px);` in an `:active` state.

If you do get stuck, feel free to refer back to last week's session where we discussed CSS styling!

Here is an example of what your cards could look like (ignore dark mode):

[![Screenshot 2025-10-22 at 2.58.36 PM.png](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2025-10-22-at-2-58-36-pm.png)](https://wiki.sitblueprint.com/uploads/images/gallery/2025-10/screenshot-2025-10-22-at-2-58-36-pm.png)

## Uhhh... what now?

Great job building the static components for our Kudos Board! You have a beautiful `<KudosForm />` that you can type in and a stylish `<KudosCard />` component ready to display data.

There's just one problem... they don't talk to each other. 😅

Next week, we will tie evrything together and get this component working with state! Get hype!

# Week 6 + 7

## Welcome!

### Goals

- [ ] Get an intuition for how state dictates behavior in an app
- [ ] Ponder some examples/use cases
- [ ] Complete this week's challenge!

### A Quick Recap...

Last week was awesome!!! Evevryone stepped up and took a leap of faith by styling a component all on your own... Kudos (😏) to you!

Big shoutout to Palak for catching the W last week!

## Understanding React State

A recurring question that has been asked for the last few weeks (and rightfully so) is how the form submission works. In other words, if someone is actually using the app on the web, how is their response to the form reflected in our project.

Currently, as you may have noticed in your code, we are hardcoding cards, which obviously isn't how an actual app works.

We want our app to be able to recieve user inputs (kudos) in real-time and update our card layout accordingly. 

And you guessed it, this is state!


### What is State?

Remember our house analogy?
- HTML is the walls (structure)
- CSS is the paint (styling)
- TypeScript is the door (logic)

**State is the furniture inside the house - it can change and move around dynamically!**

State is data that can change over time in your React component. When state changes, React automatically re-renders the component to show the updated information.

In effect, this is what gives **functionality** and actual usefulness to your code.

### Some Real-World Examples...

There are a few ways to think about state in everyday terms:

**A light switch** - It has two states: ON or OFF
- Current state: The light is currently ON
- *Action: You flip the switch*
- New state: The light is now OFF

**A shopping cart** - It has a list of items
- Current state: 3 items in cart
- *Action: You add a new item*
- New state: 4 items in cart

**Our Kudos App** - It will have a list of kudos cards
- Current state: 1 kudos card displayed
- *Action: User submits the form*
- New state: 2 kudos cards displayed

This is exactly what we're building today!

### Hooks

Hooks are functions that let you "hook into" and control React states.

Since we can use hooks for each individual (functional) component, it is actually possible to write entire React applications using only functional components, which in turn HIGHLY simplifies the component model that we discussed last week.

Before we dive into how they are used in our project, let's go over some properties of hooks that will help you understand them better

#### General Properties

- They can only be used with functional components. You CANNOT use them in class components.
- Every time our function runs/is called, its hooks must run in the exact same order. In other words, we cant really have a hook inside of a conditional statement, since if the statement didn't run, we would have an error. This follows that we really can't have hooks nested inside of anything (loops, conditionals, functions, etc.). They must be at the top level of our function, and always called in the exact same order.
- Lastly, there are a few important types of hooks that React allows us to use. In the next section, I will go over one of these types.

#### The useState Hook

React gives us a special function called `useState` to manage state. The pattern looks like this:

```ts
const [currentValue, functionToUpdateIt] = useState(initialValue);
```

Think of it like this:
- **currentValue** - What the state is right now
- **functionToUpdateIt** - How to change it
- **initialValue** - What it starts as

Don't worry if this seems abstract - it'll make perfect sense once we start building!


## Your Objective

Last week, you successfully built the static UI for our Kudos Board!

There's just one problem... they don't talk to each other. 😅

These components aren't connected yet; **they don't share any data.**

When you fill out the form and hit "Send Kudos," nothing happens. The form data just disappears, and no new card appears.

**Your goal this week is to fix this.** You need to use React's `useState` hook to capture the form submissions and display them as new cards.

### Task Outline

Make the app fully functional. When a user fills out the `KudosForm` and clicks "Send Kudos," a new `KudosCard` should appear in the `cards-grid`.

To solve this, you will need to:

1. **Find the Right Home for State:** Where does the list of all kudos need to live so that _both_ the form (to add kudos) and the card display (to read kudos) can access it?
2. **Initialize the State:** In the correct component (if you cant figure which, let us know), use the `useState` hook to create a state variable that holds an _array_ of `Kudos` objects. You can start it with an empty array `[]` or use the example kudos from the lesson plan.
3. **Create an "Add" Function:** In the _same component_ where you created your state, write a function (like `handleAddKudos`) that takes a new `Kudos` object as an argument and updates the state by adding this new object to the array.
4. **Pass the Function:** Pass your new "add" function down to the `<KudosForm />` as a prop (e.g., `onSubmit`).
5. **Render the List:** Use your state array to render the list of cards. Instead of hard-coding a `<KudosCard />`, you'll need to _map_ over your state array and return a `<KudosCard />` for each item.
    

### Bonus (If ur trying to flex)

Once it's working, try implementing a "Empty State" message. Your app should show a friendly message like "No kudos yet. Be the first!" _only_ when the `kudosList` array is empty.

### Resources Some Hints...

This is a great resource to get you started. There is a also a really good example implementation: [Managing State](https://wiki.sitblueprint.com/attachments/15)

- Don't forget to import `useState` from `'react'`(this is likely why your code might be not working).
- Remember the `Kudos` interface from Week 4? It will help TypeScript know what your state looks like (`useState<Kudos[]>(...)`).
- **IMPORTANT:** You must **never** modify state directly (like using `.push()`). You must always create a _new_ array using the spread operator (`...`) and pass that to your `setKudosList` function.
- When you `.map()` over your array to create cards, React will need a unique `key` prop for each `<KudosCard />` (if unsure/unfamiliar with what a key is or what this means, ask us!).

As always, Derrick and I are here for you!!! Just ask if you get stuck.

# Week 8

## Goals

Here are the goals for this week:
- [ ] Build a static `<Sidebar />` component.


## Recap and a Quick Note...

I know a lot of people couldn't finish implementing state during last week's session, and that is ok! The concept of state is non-trivial and much harder to implement on your own than tasks from prior weeks. 

Which brings me to my note... 

If you have free time, go watch a YouTube video and go back in to try again! Even better, read the documentation! 

I hate to admit it, but reading documentation is something I only really started doing a few months ago, and I realize now that it is extremely useful and a high ROI for your skills as a programmer/student/human imo. 

Try it out!

Now for the objective...

## Your Objective

Right now, our Kudos Board is just a form and some cards on a blank page. "Real" apps have navigation, a persistent header, and a consistent layout. When you click a menu button on a mobile site, you naturally expect a sidebar to behave and feel a certain way. 

**Your goal this week is to build a component of that static app layout.** You'll create a static `<Sidebar />` (side menu) using TypeScript, and style it using CSS.

## Motivation

You might be thinking, "Why are we making an individual `Sidebar.tsx` file? Couldn't I just dump all the HTML into `App.tsx`?"

Welllll yes, you couldddd, BUT you'd be setting yourself up for a massive headache later. 

This idea of breaking your UI into small, self-contained pieces is one of the most important concepts in React (and web dev).

Here's some reasons why:

- DRY (Don't Repeat Yourself): This is a core programming principle. If you find yourself copying and pasting the same chunk of HTML/CSS/JS, you should probably make it a component. Why? Because if you need to change it, you only have to change it in one file, not 10.
- It's just easier 🫣...
	- **Easier to Fix (Maintainability):** If your sidebar has a bug, you know _exactly_ where to look: `Sidebar.tsx`. You don't have to hunt through a giant 1000-line `App.tsx` file to find the broken `<div>`.
	- **Easier to Read (Readability):** When someone else (or you, 6 months from now) looks at your `App.tsx`, they won't see a wall of code. They'll see `<Sidebar />`, `<KudosForm />`and `<KudosCards />`. You instantly know what the page is made of.
	- **Easier to Grow (Scalability):** Need another sidebar on a different page down the line? Just import `<Sidebar />`.  You can pass it a prop to change its behavior. This makes building new features way faster.

By building a clean component today, you're building a something that you can trust, understand, and reuse anywhere, which is key to building large, complex projects.

## Task Outline

Implement a responsive navigation layout. This will involve creating a `<Sidebar />` component.

### Your Checklist

To get this done, you'll need to:

1. Create a new component file `Sidebar.tsx` (and a CSS file, `Sidebar.css`).
2. Build the `<Sidebar />`.
    - It should be a vertical bar positioned on the left side of the screen.
    - Add a few placeholder links inside like "Home," "Give Kudos," and "Profile." (don't worry about them not going anywhere yet!)        
3. Now, go into your `.css` files and make it look good! In `Sidebar.css`, style the `.sidebar` class to be a vertical bar that's always visible on the left.
4. In your main `App.tsx`, implement your component. 

### Some Hints...

Remember prior weeks! Our past sessions have covered the skills you need to do this, so feel free to reference them

Here's some icons for your sidebar. Simply copy this code and paste (define) at the top of your `Sidebar.tsx` file:

```ts
import './sidebar.css';

// --- Helper Icon Components (Replaces lucide-react) ---
// We define simple SVGs here to keep the file self-contained.

// Icon for "Home"
const HomeIcon = ({ className }: { className: string }) => (
  <svg
    className={className}
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
  >
    <path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
    <polyline points="9 22 9 12 15 12 15 22" />
  </svg>
);

// Icon for "Give Kudos" (using a simple "gift" icon)
const KudosIcon = ({ className }: { className: string }) => (
  <svg
    className={className}
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
  >
    <polyline points="20 12 20 22 4 22 4 12" />
    <rect x="2" y="7" width="20" height="5" />
    <line x1="12" y1="22" x2="12" y2="7" />
    <path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z" />
    <path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z" />
  </svg>
);

// Icon for "Profile" or "User"
const UserIcon = ({ className }: { className: string }) => (
  <svg
    className={className}
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
    strokeLinecap="round"
    strokeLinejoin="round"
  >
    <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
    <circle cx="12" cy="7" r="4" />
  </svg>
);
```

## I'm done... what's next!?

Nice! You've got a clean and modern sidebar!

Next week, we'll look into how to make those sidebar links actually go to different pages by introducing React Router!

# End of Semester Challenge! (Week 9)

## Goals

Here are this week's goals:
- Complete the EOS challenge!

## Your Objective

Get ready for the ultimate challenge... building Kudos from scratch! 🙀

For the final session of this semester, lets leverage all of the skills and practices we've obtained from prior weeks to build Kudos as if we came up with it on our own.

In other words, your goal is to setup, build, and run a React app (namely, Kudos) all on your own! 

## Your Checklist

To get this done, you'll need to recall each prior week to some extent. 

Let's walk through some high-level steps that you might take to do this:

1. **Create a react app.** Not much to add here, but if you run into any errors, just remember that the command you enter in the terminal must follow a specific syntax.
2. **Open your project.** After creating the app, you should open it in VSCode. If you remember how to do this from your terminal, awesome! If you don't, no worries, just do it via the VSCode window.
3. **Start a development server.** In the VSCode project terminal (you can open it from the navbar), run the command to start your localhost. 
4. **Create a folder to store your components and create the necessary component files.** Create and move the files you'll need to build the form and cards in your components folder. You can decide what to name them, but remember to keep the naming consistent.
5. **Write the code!** Remember to check past weeks if you need guidance. Also, remember to save your changes frequently with Ctrl + S / Cmd + S 

## Closing Remarks and an Exit Ticket

Thank you all for an amazing semester!!!!!

I had a great time learning and coding with everyone, and am even more hype for when we return in the Spring.

My last ask is that you complete this form: [EOS Feedback](https://wiki.sitblueprint.com/attachments/16)

I designed it for a few reasons:
1. To get your feedback on the sessions.
2. To see where you feel like are now vs. where you were in August when we started.
3. Lastly, and most importantly, to get your input on what we should do next semester!

Blueprint is still super young and this is our first time running Tech Team this way, so your thoughts and opinions will directly shape how we run it for semesters to come. 

On that note, please be brutally honest and open about what you liked and didn't like, it will help us out massively.

I appreciate you all and thanks again for a great semester!