diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..19a8430 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,26 @@ +# flyctl launch added from .gitignore +# Logs +**\logs +**\*.log +**\npm-debug.log* +**\yarn-debug.log* +**\yarn-error.log* +**\pnpm-debug.log* +**\lerna-debug.log* + +**\node_modules +**\dist +**\dist-ssr +**\*.local + +# Editor directories and files +**\.vscode\* +!**\.vscode\extensions.json +**\.idea +**\.DS_Store +**\*.suo +**\*.ntvs* +**\*.njsproj +**\*.sln +**\*.sw? +fly.toml diff --git a/.github/workflows/fly-deploy.yml b/.github/workflows/fly-deploy.yml new file mode 100644 index 0000000..b0c246e --- /dev/null +++ b/.github/workflows/fly-deploy.yml @@ -0,0 +1,18 @@ +# See https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/ + +name: Fly Deploy +on: + push: + branches: + - main +jobs: + deploy: + name: Deploy app + runs-on: ubuntu-latest + concurrency: deploy-group # optional: ensure only one action runs at a time + steps: + - uses: actions/checkout@v4 + - uses: superfly/flyctl-actions/setup-flyctl@master + - run: flyctl deploy --remote-only + env: + FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..be88841 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +# Build Stage +FROM node:18 AS build + +WORKDIR /app + +COPY package*.json ./ +RUN npm install + +COPY . . +RUN npm run build + +# Serve Stage +FROM nginx:stable-alpine + +# Copy built React files into nginx public folder +COPY --from=build /app/dist /usr/share/nginx/html + +# Remove default nginx config +RUN rm /etc/nginx/conf.d/default.conf + +# Add your own nginx config +COPY nginx.conf /etc/nginx/conf.d + +# Expose port 80 +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/fly.toml b/fly.toml new file mode 100644 index 0000000..c7c0a90 --- /dev/null +++ b/fly.toml @@ -0,0 +1,42 @@ +# fly.toml app configuration file generated for bytecamp-web on 2025-04-21T13:40:11-07:00 +# +# See https://fly.io/docs/reference/configuration/ for information about how to use this file. +# + +app = 'bytecamp-web' +primary_region = 'sea' + +[build] + +[env] + PORT = '8080' + +[http_service] + internal_port = 80 + force_https = true + auto_stop_machines = 'stop' + auto_start_machines = true + min_machines_running = 0 + processes = ['app'] + +[[services]] + protocol = 'tcp' + internal_port = 8080 + + [[services.ports]] + port = 80 + handlers = ['http'] + + [[services.ports]] + port = 443 + handlers = ['tls', 'http'] + + [[services.tcp_checks]] + interval = '10s' + timeout = '2s' + grace_period = '5s' + +[[vm]] + memory = '1gb' + cpu_kind = 'shared' + cpus = 1 diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..567d531 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,11 @@ +server { + listen 80; + server_name localhost; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri /index.html; + } +} diff --git a/public/images/grid-background.jpg b/public/images/grid-background.jpg new file mode 100644 index 0000000..e6f0e84 Binary files /dev/null and b/public/images/grid-background.jpg differ diff --git a/src/components/Header.jsx b/src/components/Header.jsx index deb40e6..e456c92 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -17,6 +17,9 @@ const Header = () => {
  • Login
  • +
  • + Assignment +
  • diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index a705b7e..7b94987 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -1,19 +1,41 @@ -import React from 'react' -import '../scss/styles.scss' -import '../scss/components/_navbar.scss' +import React from "react"; +import "../scss/styles.scss"; +import "../scss/components/_navbar.scss"; +import { Link } from "react-router-dom"; const Navbar = () => { return ( - ) -} + ); +}; -export default Navbar \ No newline at end of file +export default Navbar; diff --git a/src/main.jsx b/src/main.jsx index b80fa22..f7abc3f 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -5,11 +5,10 @@ import "./scss/styles.scss"; import Navbar from "./components/Navbar"; import Hero from "./components/Hero"; import Services from "./components/Services"; +import Header from "./components/Header"; createRoot(document.getElementById("root")).render( - - ); diff --git a/src/pages/LoginPage.jsx b/src/pages/LoginPage.jsx index e7b1385..e3b4712 100644 --- a/src/pages/LoginPage.jsx +++ b/src/pages/LoginPage.jsx @@ -8,7 +8,7 @@ const LoginPage = () => { const [type, setType] = useState("signIn"); useEffect(() => { - document.title = "Login / Sign Up"; + document.title = "Login / Instructor"; }, []); const handleOnClick = (text) => { @@ -23,7 +23,7 @@ const LoginPage = () => { return (
    -

    Sign In/Sign Up

    +

    Student/Instructor

    @@ -31,26 +31,24 @@ const LoginPage = () => {

    Welcome Back!

    -

    - To keep connected with us please login with your personal info -

    +

    Please login with your personal info

    -

    Hello, Friend!

    -

    Enter your personal details and start journey with us

    +

    Hello, Instructor!

    +

    Please enter your personal details here

    diff --git a/src/pages/SignIn.jsx b/src/pages/SignIn.jsx index b6a203a..9976eb5 100644 --- a/src/pages/SignIn.jsx +++ b/src/pages/SignIn.jsx @@ -31,22 +31,16 @@ function SignInForm() { return (
    -

    Sign in

    -
    - - - +

    Student

    + {/* - or use your account +
    */} + - Forgot your password? +
    diff --git a/src/pages/SignUp.jsx b/src/pages/SignUp.jsx index 64d9042..4617f1d 100644 --- a/src/pages/SignUp.jsx +++ b/src/pages/SignUp.jsx @@ -18,7 +18,7 @@ function SignUpForm() { const { name, email, password } = state; alert( - `You are sign up with name: ${name} email: ${email} and password: ${password}` + `You are signed in with name: ${name} email: ${email} and password: ${password}` ); for (const key in state) { @@ -29,20 +29,18 @@ function SignUpForm() { } }; + const googleAuth = () => { + window.open("https://byte-camp-auth-service.fly.dev/auth/google", "_self"); + }; + return (
    -

    Create Account

    +

    Instructor

    or use your email for registration - +
    ); diff --git a/src/routers/AppRouter.jsx b/src/routers/AppRouter.jsx index 0ca9c86..5899d8f 100644 --- a/src/routers/AppRouter.jsx +++ b/src/routers/AppRouter.jsx @@ -11,6 +11,7 @@ import HomePage from "../pages/HomePage"; import LoginPage from "../pages/LoginPage"; import PageCodeEditor from "../pages/CodeEditor"; import PageNotFound from "../pages/PageNotFound"; +import AssignmentPage from "../pages/AssignmentPage"; import Hero from "../components/Hero"; import Navbar from "../components/Navbar"; import Services from "../components/Services"; @@ -20,16 +21,14 @@ const AppRouter = () => { return (
    - {/*
    */} - - - + + } /> @@ -43,7 +42,7 @@ const AppRouter = () => { /> } /> @@ -53,7 +52,7 @@ const AppRouter = () => { } /> - +
    diff --git a/src/scss/page/_login.scss b/src/scss/page/_login.scss index d80b2f5..145d026 100644 --- a/src/scss/page/_login.scss +++ b/src/scss/page/_login.scss @@ -1,3 +1,21 @@ +// .login-page { +// min-height: 100vh; +// display: flex; +// justify-content: center; +// align-items: center; + +// background-image: url("../../../public/images/grid-background.png"); +// background-size: cover; +// background-position: center; +// background-repeat: no-repeat; +// background-attachment: fixed; + +// section { +// width: 100%; +// max-width: 800px; +// padding: 20px; +// } +// } .App { font-family: sans-serif; text-align: center; @@ -10,7 +28,12 @@ } body { - background: #f6f5f7; + background: transparent; + background-image: url("../../../public/images/grid-background.jpg"); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + background-attachment: fixed; display: flex; justify-content: center; align-items: center; @@ -27,6 +50,8 @@ h1 { h2 { text-align: center; + color: #fff; + text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5); } p { @@ -227,8 +252,8 @@ input { justify-content: center; align-items: center; margin: 0 5px; - height: 40px; - width: 40px; + height: 60px; + width: 60px; } footer { diff --git a/src/scss/page/assignment.scss b/src/scss/page/assignment.scss new file mode 100644 index 0000000..04c9baf --- /dev/null +++ b/src/scss/page/assignment.scss @@ -0,0 +1,198 @@ +// Assignment Page Styling + +.assignment-page { + display: flex; + flex-direction: column; + align-items: center; + padding: 2rem; + + section { + width: 100%; + max-width: 900px; + } + + .assignment-header { + margin-bottom: 2rem; + border-bottom: 1px solid #e0e0e0; + padding-bottom: 1rem; + + h2 { + font-size: 3rem; + margin-bottom: 1rem; + color: #ffffff; + } + + .due-date { + color: #c6c6c6; + font-size: 1.2rem; + } + } + + .assignment-container { + background-color: #fff; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + padding: 2rem; + + .assignment-info { + margin-bottom: 2rem; + + h3 { + font-size: 1.4rem; + margin-bottom: 0.5rem; + color: #333; + } + + .files-count { + font-size: 1rem; + margin-bottom: 0.5rem; + } + + .submission-note { + font-size: 0.9rem; + color: #666; + } + } + + .file-upload-section { + margin-bottom: 2rem; + + .upload-buttons { + display: flex; + gap: 1rem; + margin-bottom: 1.5rem; + flex-wrap: wrap; + + .file-upload-btn, + .record-audio-btn, + .record-video-btn { + background-color: #f5f5f5; + border: 1px solid #ddd; + border-radius: 4px; + padding: 0.6rem 1rem; + cursor: pointer; + font-size: 0.9rem; + transition: all 0.2s ease; + color: #333; + + &:hover { + background-color: #e9e9e9; + } + } + } + + .files-list { + background-color: #f9f9f9; + border-radius: 6px; + padding: 1rem; + + h4 { + margin-bottom: 0.8rem; + font-size: 1rem; + } + + ul { + list-style: none; + padding: 0; + + .file-item { + display: flex; + align-items: center; + padding: 0.5rem 0; + border-bottom: 1px solid #eee; + + &:last-child { + border-bottom: none; + } + + .file-name { + flex-grow: 1; + font-weight: 500; + } + + .file-size { + color: #777; + margin: 0 1rem; + font-size: 0.8rem; + } + + .remove-file-btn { + background-color: transparent; + border: none; + color: #ff5252; + cursor: pointer; + font-size: 0.8rem; + padding: 0.3rem 0.6rem; + + &:hover { + text-decoration: underline; + } + } + } + } + } + } + + .comments-section { + margin-bottom: 2rem; + + h4 { + margin-bottom: 0.8rem; + font-size: 1rem; + } + + textarea { + width: 100%; + border: 1px solid #ddd; + border-radius: 4px; + padding: 0.8rem; + font-family: inherit; + resize: vertical; + + &:focus { + outline: none; + border-color: #4a90e2; + } + } + } + + .submission-buttons { + display: flex; + gap: 1rem; + + .submit-btn, + .cancel-btn { + padding: 0.7rem 1.5rem; + border-radius: 4px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + } + + .submit-btn { + background-color: #4a90e2; + color: white; + border: none; + + &:hover { + background-color: #3a7bc8; + } + + &:disabled { + background-color: #a0c3e8; + cursor: not-allowed; + } + } + + .cancel-btn { + background-color: transparent; + border: 1px solid #ddd; + color: #666; + + &:hover { + background-color: #f5f5f5; + } + } + } + } +} diff --git a/src/scss/styles.scss b/src/scss/styles.scss index 6379fda..aeb88bb 100644 --- a/src/scss/styles.scss +++ b/src/scss/styles.scss @@ -13,6 +13,7 @@ @use "./page//home"; @use "./page//login"; @use "./page/code_editor"; +@use "./page/assignment"; // Utilities @use "./utilities/utility-classes";