diff --git a/.env.example b/.env.example index d281c1d..ed83241 100644 --- a/.env.example +++ b/.env.example @@ -6,7 +6,7 @@ TZ=America/Edmonton # For homelab server, change the following to your server ip ex: http://192.168.x.x:3000 -NEXTAUTH_URL=http://localhost:3000 +NEXTAUTH_URL=http://localhost:3737 # AUTH_SECRET is auto-generated by deploy.sh and docker-entrypoint.sh # To set manually, uncomment and provide your own value: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ef02864 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: CI + +on: + pull_request: + branches: [dev, main] + +jobs: + ci: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "npm" + + - run: npm ci + + - run: npx prisma generate + + - run: npm run lint + + - run: npm test diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml new file mode 100644 index 0000000..4f990bd --- /dev/null +++ b/.github/workflows/docker-release.yml @@ -0,0 +1,56 @@ +name: Docker Release + +on: + push: + tags: + - "v*.*.*" + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +permissions: + contents: read + packages: write + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=raw,value=latest + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..a062011 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,23 @@ +name: release-please + +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + outputs: + release_created: ${{ steps.release.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + steps: + - uses: googleapis/release-please-action@v4 + id: release + with: + release-type: node + target-branch: main diff --git a/.gitignore b/.gitignore index a8c23d8..384c7b9 100644 --- a/.gitignore +++ b/.gitignore @@ -47,7 +47,8 @@ dev.db-journal data/files/resumes CLAUDE.md /docs -.github +.github/* +!.github/workflows .claude .specify /specs diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6dbeebd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,36 @@ +# Changelog + +## 1.0.0 (2026-02-28) + + +### Features + +* add release automation ([6fd8247](https://github.com/Gsync/jobsync/commit/6fd8247f836208d61eddae935c4cbd63fac36cde)) + + +### Bug Fixes + +* Add job draft date in job details ([f6c2bb6](https://github.com/Gsync/jobsync/commit/f6c2bb65f14364f1292ecccf66c4f2999ba5cfc6)) +* Admin tab swich ([8c57052](https://github.com/Gsync/jobsync/commit/8c5705297c643a13c9d00da34a45d7d85f785f23)) +* bullet and order styling of editor content ([423b0f4](https://github.com/Gsync/jobsync/commit/423b0f43d0cfff76e1522864bd1b5177773692fb)) +* button hydration error ([d7e97a0](https://github.com/Gsync/jobsync/commit/d7e97a014e2d41ccdb1cd77d6baa0b6975576f4b)) +* Combobox filter issue ([1ab477e](https://github.com/Gsync/jobsync/commit/1ab477eb6e64f0aab7da360fcc936897217583e5)) +* Combobox undefined error ([fdaa9fe](https://github.com/Gsync/jobsync/commit/fdaa9fe72c35695136871a8e92fb5311af52a476)) +* configure release-please to target dev branch ([9ca7db0](https://github.com/Gsync/jobsync/commit/9ca7db003a5fb2d0ef4484a223aa7511eb84c08b)) +* Create company bug when adding experience ([c992077](https://github.com/Gsync/jobsync/commit/c99207744f8f038ad490d10dba581dba8c13d960)) +* DatePicker bug in Safari browser ([0f24106](https://github.com/Gsync/jobsync/commit/0f24106ebe5fabbd65336e2de128a623d3406099)) +* Dialog scroll ([93f8e7d](https://github.com/Gsync/jobsync/commit/93f8e7dbec477b14c924ea0f819283c9a1f142f0)) +* Edit company ([d7a15e2](https://github.com/Gsync/jobsync/commit/d7a15e293345e8097a43e9e4128b1e5a07ff024b)) +* Error accessing ollama api endpoint in docker ([83aa24a](https://github.com/Gsync/jobsync/commit/83aa24a5ec8f503c1f2c758e4fb5ec5d2506bcc4)) +* Failing Tasks playwright tests ([4c2cecf](https://github.com/Gsync/jobsync/commit/4c2cecf95c77106b7f6fafd2ded8ca4c16822d9c)) +* hydration error, minor refactor ([6d2db31](https://github.com/Gsync/jobsync/commit/6d2db31ebde9ee6afc426f8ece397145becfe731)) +* job status undefined issue ([91d3097](https://github.com/Gsync/jobsync/commit/91d309762d87f863ffd481b6c720b91ee8e21c5a)) +* jobsApplied based on applied field ([d0ad166](https://github.com/Gsync/jobsync/commit/d0ad166a291477bd53663d59165a40bc6af203cb)) +* login error validation ([7df090a](https://github.com/Gsync/jobsync/commit/7df090a6b899b89394d29722f7f247730b2b8713)) +* minor layout issues ([55e1e42](https://github.com/Gsync/jobsync/commit/55e1e42d38e26c74ff675f0a761cabe40cde7cb2)) +* no matching decryption secret ([b8f3919](https://github.com/Gsync/jobsync/commit/b8f3919cc5fa39d241b034639c73684c3284e34d)) +* openssl not found ([290a1a7](https://github.com/Gsync/jobsync/commit/290a1a7b6ba54968ba19ebd0c41a378bbd8b1fa0)) +* resume undefined issue ([dbe01a9](https://github.com/Gsync/jobsync/commit/dbe01a91ede0a378dd9678c44ac73823339e4546)) +* Revalidate company list in addjob when adding company ([785c49b](https://github.com/Gsync/jobsync/commit/785c49b92ef6459fdb9d77045795108d78d26c65)) +* route path ([4234c08](https://github.com/Gsync/jobsync/commit/4234c0808d83871bffb1d2d54a2205a244133771)) +* session based conditional rendering ([b008e1b](https://github.com/Gsync/jobsync/commit/b008e1b7efa0912db5512b33561295b4c59b0c4d)) diff --git a/README.md b/README.md index 8389073..88af451 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ cd jobsync docker compose up ``` -Open [http://localhost:3000](http://localhost:3000) and create your account. That's it! +Open [http://localhost:3737](http://localhost:3737) and create your account. That's it! API keys for AI providers can be configured in **Settings** after signing in. diff --git a/__tests__/AddCompany.spec.tsx b/__tests__/AddCompany.spec.tsx index bfa4e0f..9262911 100644 --- a/__tests__/AddCompany.spec.tsx +++ b/__tests__/AddCompany.spec.tsx @@ -27,7 +27,7 @@ describe("AddCompany Component", () => { />, ); expect( - screen.getByRole("button", { name: /add company/i }), + screen.getByRole("button", { name: /new company/i }), ).toBeInTheDocument(); }); @@ -41,7 +41,7 @@ describe("AddCompany Component", () => { />, ); const addCompanyButton = screen.getByRole("button", { - name: /add company/i, + name: /new company/i, }); fireEvent.click(addCompanyButton); diff --git a/__tests__/ProfileContainer.spec.tsx b/__tests__/ProfileContainer.spec.tsx index fa34690..45cf6f5 100644 --- a/__tests__/ProfileContainer.spec.tsx +++ b/__tests__/ProfileContainer.spec.tsx @@ -10,7 +10,7 @@ jest.mock("@/actions/profile.actions", () => ({ total: 0, success: true, message: "", - }) + }), ), })); @@ -31,7 +31,7 @@ describe("ProfileContainer Component", () => { it("should open the create resume dialog upon clicking create resume button", async () => { const createResumeButton = screen.getByRole("button", { - name: /create resume/i, + name: /new resume/i, }); await act(async () => { fireEvent.click(createResumeButton); @@ -39,7 +39,7 @@ describe("ProfileContainer Component", () => { expect(screen.getByRole("dialog")).toBeInTheDocument(); expect( - screen.getByRole("heading", { level: 2, name: /create resume/i }) + screen.getByRole("heading", { level: 2, name: /create resume/i }), ).toBeInTheDocument(); }); }); diff --git a/__tests__/dashboard.actions.spec.ts b/__tests__/dashboard.actions.spec.ts index 4b17623..6763047 100644 --- a/__tests__/dashboard.actions.spec.ts +++ b/__tests__/dashboard.actions.spec.ts @@ -5,6 +5,7 @@ import { getJobsActivityForPeriod, getActivityCalendarData, } from "@/actions/dashboard.actions"; +import { APP_CONSTANTS } from "@/lib/constants"; import { getCurrentUser } from "@/utils/user.utils"; import { PrismaClient } from "@prisma/client"; @@ -52,7 +53,7 @@ describe("Dashboard Actions", () => { (getCurrentUser as jest.Mock).mockResolvedValue(null); await expect(getJobsAppliedForPeriod(7)).rejects.toThrow( - "Not authenticated" + "Not authenticated", ); }); @@ -68,11 +69,11 @@ describe("Dashboard Actions", () => { it("should handle database errors", async () => { (getCurrentUser as jest.Mock).mockResolvedValue(mockUser); (prisma.$transaction as jest.Mock).mockRejectedValue( - new Error("Database error") + new Error("Database error"), ); await expect(getJobsAppliedForPeriod(7)).rejects.toThrow( - "Failed to calculate job count" + "Failed to calculate job count", ); }); }); @@ -114,7 +115,7 @@ describe("Dashboard Actions", () => { orderBy: { appliedDate: "desc", }, - take: 6, + take: APP_CONSTANTS.RECENT_NUM_JOBS_ACTIVITIES, }); }); @@ -122,18 +123,18 @@ describe("Dashboard Actions", () => { (getCurrentUser as jest.Mock).mockResolvedValue(null); await expect(getRecentJobs()).rejects.toThrow( - "Failed to fetch jobs list. " + "Failed to fetch jobs list. ", ); }); it("should handle database errors", async () => { (getCurrentUser as jest.Mock).mockResolvedValue(mockUser); (prisma.job.findMany as jest.Mock).mockRejectedValue( - new Error("Database error") + new Error("Database error"), ); await expect(getRecentJobs()).rejects.toThrow( - "Failed to fetch jobs list. " + "Failed to fetch jobs list. ", ); }); @@ -176,18 +177,18 @@ describe("Dashboard Actions", () => { (getCurrentUser as jest.Mock).mockResolvedValue(null); await expect(getActivityDataForPeriod()).rejects.toThrow( - "Failed to fetch activities data." + "Failed to fetch activities data.", ); }); it("should handle database errors", async () => { (getCurrentUser as jest.Mock).mockResolvedValue(mockUser); (prisma.activity.findMany as jest.Mock).mockRejectedValue( - new Error("Database error") + new Error("Database error"), ); await expect(getActivityDataForPeriod()).rejects.toThrow( - "Failed to fetch activities data." + "Failed to fetch activities data.", ); }); @@ -251,18 +252,18 @@ describe("Dashboard Actions", () => { (getCurrentUser as jest.Mock).mockResolvedValue(null); await expect(getJobsActivityForPeriod()).rejects.toThrow( - "Failed to fetch jobs list. " + "Failed to fetch jobs list. ", ); }); it("should handle database errors", async () => { (getCurrentUser as jest.Mock).mockResolvedValue(mockUser); (prisma.job.groupBy as jest.Mock).mockRejectedValue( - new Error("Database error") + new Error("Database error"), ); await expect(getJobsActivityForPeriod()).rejects.toThrow( - "Failed to fetch jobs list. " + "Failed to fetch jobs list. ", ); }); @@ -308,18 +309,18 @@ describe("Dashboard Actions", () => { (getCurrentUser as jest.Mock).mockResolvedValue(null); await expect(getActivityCalendarData()).rejects.toThrow( - "Failed to fetch jobs list. " + "Failed to fetch jobs list. ", ); }); it("should handle database errors", async () => { (getCurrentUser as jest.Mock).mockResolvedValue(mockUser); (prisma.job.groupBy as jest.Mock).mockRejectedValue( - new Error("Database error") + new Error("Database error"), ); await expect(getActivityCalendarData()).rejects.toThrow( - "Failed to fetch jobs list. " + "Failed to fetch jobs list. ", ); }); diff --git a/docker-compose.yml b/docker-compose.yml index 8aeac49..5f5cdde 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,17 +1,15 @@ services: app: + image: ghcr.io/gsync/jobsync:latest container_name: jobsync_app - build: - context: . - dockerfile: Dockerfile ports: - - "3000:3000" + - "3737:3000" environment: - NODE_ENV=production - DATABASE_URL=file:/data/dev.db - AUTH_SECRET=${AUTH_SECRET:-} - - ENCRYPTION_KEY=you-encryption-key-here - - NEXTAUTH_URL=${NEXTAUTH_URL:-http://localhost:3000} + - ENCRYPTION_KEY=${ENCRYPTION_KEY:-you-encryption-key-here} + - NEXTAUTH_URL=${NEXTAUTH_URL:-http://localhost:3737} - AUTH_TRUST_HOST=${AUTH_TRUST_HOST:-true} - TZ=${TZ:-America/Edmonton} - OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434} @@ -21,3 +19,9 @@ services: volumes: - ./jobsyncdb/data:/data restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://localhost:3737"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s diff --git a/e2e/add-job.spec.ts b/e2e/add-job.spec.ts index 31f8a4b..b884794 100644 --- a/e2e/add-job.spec.ts +++ b/e2e/add-job.spec.ts @@ -19,7 +19,7 @@ async function createNewJob(page: Page, jobText: string) { const companyText = `company ${suffix}`; const locationText = `location ${suffix}`; - await page.getByRole("button", { name: "Add New Job" }).click(); + await page.getByRole("button", { name: "New Job" }).click(); await expect(page).toHaveURL("/dashboard/myjobs"); await page.getByTestId("add-job-btn").click(); @@ -111,7 +111,7 @@ test.describe("Add New Job", () => { test("should allow me to add a new job", async ({ page }) => { await createNewJob(page, jobText); await expect( - page.getByRole("row", { name: jobText }).first() + page.getByRole("row", { name: jobText }).first(), ).toBeVisible(); await deleteJob(page, jobText); }); @@ -129,16 +129,16 @@ test.describe("Add New Job", () => { .click(); await page.getByRole("menuitem", { name: "Edit Job" }).click(); await expect( - page.getByPlaceholder("Copy and paste job link here") + page.getByPlaceholder("Copy and paste job link here"), ).toHaveValue("www.google.com"); await expect(page.getByLabel("Job Title")).toContainText( - "developer test title" + "developer test title", ); await expect(page.getByLabel("Company")).toContainText( - `company ${jobText.replace(/\s+/g, "-")}` + `company ${jobText.replace(/\s+/g, "-")}`, ); await expect(page.getByLabel("Job Location")).toContainText( - `location ${jobText.replace(/\s+/g, "-")}` + `location ${jobText.replace(/\s+/g, "-")}`, ); await expect(page.getByLabel("Job Source")).toContainText("Indeed"); await expect(page.getByLabel("Select Job Status")).toContainText("Draft"); @@ -150,7 +150,7 @@ test.describe("Add New Job", () => { .fill("test description edited"); await page.getByTestId("save-job-btn").click(); await expect(page.getByRole("status").first()).toContainText( - /Job has been updated/ + /Job has been updated/, ); await deleteJob(page, jobText); }); diff --git a/e2e/profile.spec.ts b/e2e/profile.spec.ts index f56375a..03f6079 100644 --- a/e2e/profile.spec.ts +++ b/e2e/profile.spec.ts @@ -12,7 +12,7 @@ test.beforeEach(async ({ page, baseURL }) => { }); async function createResume(page: Page, title: string) { - await page.getByRole("button", { name: "Create Resume" }).click(); + await page.getByRole("button", { name: "New Resume" }).click(); await page.getByPlaceholder("Ex: Full Stack Developer").fill(title); await page.getByRole("button", { name: "Save" }).click(); } @@ -204,7 +204,12 @@ test.describe("Profile page", () => { await page.getByPlaceholder("Ex: Stanford").click(); await page.getByPlaceholder("Ex: Stanford").fill("test school"); const locationText = "location test"; - await selectOrCreateComboboxOption(page, "Location", "Create or Search location", locationText); + await selectOrCreateComboboxOption( + page, + "Location", + "Create or Search location", + locationText, + ); await expect(page.getByLabel("Location")).toContainText(locationText); await page.getByPlaceholder("Ex: Bachelor's").click(); await page.getByPlaceholder("Ex: Bachelor's").fill("degree text"); @@ -260,13 +265,28 @@ async function addExperience(page: Page, resumeTitle: string, jobText: string) { await sectionTitleField.fill("Experience"); await sectionTitleField.press("Tab"); } - await selectOrCreateComboboxOption(page, "Job Title", "Create or Search title", jobText); + await selectOrCreateComboboxOption( + page, + "Job Title", + "Create or Search title", + jobText, + ); await expect(page.getByLabel("Job Title")).toContainText(jobText); const companyText = "company test"; - await selectOrCreateComboboxOption(page, "Company", "Create or Search company", companyText); + await selectOrCreateComboboxOption( + page, + "Company", + "Create or Search company", + companyText, + ); await expect(page.getByLabel("Company")).toContainText(companyText); const locationText = "location test"; - await selectOrCreateComboboxOption(page, "Job Location", "Create or Search location", locationText); + await selectOrCreateComboboxOption( + page, + "Job Location", + "Create or Search location", + locationText, + ); await expect(page.getByLabel("Job Location")).toContainText(locationText); await page.getByLabel("Start Date").click(); // Wait for calendar popover to open diff --git a/package-lock.json b/package-lock.json index 347254e..baff350 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jobsync", - "version": "0.2.3", + "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jobsync", - "version": "0.2.3", + "version": "1.0.0", "dependencies": { "@ai-sdk/deepseek": "^2.0.4", "@ai-sdk/openai": "^3.0.2", diff --git a/package.json b/package.json index bd2f702..94867e7 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "jobsync", - "version": "0.2.4", + "version": "1.0.0", "private": true, "scripts": { - "dev": "next dev --turbopack -p 3000", + "dev": "next dev --turbopack -p 3737", "build": "next build", "start": "next start", "lint": "next lint", -"test": "jest", + "test": "jest", "test:e2e": "npx playwright test", "test:watch": "jest --watch" }, diff --git a/playwright.config.ts b/playwright.config.ts index 16ed09a..849a465 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -25,7 +25,7 @@ export default defineConfig({ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: "http://localhost:3000", + baseURL: "http://localhost:3737", /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: "on-first-retry", @@ -72,7 +72,7 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ webServer: { command: "npm run dev", - url: "http://localhost:3000", + url: "http://localhost:3737", reuseExistingServer: true, timeout: 120 * 1000, }, diff --git a/src/actions/dashboard.actions.ts b/src/actions/dashboard.actions.ts index 5a6060d..ff3007c 100644 --- a/src/actions/dashboard.actions.ts +++ b/src/actions/dashboard.actions.ts @@ -1,3 +1,4 @@ +import { APP_CONSTANTS } from "@/lib/constants"; import prisma from "@/lib/db"; import { calculatePercentageDifference, getLast7Days } from "@/lib/utils"; import { getCurrentUser } from "@/utils/user.utils"; @@ -64,7 +65,7 @@ export const getRecentJobs = async (): Promise => { orderBy: { appliedDate: "desc", }, - take: 6, + take: APP_CONSTANTS.RECENT_NUM_JOBS_ACTIVITIES, }); return list; } catch (error) { @@ -312,7 +313,7 @@ export const getRecentActivities = async () => { orderBy: { endTime: "desc", }, - take: 6, + take: APP_CONSTANTS.RECENT_NUM_JOBS_ACTIVITIES, }); return list; } catch (error) { diff --git a/src/app/dashboard/automations/[id]/page.tsx b/src/app/dashboard/automations/[id]/page.tsx index d17d147..2e13082 100644 --- a/src/app/dashboard/automations/[id]/page.tsx +++ b/src/app/dashboard/automations/[id]/page.tsx @@ -233,6 +233,7 @@ export default function AutomationDetailPage() { {automation.status === "active" ? "Pause" : "Resume"} @@ -183,7 +183,11 @@ function ActivitiesContainer() { size="sm" variant="outline" onClick={() => - loadActivities(page + 1, recordsPerPage, searchTerm || undefined) + loadActivities( + page + 1, + recordsPerPage, + searchTerm || undefined, + ) } disabled={loading} className="btn btn-primary" diff --git a/src/components/admin/AddCompany.tsx b/src/components/admin/AddCompany.tsx index e01b572..0b07d46 100644 --- a/src/components/admin/AddCompany.tsx +++ b/src/components/admin/AddCompany.tsx @@ -118,7 +118,7 @@ function AddCompany({ > - Add Company + New Company diff --git a/src/components/automations/AutomationContainer.tsx b/src/components/automations/AutomationContainer.tsx index c9fa8c1..bcfe4c7 100644 --- a/src/components/automations/AutomationContainer.tsx +++ b/src/components/automations/AutomationContainer.tsx @@ -24,7 +24,8 @@ export function AutomationContainer({ resumes }: AutomationContainerProps) { const [automations, setAutomations] = useState([]); const [loading, setLoading] = useState(true); const [wizardOpen, setWizardOpen] = useState(false); - const [editAutomation, setEditAutomation] = useState(null); + const [editAutomation, setEditAutomation] = + useState(null); const loadAutomations = useCallback(async () => { setLoading(true); @@ -71,7 +72,11 @@ export function AutomationContainer({ resumes }: AutomationContainerProps) { - diff --git a/src/components/dashboard/JobsAppliedCard.tsx b/src/components/dashboard/JobsAppliedCard.tsx index 8810eec..7414356 100644 --- a/src/components/dashboard/JobsAppliedCard.tsx +++ b/src/components/dashboard/JobsAppliedCard.tsx @@ -26,18 +26,14 @@ export default function JobsAppliedCard() { onClick={() => router.push("/dashboard/myjobs")} > - - Add New Job - + New Job diff --git a/src/components/myjobs/AddJob.tsx b/src/components/myjobs/AddJob.tsx index 78573c7..ef2a503 100644 --- a/src/components/myjobs/AddJob.tsx +++ b/src/components/myjobs/AddJob.tsx @@ -189,7 +189,7 @@ export function AddJob({ > - Add Job + New Job diff --git a/src/components/profile/ProfileContainer.tsx b/src/components/profile/ProfileContainer.tsx index 41d7baa..2e94ef8 100644 --- a/src/components/profile/ProfileContainer.tsx +++ b/src/components/profile/ProfileContainer.tsx @@ -30,7 +30,7 @@ const ProfileContainer = () => { setLoading(true); const { data, total, success, message } = await getResumeList( page, - recordsPerPage + recordsPerPage, ); if (success && data) { setResumes((prev) => (page === 1 ? data : [...prev, ...data])); @@ -46,7 +46,7 @@ const ProfileContainer = () => { }); } }, - [recordsPerPage] + [recordsPerPage], ); const reloadResumes = useCallback(async () => { @@ -87,7 +87,7 @@ const ProfileContainer = () => { > - Create Resume + New Resume { + async ( + pageNum: number, + filter?: string, + statuses?: TaskStatus[], + search?: string, + ) => { setLoading(true); const { success, data, total, message } = await getTasksList( pageNum, @@ -204,7 +209,8 @@ function TasksContainer({ }; useEffect(() => { - (async () => await loadTasks(1, filterKey, statusFilter, searchTerm || undefined))(); + (async () => + await loadTasks(1, filterKey, statusFilter, searchTerm || undefined))(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [loadTasks, filterKey, statusFilter, recordsPerPage]); @@ -306,12 +312,18 @@ function TasksContainer({ Created Date Due Date Updated Date - Activity Type + + Activity Type + ) : ( - @@ -325,7 +337,7 @@ function TasksContainer({ > - Add Task + New Task @@ -368,7 +380,14 @@ function TasksContainer({