diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index ad9e555fc..da45397f2 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -1,15 +1,17 @@ name: Backend +permissions: read-all + on: push: paths: - - "backend/**" - - ".github/workflows/backend.yml" + - backend/** + - .github/workflows/backend.yml pull_request: types: [opened] paths: - - "backend/**" - - ".github/workflows/backend.yml" + - backend/** + - .github/workflows/backend.yml concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index d6d253b93..fea68d17c 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -1,15 +1,17 @@ name: CLI +permissions: read-all + on: push: paths: - - "cli/**" - - ".github/workflows/cli.yml" + - cli/** + - .github/workflows/cli.yml pull_request: types: [opened] paths: - - "cli/**" - - ".github/workflows/cli.yml" + - cli/** + - .github/workflows/cli.yml concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/mobile.yml b/.github/workflows/mobile.yml new file mode 100644 index 000000000..5f03fdd09 --- /dev/null +++ b/.github/workflows/mobile.yml @@ -0,0 +1,69 @@ +name: Mobile + +permissions: read-all + +on: + push: + paths: + - frontend/sac-mobile/** + - .github/workflows/mobile.yml + pull_request: + types: opened + paths: + - frontend/sac-mobile/** + - .github/workflows/mobile.yml + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x] + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: yarn + cache-dependency-path: frontend/sac-mobile/yarn.lock + + - name: Install dependencies + run: | + cd frontend/sac-mobile + yarn install + + - name: Lint + run: | + cd frontend/sac-mobile + yarn lint + + test: + name: Test + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x] + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: yarn + cache-dependency-path: frontend/sac-mobile/yarn.lock + + - name: Install dependencies + run: | + cd frontend/sac-mobile + yarn install + + - name: Test + run: | + cd frontend/sac-mobile + yarn test \ No newline at end of file diff --git a/.gitignore b/.gitignore index 46329301c..a24e4c1b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store .env sac-cli +node_modules .vscode -.trunk \ No newline at end of file +.trunk diff --git a/.trunk/.gitignore b/.trunk/.gitignore new file mode 100644 index 000000000..15966d087 --- /dev/null +++ b/.trunk/.gitignore @@ -0,0 +1,9 @@ +*out +*logs +*actions +*notifications +*tools +plugins +user_trunk.yaml +user.yaml +tmp diff --git a/.trunk/configs/.markdownlint.yaml b/.trunk/configs/.markdownlint.yaml new file mode 100644 index 000000000..fb940393d --- /dev/null +++ b/.trunk/configs/.markdownlint.yaml @@ -0,0 +1,10 @@ +# Autoformatter friendly markdownlint config (all formatting rules disabled) +default: true +blank_lines: false +bullet: false +html: false +indentation: false +line_length: false +spaces: false +url: false +whitespace: false diff --git a/.trunk/configs/.shellcheckrc b/.trunk/configs/.shellcheckrc new file mode 100644 index 000000000..8c7b1ada8 --- /dev/null +++ b/.trunk/configs/.shellcheckrc @@ -0,0 +1,7 @@ +enable=all +source-path=SCRIPTDIR +disable=SC2154 + +# If you're having issues with shellcheck following source, disable the errors via: +# disable=SC1090 +# disable=SC1091 diff --git a/.trunk/configs/.yamllint.yaml b/.trunk/configs/.yamllint.yaml new file mode 100644 index 000000000..4d444662d --- /dev/null +++ b/.trunk/configs/.yamllint.yaml @@ -0,0 +1,10 @@ +rules: + quoted-strings: + required: only-when-needed + extra-allowed: ["{|}"] + empty-values: + forbid-in-block-mappings: true + forbid-in-flow-mappings: true + key-duplicates: {} + octal-values: + forbid-implicit-octal: true diff --git a/.trunk/configs/svgo.config.js b/.trunk/configs/svgo.config.js new file mode 100644 index 000000000..b257d1349 --- /dev/null +++ b/.trunk/configs/svgo.config.js @@ -0,0 +1,14 @@ +module.exports = { + plugins: [ + { + name: "preset-default", + params: { + overrides: { + removeViewBox: false, // https://github.com/svg/svgo/issues/1128 + sortAttrs: true, + removeOffCanvasPaths: true, + }, + }, + }, + ], +}; diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml new file mode 100644 index 000000000..fcafbbf73 --- /dev/null +++ b/.trunk/trunk.yaml @@ -0,0 +1,43 @@ +# This file controls the behavior of Trunk: https://docs.trunk.io/cli +# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml +version: 0.1 +cli: + version: 1.19.0 +# Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins) +plugins: + sources: + - id: trunk + ref: v1.4.2 + uri: https://github.com/trunk-io/plugins +# Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes) +runtimes: + enabled: + - go@1.21.0 + - node@18.12.1 + - python@3.10.8 +# This is the section where you manage your linters. (https://docs.trunk.io/check/configuration) +lint: + disabled: + - checkov + enabled: + - actionlint@1.6.26 + - git-diff-check + - gofmt@1.20.4 + - golangci-lint@1.56.1 + - markdownlint@0.39.0 + - osv-scanner@1.6.2 + - oxipng@9.0.0 + - prettier@3.2.5 + - shellcheck@0.9.0 + - shfmt@3.6.0 + - svgo@3.2.0 + - trivy@0.49.1 + - trufflehog@3.67.5 + - yamllint@1.34.0 +actions: + disabled: + - trunk-announce + - trunk-check-pre-push + - trunk-fmt-pre-commit + enabled: + - trunk-upgrade-available diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7b2f62a13..29c91195d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -129,7 +129,7 @@ To install use `./install.sh` and then run `sac-cli` to see all commands. - ```console + ```console NAME: sac-cli - CLI for SAC @@ -138,24 +138,28 @@ COMMANDS: swagger, swag Updates the swagger documentation - be Run the backend test, t Runs tests - format, f Runs formatting tools - lint, l Runs linting tools help, h Shows a list of commands or help for one command + CI: + format, f Runs formatting tools + lint, l Runs linting tools + * can use --fix to fix linting errors for frontend Database Operations: - clean Remove databases used for testing - migrate Migrate the database, creating tables and relationships - insert, i Inserts mock data into the database - reset, r Resets the database, dropping all tables, clearing data, and re-running migrations + clean, c Remove databases used for testing + migrate, m Migrate the database, creating tables and relationships + reset, r Resets the database, dropping all tables, clearing data, and re-running migrations * can use --data to just reset data and not drop tables - drop, d Drop data with a migration or drops the entire database + insert, i Inserts mock data into the database + drop, d Drop data with a migration or drops the entire database * can use --data to just drop data and not drop tables + Development: + be Run the backend + fe Run the frontend + GLOBAL OPTIONS: --help, -h show help ``` - # Git Flow 1. **Create a new branch** diff --git a/README.md b/README.md index fb5635004..77977b676 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ Backend Workflow Status + + Mobile Workflow Status + 0 { return cli.Exit("Invalid arguments", 1) diff --git a/cli/commands/fe.go b/cli/commands/fe.go new file mode 100644 index 000000000..63d24fc82 --- /dev/null +++ b/cli/commands/fe.go @@ -0,0 +1,80 @@ +package commands + +import ( + "os" + "os/exec" + + _ "github.com/lib/pq" + "github.com/urfave/cli/v2" +) + +func RunFrontendCommand() *cli.Command { + command := cli.Command{ + Name: "fe", + Usage: "Run the frontend", + Category: "Development", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "target", + Aliases: []string{"t"}, + Value: "mobile", + Usage: "Run a specific frontend type (web or mobile)", + }, + &cli.StringFlag{ + Name: "platform", + Aliases: []string{"p"}, + Usage: "Run a specific platform for mobile frontend", + Value: "ios", + }, + }, + Action: func(c *cli.Context) error { + if c.Args().Len() > 0 { + return cli.Exit("Invalid arguments", 1) + } + + target := c.String("target") + if target != "web" && target != "mobile" { + return cli.Exit("Invalid frontend type: must be 'web' or 'mobile'", 1) + } + + err := RunFE(c.String("type"), c.String("platform")) + if err != nil { + return cli.Exit(err.Error(), 1) + } + + return nil + }, + } + + return &command +} + +func RunFE(feType string, platform string) error { + switch feType { + case "mobile": + return RunMobileFE(platform) + case "web": + return RunWebFE() + default: + return RunMobileFE(platform) + } +} + +func RunMobileFE(platform string) error { + mobileCmd := exec.Command("yarn", "run", platform) + mobileCmd.Dir = FRONTEND_DIR + "/sac-mobile" + + mobileCmd.Stdout = os.Stdout + mobileCmd.Stderr = os.Stderr + mobileCmd.Stdin = os.Stdin + + if err := mobileCmd.Run(); err != nil { + return err + } + + return nil +} + +func RunWebFE() error { + return nil +} diff --git a/cli/commands/format.go b/cli/commands/format.go index cfaa9ddea..811032556 100644 --- a/cli/commands/format.go +++ b/cli/commands/format.go @@ -2,88 +2,84 @@ package commands import ( "fmt" + "os" "os/exec" - "sync" "github.com/urfave/cli/v2" ) func FormatCommand() *cli.Command { command := cli.Command{ - Name: "format", - Usage: "Runs formatting tools", - Aliases: []string{"f"}, - Flags: []cli.Flag{ - &cli.StringFlag{ + Name: "format", + Aliases: []string{"f"}, + Usage: "Runs formatting tools", + Category: "CI", + Subcommands: []*cli.Command{ + { Name: "frontend", + Usage: "Format the frontend", Aliases: []string{"f"}, - Value: "", - Usage: "Formats a specific frontend folder", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "target", + Aliases: []string{"t"}, + Value: "mobile", + Usage: "Format a specific frontend type (web or mobile)", + }, + }, + Action: func(c *cli.Context) error { + if c.Args().Len() > 0 { + return cli.Exit("Invalid arguments", 1) + } + + target := c.String("target") + if target != "web" && target != "mobile" { + return cli.Exit("Invalid frontend type: must be 'web' or 'mobile'", 1) + } + + err := FormatFrontend(target) + if err != nil { + return cli.Exit(err.Error(), 1) + } + + return nil + }, }, - &cli.BoolFlag{ + { Name: "backend", + Usage: "Format the backend", Aliases: []string{"b"}, - Usage: "Formats the backend", + Action: func(c *cli.Context) error { + if c.Args().Len() > 0 { + return cli.Exit("Invalid arguments", 1) + } + + err := FormatBackend() + if err != nil { + return cli.Exit(err.Error(), 1) + } + + return nil + }, }, }, - Action: func(c *cli.Context) error { - if c.Args().Len() > 0 { - return cli.Exit("Invalid arguments", 1) - } - - if c.String("frontend") == "" && !c.Bool("backend") { - return cli.Exit("Must specify frontend or backend", 1) - } - - folder := c.String("frontend") - runFrontend := folder != "" - runBackend := c.Bool("backend") - - err := Format(folder, runFrontend, runBackend) - if err != nil { - return cli.Exit(err.Error(), 1) - } - - return nil - }, } return &command } -func Format(folder string, runFrontend bool, runBackend bool) error { - var wg sync.WaitGroup - - // Start the backend if specified - if runBackend { - wg.Add(1) - go func() { - defer wg.Done() - err := BackendFormat() - if err != nil { - fmt.Println(err) - } - }() +func FormatFrontend(target string) error { + switch target { + case "web": + return FormatWeb() + case "mobile": + return FormatMobile() + default: + return FormatMobile() } - - // Start the frontend if specified - if runFrontend { - wg.Add(1) - go func() { - defer wg.Done() - err := FrontendFormat(folder) - if err != nil { - fmt.Println(err) - } - }() - } - - wg.Wait() - - return nil } -func BackendFormat() error { +func FormatBackend() error { fmt.Println("Formatting backend") cmd := exec.Command("gofumpt", "-l", "-w", ".") @@ -98,7 +94,21 @@ func BackendFormat() error { return nil } -func FrontendFormat(folder string) error { - fmt.Println("UNIMPLEMENTED") +func FormatWeb() error { + return nil +} + +func FormatMobile() error { + mobileCmd := exec.Command("yarn", "run", "format") + mobileCmd.Dir = FRONTEND_DIR + "/sac-mobile" + + mobileCmd.Stdout = os.Stdout + mobileCmd.Stderr = os.Stderr + mobileCmd.Stdin = os.Stdin + + if err := mobileCmd.Run(); err != nil { + return err + } + return nil } diff --git a/cli/commands/lint.go b/cli/commands/lint.go index 921a45eb8..f2eaeee9c 100644 --- a/cli/commands/lint.go +++ b/cli/commands/lint.go @@ -2,101 +2,91 @@ package commands import ( "fmt" + "os" "os/exec" - "sync" "github.com/urfave/cli/v2" ) func LintCommand() *cli.Command { command := cli.Command{ - Name: "lint", - Aliases: []string{"l"}, - Usage: "Runs linting tools", - Flags: []cli.Flag{ - &cli.StringFlag{ + Name: "lint", + Aliases: []string{"l"}, + Usage: "Runs linting tools", + Category: "CI", + Subcommands: []*cli.Command{ + { Name: "frontend", + Usage: "Lint the frontend", Aliases: []string{"f"}, - Value: "", - Usage: "Lint a specific frontend folder", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "target", + Aliases: []string{"t"}, + Value: "mobile", + Usage: "Lint a specific frontend type (web or mobile)", + }, + &cli.BoolFlag{ + Name: "fix", + Aliases: []string{"f"}, + Usage: "Fix linting errors", + }, + }, + Action: func(c *cli.Context) error { + if c.Args().Len() > 0 { + return cli.Exit("Invalid arguments", 1) + } + + target := c.String("target") + if target != "web" && target != "mobile" { + return cli.Exit("Invalid frontend type: must be 'web' or 'mobile'", 1) + } + + fix := c.Bool("fix") + + err := LintFrontend(target, fix) + if err != nil { + return cli.Exit(err.Error(), 1) + } + + return nil + }, }, - &cli.BoolFlag{ + { Name: "backend", - Aliases: []string{"b"}, Usage: "Lint the backend", + Aliases: []string{"b"}, + Action: func(c *cli.Context) error { + if c.Args().Len() > 0 { + return cli.Exit("Invalid arguments", 1) + } + + err := LintBackend() + if err != nil { + return cli.Exit(err.Error(), 1) + } + + return nil + }, }, }, - Action: func(c *cli.Context) error { - if c.Args().Len() > 0 { - return cli.Exit("Invalid arguments", 1) - } - - if c.String("frontend") == "" && !c.Bool("backend") { - return cli.Exit("Must specify frontend or backend", 1) - } - - folder := c.String("frontend") - runFrontend := folder != "" - runBackend := c.Bool("backend") - - err := Lint(folder, runFrontend, runBackend) - if err != nil { - return cli.Exit(err.Error(), 1) - } - - return nil - }, } return &command } -func Lint(folder string, runFrontend bool, runBackend bool) error { - var wg sync.WaitGroup - errChan := make(chan error, 1) - var errOccurred bool // Flag to indicate whether an error has occurred - - // Start the backend if specified - if runBackend && !errOccurred { - wg.Add(1) - go func() { - defer wg.Done() - err := BackendLint() - if err != nil { - errChan <- err - errOccurred = true - } - }() - } - - // Start the frontend if specified - if runFrontend && !errOccurred { - wg.Add(1) - go func() { - defer wg.Done() - err := FrontendLint(folder) - if err != nil { - errChan <- err - errOccurred = true - } - }() - } - - go func() { - wg.Wait() - close(errChan) - }() - - for err := range errChan { - if err != nil { - return err - } +func LintFrontend(target string, fix bool) error { + switch target { + case "web": + return LintWeb(fix) + case "mobile": + return LintMobile(fix) + default: + return LintMobile(fix) } - - return nil } -func BackendLint() error { +func LintBackend() error { fmt.Println("Linting backend") cmd := exec.Command("golangci-lint", "run", "--fix") @@ -112,7 +102,26 @@ func BackendLint() error { return nil } -func FrontendLint(folder string) error { - fmt.Println("UNIMPLEMENTED") +func LintWeb(fix bool) error { + return nil +} + +func LintMobile(fix bool) error { + var mobileCmd *exec.Cmd + if fix { + mobileCmd = exec.Command("yarn", "run", "lint", "--fix") + } else { + mobileCmd = exec.Command("yarn", "run", "lint") + } + mobileCmd.Dir = FRONTEND_DIR + "/sac-mobile" + + mobileCmd.Stdout = os.Stdout + mobileCmd.Stderr = os.Stderr + mobileCmd.Stdin = os.Stdin + + if err := mobileCmd.Run(); err != nil { + return err + } + return nil } diff --git a/cli/commands/migrate.go b/cli/commands/migrate.go index 7aa7d8aa4..672b8be4d 100644 --- a/cli/commands/migrate.go +++ b/cli/commands/migrate.go @@ -10,6 +10,7 @@ import ( func MigrateCommand() *cli.Command { command := cli.Command{ Name: "migrate", + Aliases: []string{"m"}, Usage: "Migrate the database, creating tables and relationships", Category: "Database Operations", Action: func(c *cli.Context) error { diff --git a/cli/go.mod b/cli/go.mod index ef0743b53..f36f981fe 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -13,7 +13,7 @@ require ( github.com/awnumar/memguard v0.22.4 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/garrettladley/mattress v0.2.0 // indirect + github.com/garrettladley/mattress v0.2.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -30,10 +30,11 @@ require ( github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/crypto v0.18.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/cli/go.sum b/cli/go.sum deleted file mode 100644 index df51b4c76..000000000 --- a/cli/go.sum +++ /dev/null @@ -1,90 +0,0 @@ -github.com/GenerateNU/sac/backend v0.0.0-20240208151800-c7c93bbd1bb7 h1:PiMBcw9KZxoH1pSfyyQsiisyemef2TwCG/WSSYailYw= -github.com/GenerateNU/sac/backend v0.0.0-20240208151800-c7c93bbd1bb7/go.mod h1:x3FsVBrEq6k60rGtxaOLg3UJ35BIOh6pyjRdGdte5bo= -github.com/awnumar/memcall v0.2.0 h1:sRaogqExTOOkkNwO9pzJsL8jrOV29UuUW7teRMfbqtI= -github.com/awnumar/memcall v0.2.0/go.mod h1:S911igBPR9CThzd/hYQQmTc9SWNu3ZHIlCGaWsWsoJo= -github.com/awnumar/memguard v0.22.4 h1:1PLgKcgGPeExPHL8dCOWGVjIbQUBgJv9OL0F/yE1PqQ= -github.com/awnumar/memguard v0.22.4/go.mod h1:+APmZGThMBWjnMlKiSM1X7MVpbIVewen2MTkqWkA/zE= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/garrettladley/mattress v0.2.0 h1:+XUdsv9NO2s4JL+8exvAFziw0b1kv/0WlQo2Dlxat+w= -github.com/garrettladley/mattress v0.2.0/go.mod h1:OWKIRc9wC3gtD3Ng/nUuNEiR1TJvRYLmn/KZYw9nl5Q= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= -github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= -github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= -github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= -github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= -github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cli/main.go b/cli/main.go index f9b41303d..abf20d447 100755 --- a/cli/main.go +++ b/cli/main.go @@ -20,6 +20,7 @@ func main() { commands.InsertCommand(), commands.DropCommand(), commands.RunBackendCommand(), + commands.RunFrontendCommand(), commands.TestCommand(), // TODO: frontend tests commands.FormatCommand(), commands.LintCommand(), diff --git a/frontend/STYLEGUIDE.md b/frontend/STYLEGUIDE.md index 1573ab75b..7a978c3c4 100644 --- a/frontend/STYLEGUIDE.md +++ b/frontend/STYLEGUIDE.md @@ -5,7 +5,7 @@ 1. [General](#general) 2. [Naming](#naming) 3. [Imports](#imports) -4. [Components](#components) +4. [Components](#components-and-screens--pages) ## General diff --git a/frontend/sac-mobile/.eslintrc.js b/frontend/sac-mobile/.eslintrc.js index 1679505ff..2441767bf 100644 --- a/frontend/sac-mobile/.eslintrc.js +++ b/frontend/sac-mobile/.eslintrc.js @@ -1,12 +1,17 @@ module.exports = { - root: true, - extends: ['@react-native-community', 'plugin:prettier/recommended'], - plugins: ['prettier', 'jest'], - rules: { - 'prettier/prettier': 'error', - 'react/react-in-jsx-scope': 'off' - }, - env: { - 'jest/globals': true - } + root: true, + extends: ['@react-native-community', 'plugin:prettier/recommended'], + plugins: ['prettier', 'jest'], + rules: { + 'prettier/prettier': 'error', + 'react/react-in-jsx-scope': 'off' + }, + env: { + 'jest/globals': true + }, + parserOptions: { + babelOptions: { + configFile: './babel.config.js' + } + } }; diff --git a/frontend/sac-mobile/.gitignore b/frontend/sac-mobile/.gitignore index 1b35333e7..9af0481f5 100644 --- a/frontend/sac-mobile/.gitignore +++ b/frontend/sac-mobile/.gitignore @@ -3,6 +3,8 @@ # dependencies node_modules/ +coverage/ + # Expo .expo/ dist/ @@ -34,7 +36,6 @@ yarn-error.* # typescript *.tsbuildinfo - # @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb # The following patterns were generated by expo-cli diff --git a/frontend/sac-mobile/.prettierrc b/frontend/sac-mobile/.prettierrc index 0c8098f06..e10202567 100644 --- a/frontend/sac-mobile/.prettierrc +++ b/frontend/sac-mobile/.prettierrc @@ -1,21 +1,22 @@ { - "plugins": ["@trivago/prettier-plugin-sort-imports"], - "printWidth": 80, - "tabWidth": 2, - "semi": true, - "singleQuote": true, - "trailingComma": "none", - "bracketSpacing": true, - "arrowParens": "always", - "importOrder": [ - "^@core/(.*)$", - "^@server/(.*)$", - "^@ui/(.*)$", - "^lodash", - "^react", - "^rxjs", - "^[./]" - ], - "importOrderSeparation": true, - "importOrderSortSpecifiers": true + "plugins": ["@trivago/prettier-plugin-sort-imports"], + "printWidth": 80, + "tabWidth": 4, + "semi": true, + "singleQuote": true, + "trailingComma": "none", + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "auto", + "importOrder": [ + "^react", + "^react-native", + "^expo", + "", + "^@/", + "^src", + "^[./]" + ], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true } diff --git a/frontend/sac-mobile/app.json b/frontend/sac-mobile/app.json index 7744f042f..ff0952b83 100644 --- a/frontend/sac-mobile/app.json +++ b/frontend/sac-mobile/app.json @@ -1,50 +1,47 @@ { - "expo": { - "name": "sac-mobile", - "slug": "student-activity-calendar", - "version": "1.0.0", - "orientation": "portrait", - "icon": "./assets/images/icon.png", - "scheme": "myapp", - "userInterfaceStyle": "automatic", - "splash": { - "image": "./assets/images/splash.png", - "resizeMode": "contain", - "backgroundColor": "#ffffff" - }, - "assetBundlePatterns": [ - "**/*" - ], - "ios": { - "supportsTablet": true - }, - "android": { - "adaptiveIcon": { - "foregroundImage": "./assets/images/adaptive-icon.png", - "backgroundColor": "#ffffff" - } - }, - "web": { - "bundler": "metro", - "output": "static", - "favicon": "./assets/images/favicon.png" - }, - "plugins": [ - "expo-router" - ], - "experiments": { - "typedRoutes": true, - "tsconfigPaths": true - }, - "extra": { - "clerkPublishableKey": "pk_test_YnJpZ2h0LWxpb24tOC5jbGVyay5hY2NvdW50cy5kZXYk", - "router": { - "origin": false - }, - "eas": { - "projectId": "9cfc60bc-2788-4837-9895-3fe0afdc13c5" - } - }, - "owner": "generatesac" - } -} \ No newline at end of file + "expo": { + "name": "sac-mobile", + "slug": "student-activity-calendar", + "version": "1.0.0", + "orientation": "portrait", + "icon": "./assets/images/icon.png", + "scheme": "myapp", + "userInterfaceStyle": "automatic", + "splash": { + "image": "./assets/images/splash.png", + "resizeMode": "contain", + "backgroundColor": "#ffffff" + }, + "assetBundlePatterns": ["**/*"], + "ios": { + "supportsTablet": true, + "bundleIdentifier": "com.generatesac.studentactivitycalendar" + }, + "android": { + "adaptiveIcon": { + "foregroundImage": "./assets/images/adaptive-icon.png", + "backgroundColor": "#ffffff" + }, + "package": "com.generatesac.studentactivitycalendar" + }, + "web": { + "bundler": "metro", + "output": "static", + "favicon": "./assets/images/favicon.png" + }, + "plugins": ["expo-router"], + "experiments": { + "typedRoutes": true, + "tsconfigPaths": true + }, + "extra": { + "router": { + "origin": false + }, + "eas": { + "projectId": "9cfc60bc-2788-4837-9895-3fe0afdc13c5" + } + }, + "owner": "generatesac" + } +} diff --git a/frontend/sac-mobile/app/(app)/_layout.tsx b/frontend/sac-mobile/app/(app)/_layout.tsx new file mode 100644 index 000000000..bfc0d2c00 --- /dev/null +++ b/frontend/sac-mobile/app/(app)/_layout.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +import { Tabs } from 'expo-router'; + +import { MaterialCommunityIcons } from '@expo/vector-icons'; + +const HomeTabBarIcon = ({ color }: { color: string }) => ( + +); + +const AppLayout = () => { + return ( + + + + ); +}; + +export default AppLayout; diff --git a/frontend/sac-mobile/app/(app)/index.tsx b/frontend/sac-mobile/app/(app)/index.tsx new file mode 100644 index 000000000..75e348171 --- /dev/null +++ b/frontend/sac-mobile/app/(app)/index.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { Button, Text, View } from 'react-native'; + +import { useAuthStore } from '@/hooks/use-auth'; + +const Home = () => { + const { logout } = useAuthStore(); + return ( + +