diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 28d9040..0000000 --- a/.editorconfig +++ /dev/null @@ -1,12 +0,0 @@ -# EditorConfig is awesome: https://EditorConfig.org - -# top-most EditorConfig file -root = true - -[*] -indent_style = tab -indent_size = 4 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = false -insert_final_newline = true \ No newline at end of file diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..08d320d --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,47 @@ +# Code of Conduct +## Introduction + +Our open source project is committed to creating a welcoming and inclusive environment for everyone who participates. We value diversity and strive to ensure that our community remains respectful and supportive. By participating in this project, you agree to abide by this Code of Conduct. +Expected Behavior + +## Everyone in our community is expected to: + +- Be Respectful: Treat all individuals with respect, and be considerate of different viewpoints and experiences. +- Be Inclusive: Encourage participation from people of diverse backgrounds and experiences. +- Communicate Clearly: Use clear and professional language in all communications, whether they are in comments, issues, or discussions. +- Give Constructive Feedback: Provide feedback that is constructive and aimed at improving the project, rather than criticizing individuals personally. +- Acknowledge Contributions: Recognize and respect the contributions and ideas of others. + +## Unacceptable Behavior + +The following behaviors are not tolerated: + +- Harassment: Engaging in discriminatory, harassing, or threatening behavior. This includes, but is not limited to, offensive comments related to gender, sexual orientation, disability, physical appearance, race, or religion. +- Personal Attacks: Making personal attacks or derogatory comments about others. +- Disruptive Behavior: Engaging in disruptive behavior that undermines the project or community, such as spamming or trolling. +- Abuse of Authority: Using a position of power or influence to coerce or intimidate others. + +## Reporting Issues + +If you encounter or witness behavior that violates this Code of Conduct, please report it to the project maintainers. You can do so by: + +- Opening an Issue: File an issue on our GitHub repository with a description of the behavior and any relevant context. +- Contacting Maintainers Directly: Reach out via email or direct message to one of the project maintainers. Contact information can be found in the MAINTAINERS.md file. + +All reports will be reviewed and investigated promptly and fairly. Confidentiality will be maintained to the extent possible. + +## Enforcement + +Violations of the Code of Conduct may result in a range of responses, from a warning to temporary or permanent removal from the project. The severity of the response will be proportional to the nature of the violation. + +The project maintainers will handle enforcement with discretion and transparency. Our goal is to address issues fairly and ensure a positive experience for everyone involved. + +## Acknowledgements + +This Code of Conduct is inspired by the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1. + +## Changes + +This Code of Conduct may be updated periodically to reflect changes in the project or community needs. Please check this document regularly for any updates. + +Thank you for helping to make our project a welcoming and inclusive space! \ No newline at end of file diff --git a/.github/CONTRIBUTING b/.github/CONTRIBUTING new file mode 100644 index 0000000..10a7b75 --- /dev/null +++ b/.github/CONTRIBUTING @@ -0,0 +1,50 @@ +# Contributing to sharedway + +Thank you for considering contributing to sharedway! We welcome contributions of all kinds, whether it's code, documentation, or simply feedback. This guide will help you get started. + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [Getting Started](#getting-started) +- [Reporting Issues](#reporting-issues) +- [Style Guide](#style-guide) +- [Questions?](#questions) + +## Code of Conduct + +Please read and follow our [Code of Conduct](CODE_OF_CONDUCT.md). We are committed to creating a welcoming and inclusive environment for all contributors. + +## Getting Started + +1. **Fork the Repository**: Click the "Fork" button at the top-right corner of this page. +2. **Clone Your Fork**: Clone your forked repository to your local machine. + ```bash + git clone https://github.com/darklight9811/sharedway.git + ``` +3. **Create a Branch**: Create a new branch for your changes. + ```bash + git checkout -b your-branch-name + ``` +4. **Install Dependencies**: Run `bun install` to install all required dependencies. +5. **Make Your Changes**: Implement your feature or fix. + +## Reporting Issues +If you encounter a bug or have a feature request, please open an issue on GitHub. Provide as much detail as possible, including: +- A clear description of the problem or request +- Steps to reproduce the issue +- Expected and actual results +- Any relevant screenshots or logs + +## Style Guide + +Please follow our project's style guide to ensure consistency. Key points include: + +- Use descriptive commit messages +- Run `biomejs` linter and formatter +- Write clear, concise documentation + +## Questions? + +If you have any questions, feel free to reach out via discussions or contact us directly at rafael.correa@yamiassu.com.br + +Thank you for contributing to sharedway! \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/1.bug_report.yml b/.github/ISSUE_TEMPLATE/1.bug_report.yml new file mode 100644 index 0000000..545e1b2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1.bug_report.yml @@ -0,0 +1,85 @@ +name: Report an issue +description: Report an issue. +labels: ['bug'] +body: + - type: markdown + attributes: + value: | + This template is used for reporting a issue with sharedway. + + Feature requests should be opened in [discussions](https://github.com/darklight9811/sharedway/discussions/new?category=ideas). + + Before opening a new issue, please do a [search](https://github.com/darkligh9811/sharedway/issues) of existing issues and :+1: upvote the existing issue instead. This will result in a quicker resolution. + - type: textarea + attributes: + label: To Reproduce + description: A step-by-step description of how to reproduce the issue, based on the linked reproduction. Screenshots can be provided in the issue body below. If using code blocks, make sure that [syntax highlighting is correct](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting) and double check that the rendered preview is not broken. + placeholder: | + 1. Start the application in development (bun dev --filter=app) + 2. Click X + 3. Y will happen + validations: + required: true + - type: textarea + attributes: + label: Current vs. Expected behavior + description: | + A clear and concise description of what the bug is (e.g., screenshots, logs, etc.), and what you expected to happen. + + **Skipping this/failure to provide complete information of the bug will result in the issue being closed.** + placeholder: 'Following the steps from the previous section, I expected A to happen, but I observed B instead.' + validations: + required: true + - type: textarea + attributes: + label: Provide environment information + description: Please run `next info` in the app directory of the project and paste the results. You might need to use `npx --no-install next info` if next is not in the current PATH. + render: bash + placeholder: | + Operating System: + Platform: darwin + Arch: arm64 + Version: Darwin Kernel Version 22.5.0 + Binaries: + Node: 18.17.1 + npm: 9.5.1 + Yarn: 1.22.19 + pnpm: N/A + Relevant Packages: + next: 13.4.20 + eslint-config-next: 13.4.20 + react: 18.2.0 + react-dom: 18.2.0 + typescript: 5.2.2 + Next.js Config: + output: N/A + validations: + required: true + - type: dropdown + attributes: + label: Which area(s) are affected? (Select all that apply) + multiple: true + options: + - 'Not sure' + - 'Services' + - 'Frontend' + - 'Design System' + - 'API' + - 'Deployment' + - 'Development' + + validations: + required: true + validations: + required: true + - type: markdown + attributes: + value: | + Another way you can help the maintainers' job is to pinpoint the commit that introduced the issue. + - type: textarea + attributes: + label: Additional context + description: | + Any extra information that might help us investigate. For example, is it only reproducible online, or locally too? Is the issue only happening in a specific browser? etc. + placeholder: | + I tested my reproduction against development branch. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..a4d03e5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Ask a question or discuss a topic + url: https://github.com/darklight9811/sharedway/discussions + about: Ask questions or discuss with other contributors in discussions. + - name: Feature or documentation request + url: https://github.com/darklight9811/sharedway/discussions/new?category=ideas + about: Open a feature request in discussions. \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE/feature_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md similarity index 99% rename from .github/PULL_REQUEST_TEMPLATE/feature_template.md rename to .github/PULL_REQUEST_TEMPLATE/pull_request_template.md index f1db424..448c3c0 100644 --- a/.github/PULL_REQUEST_TEMPLATE/feature_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -9,7 +9,6 @@ Please include a summary of the change and/or which issue is fixed. List any dependencies required for this change, if there are any. 📛📛 --> - --- ### **Additional context** diff --git a/SECURITY.md b/.github/SECURITY.md similarity index 100% rename from SECURITY.md rename to .github/SECURITY.md diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index dc8fc29..b6de14d 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -65,6 +65,39 @@ jobs: - name: Run tests run: bun run test --filter=@repo/env + envs-production: + name: Check production env integrity + runs-on: ubuntu-latest + environment: Production + steps: + - name: Check out code + uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v1 + - name: Install dependencies + run: bun install + + - name: Run tests + run: bun run test --filter=@repo/env + + - name: Run type tests + run: bun run test:type + + envs-preview: + name: Check preview env integrity + runs-on: ubuntu-latest + environment: Preview + steps: + - name: Check out code + uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v1 + - name: Install dependencies + run: bun install + + - name: Run tests + run: bun run test --filter=@repo/env + envs-production: name: Check production env integrity runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index ed55d42..f5a74e5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ node_modules # testing coverage trace +tsconfig.vitest-temp.json # next.js .next/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 1996a4d..2214dff 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -22,5 +22,11 @@ }, "[prisma]": { "editor.defaultFormatter": "Prisma.prisma" + }, + "[jsonc]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome" } } diff --git a/README.md b/README.md index 4f7d16f..8618df7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ + + # Sharedway [![Production](https://img.shields.io/badge/deployment-prod-3a506b?&style=for-the-badge&labelColor=dbf0fd)](https://sharedway.org) @@ -7,6 +9,8 @@ An application to help find missing people and animals. Serving as a central bank (or HUB) for institutions, the government and anyone can access the data. A difference is that it allows you to filter by region, so that you can see missing people or animals in the location with better distinction. + + ## Installation > You will need to have API keys for: clerk, kv, uploadthing and a postgres database diff --git a/apps/app/package.json b/apps/app/package.json index 22c156a..b1400b3 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -14,34 +14,35 @@ "postinstall": "cd ../../ && bun run postinstall" }, "dependencies": { - "@clerk/localizations": "^2.6.0", - "@clerk/nextjs": "^5.3.2", + "@clerk/localizations": "^2.7.1", + "@clerk/nextjs": "^5.3.7", "@react-pdf/renderer": "^3.4.4", "@repo/ds": "1.0.0", "@repo/env": "1.0.0", "@repo/schemas": "1.0.0", "@repo/services": "1.0.0", - "@tanstack/react-query": "^5.52.0", - "@tanstack/react-query-devtools": "^5.52.0", - "@upstash/ratelimit": "^2.0.1", + "@tanstack/react-query": "^5.53.3", + "@tanstack/react-query-devtools": "^5.53.3", + "@upstash/ratelimit": "^2.0.2", "@vercel/analytics": "^1.3.1", - "@vercel/functions": "^1.4.0", + "@vercel/functions": "^1.4.1", "@vercel/kv": "^2.0.0", "@vercel/speed-insights": "^1.0.12", - "lucide-react": "^0.428.0", - "next": "^14.2.5", - "next-intl": "^3.17.4", + "@yamiassu/shared": "*", + "lucide-react": "^0.438.0", + "next": "^14.2.7", + "next-intl": "^3.19.0", "react": "^18.3.1", "react-dom": "^18.3.1", "zod": "^3.23.8" }, "devDependencies": { "@repo/config": "0.0.0", - "@types/node": "^20.16.1", - "@types/react": "^18.3.4", + "@types/node": "^22.5.2", + "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", "autoprefixer": "^10.4.20", - "postcss": "^8.4.41", + "postcss": "^8.4.44", "tailwindcss": "^3.4.10", "typescript": "^5.5.4" } diff --git a/apps/app/src/app/(app)/profiles/new/page.tsx b/apps/app/src/app/(app)/profiles/new/page.tsx index 711cd52..4249bc0 100644 --- a/apps/app/src/app/(app)/profiles/new/page.tsx +++ b/apps/app/src/app/(app)/profiles/new/page.tsx @@ -60,7 +60,7 @@ export default function Page() { {t("create-title")} - + {t("back")} diff --git a/apps/app/src/i18n.ts b/apps/app/src/i18n.ts index 1066ba8..4f55930 100644 --- a/apps/app/src/i18n.ts +++ b/apps/app/src/i18n.ts @@ -9,7 +9,9 @@ export const localePrefix = "always"; export default getRequestConfig(async () => { // Validate that the incoming `locale` parameter is valid - const locale = getLocaleContent(headers().get("Accept-Language")); + const locale = getLocaleContent( + headers().get("Accept-Language") || locales[0], + ); if (!locale) return notFound(); diff --git a/apps/app/src/lib/api.ts b/apps/app/src/lib/api.ts index 69232c9..f51c6ac 100644 --- a/apps/app/src/lib/api.ts +++ b/apps/app/src/lib/api.ts @@ -1,7 +1,15 @@ -import createApi from "@repo/services/api"; +import type Metadata from "@repo/services/types/metadata"; +import { createApi } from "@yamiassu/shared/js"; +import type { Prettify } from "@yamiassu/shared/types"; +import { buildMetadata } from "./parallel"; -const api = createApi({ - bind: {}, -}); +const api = createApi({}); + +export function apiService( + cb: (input: Input) => (metadata: Metadata) => Output, +) { + return async (ctx: { input: Input }): Promise> => + cb(ctx.input)(await buildMetadata()); +} export default api; diff --git a/apps/app/src/middleware.ts b/apps/app/src/middleware.ts index 22ab3ce..29f017c 100644 --- a/apps/app/src/middleware.ts +++ b/apps/app/src/middleware.ts @@ -48,11 +48,13 @@ const clerk = clerkMiddleware( // assets are always public and not internacionalized if (isAssetRoute(req)) return NextResponse.next(); - const { success } = await ratelimit.limit(ip); + if (process.env.NODE_ENV === "production") { + const { success } = await ratelimit.limit(ip); - // make sure the user is not rate limited or not in the rate limit screen - if (!success && !req.nextUrl.pathname.includes("/block")) - return NextResponse.redirect(new URL("/block", req.url)); + // make sure the user is not rate limited or not in the rate limit screen + if (!success && !req.nextUrl.pathname.includes("/block")) + return NextResponse.redirect(new URL("/block", req.url)); + } // make sure the user is authenticated if (isProtectedRoute(req)) auth().protect(); diff --git a/apps/app/src/modules/location/actions.ts b/apps/app/src/modules/location/actions.ts index 635d3e2..80a6c12 100644 --- a/apps/app/src/modules/location/actions.ts +++ b/apps/app/src/modules/location/actions.ts @@ -1,10 +1,9 @@ "use server"; -import api from "@/lib/api"; -import { buildMetadata } from "@/lib/parallel"; +import api, { apiService } from "@/lib/api"; import pagination from "@repo/schemas/pagination"; import locationService from "@repo/services/location"; export const states = api .zod(pagination) - .service(locationService.state, buildMetadata); + .action(apiService(locationService.state)); diff --git a/apps/app/src/modules/profile/actions.ts b/apps/app/src/modules/profile/actions.ts index 381915a..90e80f4 100644 --- a/apps/app/src/modules/profile/actions.ts +++ b/apps/app/src/modules/profile/actions.ts @@ -1,7 +1,6 @@ "use server"; -import api from "@/lib/api"; -import { buildMetadata } from "@/lib/parallel"; +import api, { apiService } from "@/lib/api"; import pagination from "@repo/schemas/pagination"; import { profileStoreSchema, profileUpdateSchema } from "@repo/schemas/profile"; import profileService from "@repo/services/profile"; @@ -9,25 +8,25 @@ import { z } from "zod"; export const index = api .zod(pagination) - .service(profileService.index, buildMetadata); + .action(apiService(profileService.index)); export const store = api .zod(profileStoreSchema) - .service(profileService.store, buildMetadata) - .action(async ({ input }: any) => ({ - redirect: `/profiles/${input.id}`, + .action(apiService(profileService.store)) + .action(async ({ input }) => ({ + redirect: `/profiles/${input!.id}`, })); export const update = api .zod(z.object({ id: z.string().cuid(), data: profileUpdateSchema })) - .service(profileService.update, buildMetadata) + .action(apiService(profileService.update)) .action(async () => ({ reload: true, })); export const remove = api .zod(z.string()) - .service(profileService.delete, buildMetadata) + .action(apiService(profileService.delete)) .action(async () => ({ redirect: "/", message: "Apagado com sucesso", diff --git a/apps/app/src/modules/profile/components/profile-form.contact.tsx b/apps/app/src/modules/profile/components/profile-form.contact.tsx new file mode 100644 index 0000000..d1f14fc --- /dev/null +++ b/apps/app/src/modules/profile/components/profile-form.contact.tsx @@ -0,0 +1,83 @@ +"use client"; + +import Field from "@repo/ds/form/field"; +import FieldList from "@repo/ds/form/field-list"; +import { Button } from "@repo/ds/ui/button"; +import { Input } from "@repo/ds/ui/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@repo/ds/ui/select"; +import { TabsContent } from "@repo/ds/ui/tabs"; +import { Textarea } from "@repo/ds/ui/textarea"; +import { Trash } from "lucide-react"; +import { useTranslations } from "next-intl"; + +export default function ProfileFormContact() { + const t = useTranslations("profiles.new"); + + return ( + +

{t("contact.title")}

+ + ( +
+ ( + + )} + /> + } + /> + +
+ )} + /> + + { + return