nikniksen commited on
Commit
5ab90e1
1 Parent(s): cdefb2d

Add 11 files

Browse files
Dockerfile ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM node:18-alpine AS base
3
+
4
+ # Install dependencies only when needed
5
+ FROM base AS deps
6
+ # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
7
+ RUN apk add --no-cache libc6-compat
8
+ WORKDIR /app
9
+
10
+ # Install dependencies based on the preferred package manager
11
+ COPY package.json package-lock.json* ./
12
+ RUN npm install
13
+
14
+ # Uncomment the following lines if you want to use a secret at buildtime,
15
+ # for example to access your private npm packages
16
+ # RUN --mount=type=secret,id=HF_EXAMPLE_SECRET,mode=0444,required=true # $(cat /run/secrets/HF_EXAMPLE_SECRET)
17
+
18
+ # Rebuild the source code only when needed
19
+ FROM base AS builder
20
+ WORKDIR /app
21
+ COPY --from=deps /app/node_modules ./node_modules
22
+ COPY . .
23
+
24
+ # Next.js collects completely anonymous telemetry data about general usage.
25
+ # Learn more here: https://nextjs.org/telemetry
26
+ # Uncomment the following line in case you want to disable telemetry during the build.
27
+ # ENV NEXT_TELEMETRY_DISABLED 1
28
+
29
+ RUN npm run build
30
+
31
+ # Production image, copy all the files and run next
32
+ FROM base AS runner
33
+ WORKDIR /app
34
+
35
+ ENV NODE_ENV production
36
+ # Uncomment the following line in case you want to disable telemetry during runtime.
37
+ # ENV NEXT_TELEMETRY_DISABLED 1
38
+
39
+ RUN addgroup --system --gid 1001 nodejs
40
+ RUN adduser --system --uid 1001 nextjs
41
+
42
+ COPY --from=builder /app/public ./public
43
+
44
+ # Automatically leverage output traces to reduce image size
45
+ # https://nextjs.org/docs/advanced-features/output-file-tracing
46
+ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
47
+ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
48
+ COPY --from=builder --chown=nextjs:nodejs /app/.next/cache ./.next/cache
49
+ # COPY --from=builder --chown=nextjs:nodejs /app/.next/cache/fetch-cache ./.next/cache/fetch-cache
50
+
51
+ USER nextjs
52
+
53
+ EXPOSE 3000
54
+
55
+ ENV PORT 3000
56
+
57
+ CMD ["node", "server.js"]
public/index.html ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>To-Do List</title>
7
+ <link rel="stylesheet" href="styles.css">
8
+ </head>
9
+ <body>
10
+ <div class="container">
11
+ <h1>To-Do List</h1>
12
+ <TodoList />
13
+ </div>
14
+ </body>
15
+ </html>
public/styles.css ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ font-family: Arial, sans-serif;
3
+ margin: 0;
4
+ padding: 0;
5
+ }
6
+
7
+ .container {
8
+ max-width: 1200px;
9
+ margin: 0 auto;
10
+ padding: 20px;
11
+ }
12
+
13
+ .jumbotron {
14
+ background-color: #204070;
15
+ color: #fff;
16
+ padding: 20px;
17
+ border-radius: 5px;
18
+ margin-bottom: 20px;
19
+ }
20
+
21
+ .container h1 {
22
+ font-size: 24px;
23
+ margin-bottom: 10px;
24
+ }
25
+
26
+ .container h2 {
27
+ font-size: 18px;
28
+ margin-bottom: 10px;
29
+ }
src/components/Header.tsx ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import styles from '../styles/Header.module.css';
3
+
4
+ const Header = ({ title }) => {
5
+ return (
6
+ <header className={styles.header}>
7
+ <h1 className={styles.title}>{title}</h1>
8
+ </header>
9
+ );
10
+ };
11
+
12
+ export default Header;
src/components/Todo.tsx ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+
3
+ const Todo = ({ todo, onRemove }) => {
4
+ return (
5
+ <li key={todo.id}>
6
+ <div>{todo.name}</div>
7
+ <div className="actions">
8
+ <button className="btn btn-warning" onClick={() => onRemove(todo)}>
9
+ Remove
10
+ </button>
11
+ </div>
12
+ </li>
13
+ );
14
+ };
15
+
16
+ export default Todo;
src/components/TodoList.tsx ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState } from 'react';
2
+ import Todo from '../components/Todo';
3
+
4
+ const TodoList = () => {
5
+ const [todos, setTodos] = useState([]);
6
+
7
+ const addTodo = (todo) => {
8
+ setTodos([...todos, todo]);
9
+ };
10
+
11
+ const removeTodo = (todo) => {
12
+ setTodos(todos.filter((t) => t !== todo));
13
+ };
14
+
15
+ return (
16
+ <div className="todoList">
17
+ <h2 className="title">To-Do List</h2>
18
+ <ul>
19
+ {todos.map((todo) => (
20
+ <Todo key={todo.id} todo={todo} onRemove={() => removeTodo(todo)} />
21
+ ))}
22
+ </ul>
23
+ <form className="input-group input-symbol">
24
+ <input
25
+ type="text"
26
+ className="form-control"
27
+ placeholder="Add Todo"
28
+ aria-label="Add Todo"
29
+ aria-description="Enter todo name"
30
+ onSubmit={(e) => {
31
+ e.preventDefault();
32
+ addTodo({ id: uuid(), name: e.target.value, isCompleted: false });
33
+ e.target.value = '';
34
+ }}
35
+ />
36
+ <span className="input-group-btn"></span>
37
+ </form>
38
+ </div>
39
+ );
40
+ };
41
+
42
+ export default TodoList;
src/pages/index.tsx ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import Header from '../components/Header';
3
+ import TodoList from '../components/TodoList';
4
+
5
+ const HomePage = () => {
6
+ return (
7
+ <div>
8
+ <Header title="To-Do List" />
9
+ <TodoList />
10
+ </div>
11
+ );
12
+ };
13
+
14
+ export default HomePage;
src/styles/Header.module.css ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .header {
2
+ background-color: #204070;
3
+ padding: 10px;
4
+ text-align: center;
5
+ }
6
+
7
+ .title {
8
+ font-size: 18px;
9
+ margin-bottom: 20px;
10
+ }
11
+
12
+ .input-group {
13
+ margin-bottom: 20px;
14
+ }
15
+
16
+ /* Button */
17
+ .btn {
18
+ color: #fff;
19
+ background-color: #333;
20
+ padding: 8px 18px;
21
+ border: none;
22
+ border-radius: 4px;
23
+ cursor: pointer;
24
+ margin-right: 10px;
25
+ }
src/styles/Todo.module.css ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .todo {
2
+ padding: 10px;
3
+ border-bottom: 1px solid #ddd;
4
+ }
5
+
6
+ .name {
7
+ font-size: 16px;
8
+ }
9
+
10
+ .completed {
11
+ text-decoration: line-through;
12
+ }
src/styles/TodoList.module.css ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .todoList {
2
+ margin-top: 20px;
3
+ }
4
+
5
+ .title {
6
+ font-size: 24px;
7
+ margin-bottom: 20px;
8
+ text-align: center;
9
+ }
10
+
11
+ .input-group {
12
+ margin-bottom: 20px;
13
+ }
tsconfig.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "noEmit": true,
10
+ "esModuleInterop": true,
11
+ "module": "esnext",
12
+ "moduleResolution": "node",
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "jsx": "preserve",
16
+ "incremental": true,
17
+ "plugins": [
18
+ {
19
+ "name": "next"
20
+ }
21
+ ],
22
+ "paths": {
23
+ "@/*": ["./src/*"]
24
+ }
25
+ },
26
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
27
+ "exclude": ["node_modules"]
28
+ }