Add : app/(application)/(user)/job/[id]/

Fix:
-  app/(application)/(user)/job/(tabs)/archive.tsx
-  app/(application)/(user)/job/(tabs)/index.tsx
-  app/(application)/(user)/job/(tabs)/status.tsx
-  app/(application)/(user)/job/create.tsx

Package:
Add: expo-clipboard

# No Issue
This commit is contained in:
2025-07-25 14:19:57 +08:00
parent 7528c449eb
commit 1b1732c7d8
9 changed files with 257 additions and 48 deletions

View File

@@ -162,6 +162,13 @@ export default function UserLayout() {
name="job/(tabs)"
options={{
title: "Job Vacancy",
headerLeft: () => <BackButton path="/home" />,
}}
/>
<Stack.Screen
name="job/[id]/index"
options={{
title: "Detail Lowongan Pekerjaan",
headerLeft: () => <BackButton />,
}}
/>

View File

@@ -1,9 +1,16 @@
import { TextCustom, ViewWrapper } from "@/components";
import { BaseBox, TextCustom, ViewWrapper } from "@/components";
import { jobDataDummy } from "@/screens/Job/listDataDummy";
export default function JobArchive() {
return (
<ViewWrapper>
<TextCustom>Job Archive</TextCustom>
{jobDataDummy.map((e, i) => (
<BaseBox key={i} paddingBlock={20}>
<TextCustom align="center" bold truncate size="large">
{e.posisi}
</TextCustom>
</BaseBox>
))}
</ViewWrapper>
);
}

View File

@@ -20,7 +20,7 @@ export default function JobBeranda() {
headerComponent={<SearchInput placeholder="Cari pekerjaan" />}
>
{jobDataDummy.map((item, index) => (
<BoxWithHeaderSection key={index}>
<BoxWithHeaderSection key={index} onPress={() => router.push(`/job/${item.id}`)}>
<AvatarUsernameAndOtherComponent avatarHref={`/profile/${item.id}`} />
<Spacing />
<TextCustom truncate={2} align="center" bold size="large">

View File

@@ -1,9 +1,44 @@
import { TextCustom, ViewWrapper } from "@/components";
import {
BaseBox,
ScrollableCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { masterStatus } from "@/lib/dummy-data/_master/status";
import { jobDataDummy } from "@/screens/Job/listDataDummy";
import { useState } from "react";
export default function JobStatus() {
const [activeCategory, setActiveCategory] = useState<string | null>(
"publish"
);
const handlePress = (item: any) => {
setActiveCategory(item.value);
// tambahkan logika lain seperti filter dsb.
};
const scrollComponent = (
<ScrollableCustom
data={masterStatus.map((e, i) => ({
id: i,
label: e.label,
value: e.value,
}))}
onButtonPress={handlePress}
activeId={activeCategory as any}
/>
);
return (
<ViewWrapper>
<TextCustom>Job Status</TextCustom>
<ViewWrapper headerComponent={scrollComponent} hideFooter>
{jobDataDummy.map((e, i) => (
<BaseBox key={i} paddingBlock={20}>
<TextCustom align="center" bold truncate size="large">
{activeCategory?.toUpperCase()} {e.posisi}
</TextCustom>
</BaseBox>
))}
</ViewWrapper>
);
}

View File

@@ -0,0 +1,95 @@
import {
BaseBox,
ButtonCustom,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
import { jobDataDummy } from "@/screens/Job/listDataDummy";
import { Ionicons } from "@expo/vector-icons";
import { useLocalSearchParams } from "expo-router";
import { Alert, Linking } from "react-native";
import * as Clipboard from "expo-clipboard";
import { MainColor } from "@/constants/color-palet";
export default function JobDetail() {
const { id } = useLocalSearchParams();
const jobDetail = jobDataDummy.find((e) => e.id === Number(id));
const OpenLinkButton = () => {
const jobUrl =
"https://stg-hipmi.wibudev.com/job-vacancy/cm6ijt9w8005zucv4twsct657";
const openInBrowser = async () => {
const supported = await Linking.canOpenURL(jobUrl);
if (supported) {
await Linking.openURL(jobUrl);
} else {
Alert.alert("Gagal membuka link", "Browser tidak tersedia.");
}
};
return (
<ButtonCustom
iconLeft={<Ionicons name="globe" size={ICON_SIZE_SMALL} color="white" />}
onPress={openInBrowser}
backgroundColor="green"
textColor="white"
>
Buka Lowongan di Browser
</ButtonCustom>
);
};
const CopyLinkButton = () => {
const jobUrl =
"https://stg-hipmi.wibudev.com/job-vacancy/cm6ijt9w8005zucv4twsct657";
const copyToClipboard = async () => {
await Clipboard.setStringAsync(jobUrl);
Alert.alert(
"Link disalin",
"Tautan lowongan telah disalin ke clipboard."
);
};
return (
<ButtonCustom
iconLeft={<Ionicons name="copy" size={ICON_SIZE_SMALL} color="white" />}
onPress={copyToClipboard}
backgroundColor={MainColor.orange}
textColor="white"
>
Salin Link
</ButtonCustom>
);
};
return (
<ViewWrapper>
<BaseBox>
<StackCustom gap={"lg"}>
<TextCustom align="center" bold size="large">
{jobDetail?.posisi}
</TextCustom>
<StackCustom gap={"sm"}>
<TextCustom bold>Syarat & Ketentuan :</TextCustom>
<TextCustom>{jobDetail?.syaratKetentuan}</TextCustom>
</StackCustom>
<StackCustom gap={"sm"}>
<TextCustom bold>Deskripsi :</TextCustom>
<TextCustom>{jobDetail?.deskripsi}</TextCustom>
</StackCustom>
</StackCustom>
</BaseBox>
<OpenLinkButton />
<Spacing/>
<CopyLinkButton />
</ViewWrapper>
);
}

View File

@@ -1,9 +1,70 @@
import { TextCustom, ViewWrapper } from "@/components";
import {
ButtonCenteredOnly,
ButtonCustom,
InformationBox,
LandscapeFrameUploaded,
Spacing,
StackCustom,
TextAreaCustom,
TextInputCustom,
ViewWrapper
} from "@/components";
import { router } from "expo-router";
export default function JobCreate() {
const buttonSubmit = () => {
return (
<>
<ButtonCustom
onPress={() =>
router.replace("/(application)/(user)/job/(tabs)/status")
}
>
Simpan
</ButtonCustom>
<Spacing/>
</>
);
};
return (
<ViewWrapper>
<TextCustom>Job Create</TextCustom>
<StackCustom gap={"xs"}>
<InformationBox text="Poster atau gambar lowongan kerja bersifat opsional, tidak wajib untuk dimasukkan dan upload lah gambar yang sesuai dengan deskripsi lowongan kerja." />
<LandscapeFrameUploaded />
<ButtonCenteredOnly onPress={() => console.log("Upload")} icon="upload">
Upload
</ButtonCenteredOnly>
<Spacing />
<TextInputCustom
label="Judul Lowongan"
placeholder="Masukan Judul Lowongan Kerja"
required
/>
<TextAreaCustom
label="Syarat & Kualifikasi"
placeholder="Masukan Syarat & Kualifikasi Lowongan Kerja"
required
showCount
maxLength={1000}
/>
<TextAreaCustom
label="Deskripsi Lowongan"
placeholder="Masukan Deskripsi Lowongan Kerja"
required
showCount
maxLength={1000}
/>
{buttonSubmit()}
</StackCustom>
</ViewWrapper>
);
}